3 Utility functions for expression evaluation.
5 Copyright (c) 2011-2019, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
12 #define gEmptyString L""
14 // Global stack used to evaluate boolean expresions
16 EFI_HII_VALUE
*mOpCodeScopeStack
= NULL
;
17 EFI_HII_VALUE
*mOpCodeScopeStackEnd
= NULL
;
18 EFI_HII_VALUE
*mOpCodeScopeStackPointer
= NULL
;
20 EFI_HII_VALUE
*mExpressionEvaluationStack
= NULL
;
21 EFI_HII_VALUE
*mExpressionEvaluationStackEnd
= NULL
;
22 EFI_HII_VALUE
*mExpressionEvaluationStackPointer
= NULL
;
23 UINTN mExpressionEvaluationStackOffset
= 0;
25 EFI_HII_VALUE
*mCurrentExpressionStack
= NULL
;
26 EFI_HII_VALUE
*mCurrentExpressionEnd
= NULL
;
27 EFI_HII_VALUE
*mCurrentExpressionPointer
= NULL
;
29 EFI_HII_VALUE
*mMapExpressionListStack
= NULL
;
30 EFI_HII_VALUE
*mMapExpressionListEnd
= NULL
;
31 EFI_HII_VALUE
*mMapExpressionListPointer
= NULL
;
34 Get Value for given Name from a NameValue Storage.
36 @param Storage The NameValue Storage.
38 @param Value The retured Value.
40 @retval EFI_SUCCESS Value found for given Name.
41 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
46 IN FORMSET_STORAGE
*Storage
,
52 NAME_VALUE_NODE
*Node
;
56 Link
= GetFirstNode (&Storage
->NameValueListHead
);
57 while (!IsNull (&Storage
->NameValueListHead
, Link
)) {
58 Node
= NAME_VALUE_NODE_FROM_LINK (Link
);
60 if (FceStrCmp (Name
, Node
->Name
) == 0) {
61 NewStringCpy (Value
, Node
->EditValue
);
65 Link
= GetNextNode (&Storage
->NameValueListHead
, Link
);
72 Grow size of the stack.
74 This is an internal function.
76 @param Stack On input: old stack; On output: new stack
77 @param StackPtr On input: old stack pointer; On output: new stack
79 @param StackEnd On input: old stack end; On output: new stack end
81 @retval EFI_SUCCESS Grow stack success.
82 @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.
87 IN OUT EFI_HII_VALUE
**Stack
,
88 IN OUT EFI_HII_VALUE
**StackPtr
,
89 IN OUT EFI_HII_VALUE
**StackEnd
93 EFI_HII_VALUE
*NewStack
;
95 Size
= EXPRESSION_STACK_SIZE_INCREMENT
;
96 if (*StackPtr
!= NULL
) {
97 Size
= Size
+ (*StackEnd
- *Stack
);
100 NewStack
= AllocatePool (Size
* sizeof (EFI_HII_VALUE
));
101 if (NewStack
== NULL
) {
102 return EFI_OUT_OF_RESOURCES
;
105 if (*StackPtr
!= NULL
) {
107 // Copy from Old Stack to the New Stack
112 (*StackEnd
- *Stack
) * sizeof (EFI_HII_VALUE
)
116 // Free The Old Stack
122 // Make the Stack pointer point to the old data in the new stack
124 *StackPtr
= NewStack
+ (*StackPtr
- *Stack
);
126 *StackEnd
= NewStack
+ Size
;
133 Push an element onto the Boolean Stack.
135 @param Stack On input: old stack; On output: new stack
136 @param StackPtr On input: old stack pointer; On output: new stack
138 @param StackEnd On input: old stack end; On output: new stack end
139 @param Data Data to push.
141 @retval EFI_SUCCESS Push stack success.
146 IN OUT EFI_HII_VALUE
**Stack
,
147 IN OUT EFI_HII_VALUE
**StackPtr
,
148 IN OUT EFI_HII_VALUE
**StackEnd
,
149 IN EFI_HII_VALUE
*Data
155 // Check for a stack overflow condition
157 if (*StackPtr
>= *StackEnd
) {
161 Status
= GrowStack (Stack
, StackPtr
, StackEnd
);
162 if (EFI_ERROR (Status
)) {
168 // Push the item onto the stack
170 CopyMem (*StackPtr
, Data
, sizeof (EFI_HII_VALUE
));
171 *StackPtr
= *StackPtr
+ 1;
178 Pop an element from the stack.
180 @param Stack On input: old stack
181 @param StackPtr On input: old stack pointer; On output: new stack pointer
182 @param Data Data to pop.
184 @retval EFI_SUCCESS The value was popped onto the stack.
185 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
190 IN EFI_HII_VALUE
*Stack
,
191 IN OUT EFI_HII_VALUE
**StackPtr
,
192 OUT EFI_HII_VALUE
*Data
196 // Check for a stack underflow condition
198 if (*StackPtr
== Stack
) {
199 return EFI_ACCESS_DENIED
;
203 // Pop the item off the stack
205 *StackPtr
= *StackPtr
- 1;
206 CopyMem (Data
, *StackPtr
, sizeof (EFI_HII_VALUE
));
212 Reset stack pointer to begin of the stack.
216 ResetCurrentExpressionStack (
220 mCurrentExpressionPointer
= mCurrentExpressionStack
;
225 Push current expression onto the Stack
227 @param Pointer Pointer to current expression.
229 @retval EFI_SUCCESS The value was pushed onto the stack.
230 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
234 PushCurrentExpression (
240 Data
.Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
241 Data
.Value
.u64
= (UINT64
) (UINTN
) Pointer
;
244 &mCurrentExpressionStack
,
245 &mCurrentExpressionPointer
,
246 &mCurrentExpressionEnd
,
253 Pop current expression from the Stack
255 @param Pointer Pointer to current expression to be pop.
257 @retval EFI_SUCCESS The value was pushed onto the stack.
258 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
262 PopCurrentExpression (
270 mCurrentExpressionStack
,
271 &mCurrentExpressionPointer
,
275 *Pointer
= (VOID
*) (UINTN
) Data
.Value
.u64
;
281 Reset stack pointer to begin of the stack.
285 ResetMapExpressionListStack (
289 mMapExpressionListPointer
= mMapExpressionListStack
;
294 Push the list of map expression onto the Stack
296 @param Pointer Pointer to the list of map expression to be pushed.
298 @retval EFI_SUCCESS The value was pushed onto the stack.
299 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
303 PushMapExpressionList (
309 Data
.Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
310 Data
.Value
.u64
= (UINT64
) (UINTN
) Pointer
;
313 &mMapExpressionListStack
,
314 &mMapExpressionListPointer
,
315 &mMapExpressionListEnd
,
322 Pop the list of map expression from the Stack
324 @param Pointer Pointer to the list of map expression to be pop.
326 @retval EFI_SUCCESS The value was pushed onto the stack.
327 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
331 PopMapExpressionList (
339 mMapExpressionListStack
,
340 &mMapExpressionListPointer
,
344 *Pointer
= (VOID
*) (UINTN
) Data
.Value
.u64
;
350 Reset stack pointer to begin of the stack.
358 mOpCodeScopeStackPointer
= mOpCodeScopeStack
;
363 Push an Operand onto the Stack
365 @param Operand Operand to push.
367 @retval EFI_SUCCESS The value was pushed onto the stack.
368 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
379 Data
.Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
380 Data
.Value
.u8
= Operand
;
384 &mOpCodeScopeStackPointer
,
385 &mOpCodeScopeStackEnd
,
392 Pop an Operand from the Stack
394 @param Operand Operand to pop.
396 @retval EFI_SUCCESS The value was pushed onto the stack.
397 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
411 &mOpCodeScopeStackPointer
,
415 *Operand
= Data
.Value
.u8
;
422 Push an Expression value onto the Stack
424 @param Value Expression value to push.
426 @retval EFI_SUCCESS The value was pushed onto the stack.
427 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
433 IN EFI_HII_VALUE
*Value
437 &mExpressionEvaluationStack
,
438 &mExpressionEvaluationStackPointer
,
439 &mExpressionEvaluationStackEnd
,
446 Pop an Expression value from the stack.
448 @param Value Expression value to pop.
450 @retval EFI_SUCCESS The value was popped onto the stack.
451 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
456 OUT EFI_HII_VALUE
*Value
460 mExpressionEvaluationStack
+ mExpressionEvaluationStackOffset
,
461 &mExpressionEvaluationStackPointer
,
467 Get current stack offset from stack start.
469 @return Stack offset to stack start.
472 SaveExpressionEvaluationStackOffset (
475 UINTN TempStackOffset
;
476 TempStackOffset
= mExpressionEvaluationStackOffset
;
477 mExpressionEvaluationStackOffset
= mExpressionEvaluationStackPointer
- mExpressionEvaluationStack
;
478 return TempStackOffset
;
482 Restore stack offset based on input stack offset
484 @param StackOffset Offset to stack start.
488 RestoreExpressionEvaluationStackOffset (
492 mExpressionEvaluationStackOffset
= StackOffset
;
497 Search a Question in Form scope using its QuestionId.
499 @param Form The form which contains this Question.
500 @param QuestionId Id of this Question.
502 @retval Pointer The Question.
503 @retval NULL Specified Question not found in the form.
506 FORM_BROWSER_STATEMENT
*
508 IN FORM_BROWSER_FORM
*Form
,
513 FORM_BROWSER_STATEMENT
*Question
;
515 if (QuestionId
== 0) {
517 // The value of zero is reserved
522 Link
= GetFirstNode (&Form
->StatementListHead
);
523 while (!IsNull (&Form
->StatementListHead
, Link
)) {
524 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
526 if (Question
->QuestionId
== QuestionId
) {
530 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
538 Search a Question in Formset scope using its QuestionId.
540 @param FormSet The formset which contains this form.
541 @param Form The form which contains this Question.
542 @param QuestionId Id of this Question.
544 @retval Pointer The Question.
545 @retval NULL Specified Question not found in the form.
548 FORM_BROWSER_STATEMENT
*
550 IN FORM_BROWSER_FORMSET
*FormSet
,
551 IN FORM_BROWSER_FORM
*Form
,
556 FORM_BROWSER_STATEMENT
*Question
;
559 // Search in the form scope first
561 Question
= IdToQuestion2 (Form
, QuestionId
);
562 if (Question
!= NULL
) {
567 // Search in the formset scope
569 Link
= GetFirstNode (&FormSet
->FormListHead
);
570 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
571 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
573 Question
= IdToQuestion2 (Form
, QuestionId
);
574 if (Question
!= NULL
) {
578 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
586 Get Expression given its RuleId.
588 @param Form The form which contains this Expression.
589 @param RuleId Id of this Expression.
591 @retval Pointer The Expression.
592 @retval NULL Specified Expression not found in the form.
597 IN FORM_BROWSER_FORM
*Form
,
602 FORM_EXPRESSION
*Expression
;
604 Link
= GetFirstNode (&Form
->ExpressionListHead
);
605 while (!IsNull (&Form
->ExpressionListHead
, Link
)) {
606 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
608 if ((Expression
->Type
== EFI_HII_EXPRESSION_RULE
) && (Expression
->RuleId
== RuleId
)) {
612 Link
= GetNextNode (&Form
->ExpressionListHead
, Link
);
619 Convert the input Unicode character to upper.
621 @param String Th Unicode character to be converted.
629 while (*String
!= 0) {
630 if ((*String
>= 'a') && (*String
<= 'z')) {
631 *String
= (UINT16
) ((*String
) & ((UINT16
) ~0x20));
638 Evaluate opcode EFI_IFR_TO_STRING.
640 @param FormSet Formset which contains this opcode.
641 @param Format String format in EFI_IFR_TO_STRING.
642 @param Result Evaluation result for this opcode.
644 @retval EFI_SUCCESS Opcode evaluation success.
645 @retval Other Opcode evaluation failed.
650 IN FORM_BROWSER_FORMSET
*FormSet
,
652 OUT EFI_HII_VALUE
*Result
658 CHAR16 Buffer
[MAXIMUM_VALUE_CHARACTERS
];
661 Status
= PopExpression (&Value
);
662 if (EFI_ERROR (Status
)) {
666 switch (Value
.Type
) {
667 case EFI_IFR_TYPE_NUM_SIZE_8
:
668 case EFI_IFR_TYPE_NUM_SIZE_16
:
669 case EFI_IFR_TYPE_NUM_SIZE_32
:
670 case EFI_IFR_TYPE_NUM_SIZE_64
:
671 BufferSize
= MAXIMUM_VALUE_CHARACTERS
* sizeof (CHAR16
);
673 case EFI_IFR_STRING_UNSIGNED_DEC
:
674 case EFI_IFR_STRING_SIGNED_DEC
:
675 PrintFormat
= L
"%ld";
678 case EFI_IFR_STRING_LOWERCASE_HEX
:
679 PrintFormat
= L
"%lx";
682 case EFI_IFR_STRING_UPPERCASE_HEX
:
683 PrintFormat
= L
"%lX";
687 return EFI_UNSUPPORTED
;
689 UnicodeSPrint (Buffer
, BufferSize
, PrintFormat
, Value
.Value
.u64
);
692 case EFI_IFR_TYPE_STRING
:
693 CopyMem (Result
, &Value
, sizeof (EFI_HII_VALUE
));
696 case EFI_IFR_TYPE_BOOLEAN
:
700 return EFI_UNSUPPORTED
;
703 Result
->Type
= EFI_IFR_TYPE_STRING
;
704 //Result->Value.string = NewString (String, FormSet->HiiHandle);
709 Evaluate opcode EFI_IFR_TO_UINT.
711 @param FormSet Formset which contains this opcode.
712 @param Result Evaluation result for this opcode.
714 @retval EFI_SUCCESS Opcode evaluation success.
715 @retval Other Opcode evaluation failed.
720 IN FORM_BROWSER_FORMSET
*FormSet
,
721 OUT EFI_HII_VALUE
*Result
729 Status
= PopExpression (&Value
);
730 if (EFI_ERROR (Status
)) {
734 if (Value
.Type
>= EFI_IFR_TYPE_OTHER
) {
735 return EFI_UNSUPPORTED
;
738 Status
= EFI_SUCCESS
;
739 if (Value
.Type
== EFI_IFR_TYPE_STRING
) {
740 String
= GetToken (Value
.Value
.string
, FormSet
->UnicodeBinary
);
741 if (String
== NULL
) {
742 return EFI_NOT_FOUND
;
745 IfrStrToUpper (String
);
746 StringPtr
= StrStr (String
, L
"0X");
747 if (StringPtr
!= NULL
) {
751 Result
->Value
.u64
= FceStrHexToUint64 (String
);
756 Result
->Value
.u64
= FceStrDecimalToUint64 (String
);
760 CopyMem (Result
, &Value
, sizeof (EFI_HII_VALUE
));
763 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
768 Evaluate opcode EFI_IFR_CATENATE.
770 @param FormSet Formset which contains this opcode.
771 @param Result Evaluation result for this opcode.
773 @retval EFI_SUCCESS Opcode evaluation success.
774 @retval Other Opcode evaluation failed.
779 IN FORM_BROWSER_FORMSET
*FormSet
,
780 OUT EFI_HII_VALUE
*Result
791 // String[0] - The second string
792 // String[1] - The first string
797 Status
= EFI_SUCCESS
;
799 for (Index
= 0; Index
< 2; Index
++) {
800 Status
= PopExpression (&Value
);
801 if (EFI_ERROR (Status
)) {
805 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
806 Status
= EFI_UNSUPPORTED
;
810 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->UnicodeBinary
);
811 if (String
[Index
] == NULL
) {
812 Status
= EFI_NOT_FOUND
;
817 Size
= FceStrSize (String
[0]);
818 StringPtr
= AllocatePool (FceStrSize (String
[1]) + Size
);
819 ASSERT (StringPtr
!= NULL
);
820 StrCpy (StringPtr
, String
[1]);
821 StrCat (StringPtr
, String
[0]);
823 Result
->Type
= EFI_IFR_TYPE_STRING
;
824 //Result->Value.string = NewString (StringPtr, FormSet->HiiHandle);
827 if (String
[0] != NULL
) {
828 FreePool (String
[0]);
830 if (String
[1] != NULL
) {
831 FreePool (String
[1]);
833 if (StringPtr
!= NULL
) {
834 FreePool (StringPtr
);
841 Evaluate opcode EFI_IFR_MATCH.
843 @param FormSet Formset which contains this opcode.
844 @param Result Evaluation result for this opcode.
846 @retval EFI_SUCCESS Opcode evaluation success.
847 @retval Other Opcode evaluation failed.
852 IN FORM_BROWSER_FORMSET
*FormSet
,
853 OUT EFI_HII_VALUE
*Result
862 // String[0] - The string to search
863 // String[1] - pattern
867 Status
= EFI_SUCCESS
;
868 for (Index
= 0; Index
< 2; Index
++) {
869 Status
= PopExpression (&Value
);
870 if (EFI_ERROR (Status
)) {
874 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
875 Status
= EFI_UNSUPPORTED
;
879 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->UnicodeBinary
);
880 if (String
[Index
] == NULL
) {
881 Status
= EFI_NOT_FOUND
;
886 Result
->Type
= EFI_IFR_TYPE_BOOLEAN
;
887 Result
->Value
.b
= MetaiMatch (String
[0], String
[1]);
890 if (String
[0] != NULL
) {
891 FreePool (String
[0]);
893 if (String
[1] != NULL
) {
894 FreePool (String
[1]);
902 Evaluate opcode EFI_IFR_FIND.
904 @param FormSet Formset which contains this opcode.
905 @param Format Case sensitive or insensitive.
906 @param Result Evaluation result for this opcode.
908 @retval EFI_SUCCESS Opcode evaluation success.
909 @retval Other Opcode evaluation failed.
914 IN FORM_BROWSER_FORMSET
*FormSet
,
916 OUT EFI_HII_VALUE
*Result
926 if (Format
> EFI_IFR_FF_CASE_INSENSITIVE
) {
927 return EFI_UNSUPPORTED
;
930 Status
= PopExpression (&Value
);
931 if (EFI_ERROR (Status
)) {
934 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
935 return EFI_UNSUPPORTED
;
937 Base
= (UINTN
) Value
.Value
.u64
;
940 // String[0] - sub-string
941 // String[1] - The string to search
945 for (Index
= 0; Index
< 2; Index
++) {
946 Status
= PopExpression (&Value
);
947 if (EFI_ERROR (Status
)) {
951 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
952 Status
= EFI_UNSUPPORTED
;
956 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->UnicodeBinary
);
957 if (String
[Index
] == NULL
) {
958 Status
= EFI_NOT_FOUND
;
962 if (Format
== EFI_IFR_FF_CASE_INSENSITIVE
) {
964 // Case insensitive, convert both string to upper case
966 IfrStrToUpper (String
[Index
]);
970 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
971 if (Base
>= FceStrLen (String
[1])) {
972 Result
->Value
.u64
= 0xFFFFFFFFFFFFFFFFULL
;
974 StringPtr
= StrStr (String
[1] + Base
, String
[0]);
975 Result
->Value
.u64
= (StringPtr
== NULL
) ? 0xFFFFFFFFFFFFFFFFULL
: (StringPtr
- String
[1]);
979 if (String
[0] != NULL
) {
980 FreePool (String
[0]);
982 if (String
[1] != NULL
) {
983 FreePool (String
[1]);
991 Evaluate opcode EFI_IFR_MID.
993 @param FormSet Formset which contains this opcode.
994 @param Result Evaluation result for this opcode.
996 @retval EFI_SUCCESS Opcode evaluation success.
997 @retval Other Opcode evaluation failed.
1002 IN FORM_BROWSER_FORMSET
*FormSet
,
1003 OUT EFI_HII_VALUE
*Result
1007 EFI_HII_VALUE Value
;
1013 Status
= PopExpression (&Value
);
1014 if (EFI_ERROR (Status
)) {
1017 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1018 return EFI_UNSUPPORTED
;
1020 Length
= (UINTN
) Value
.Value
.u64
;
1022 Status
= PopExpression (&Value
);
1023 if (EFI_ERROR (Status
)) {
1026 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1027 return EFI_UNSUPPORTED
;
1029 Base
= (UINTN
) Value
.Value
.u64
;
1031 Status
= PopExpression (&Value
);
1032 if (EFI_ERROR (Status
)) {
1035 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
1036 return EFI_UNSUPPORTED
;
1038 String
= GetToken (Value
.Value
.string
, FormSet
->UnicodeBinary
);
1039 if (String
== NULL
) {
1040 return EFI_NOT_FOUND
;
1043 if ((Length
== 0) || (Base
>= FceStrLen (String
))) {
1044 SubString
= gEmptyString
;
1046 SubString
= String
+ Base
;
1047 if ((Base
+ Length
) < FceStrLen (String
)) {
1048 SubString
[Length
] = L
'\0';
1052 Result
->Type
= EFI_IFR_TYPE_STRING
;
1053 //Result->Value.string = NewString (SubString, FormSet->HiiHandle);
1061 Evaluate opcode EFI_IFR_TOKEN.
1063 @param FormSet Formset which contains this opcode.
1064 @param Result Evaluation result for this opcode.
1066 @retval EFI_SUCCESS Opcode evaluation success.
1067 @retval Other Opcode evaluation failed.
1072 IN FORM_BROWSER_FORMSET
*FormSet
,
1073 OUT EFI_HII_VALUE
*Result
1077 EFI_HII_VALUE Value
;
1085 Status
= PopExpression (&Value
);
1086 if (EFI_ERROR (Status
)) {
1089 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1090 return EFI_UNSUPPORTED
;
1092 Count
= (UINTN
) Value
.Value
.u64
;
1095 // String[0] - Delimiter
1096 // String[1] - The string to search
1100 for (Index
= 0; Index
< 2; Index
++) {
1101 Status
= PopExpression (&Value
);
1102 if (EFI_ERROR (Status
)) {
1106 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
1107 Status
= EFI_UNSUPPORTED
;
1111 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->UnicodeBinary
);
1112 if (String
[Index
] == NULL
) {
1113 Status
= EFI_NOT_FOUND
;
1118 Delimiter
= String
[0];
1119 SubString
= String
[1];
1121 SubString
= StrStr (SubString
, Delimiter
);
1122 if (SubString
!= NULL
) {
1124 // Skip over the delimiter
1126 SubString
= SubString
+ FceStrLen (Delimiter
);
1133 if (SubString
== NULL
) {
1135 // nth delimited sub-string not found, push an empty string
1137 SubString
= gEmptyString
;
1140 // Put a NULL terminator for nth delimited sub-string
1142 StringPtr
= StrStr (SubString
, Delimiter
);
1143 if (StringPtr
!= NULL
) {
1148 Result
->Type
= EFI_IFR_TYPE_STRING
;
1149 //Result->Value.string = NewString (SubString, FormSet->HiiHandle);
1152 if (String
[0] != NULL
) {
1153 FreePool (String
[0]);
1155 if (String
[1] != NULL
) {
1156 FreePool (String
[1]);
1164 Evaluate opcode EFI_IFR_SPAN.
1166 @param FormSet Formset which contains this opcode.
1167 @param Flags FIRST_MATCHING or FIRST_NON_MATCHING.
1168 @param Result Evaluation result for this opcode.
1170 @retval EFI_SUCCESS Opcode evaluation success.
1171 @retval Other Opcode evaluation failed.
1176 IN FORM_BROWSER_FORMSET
*FormSet
,
1178 OUT EFI_HII_VALUE
*Result
1182 EFI_HII_VALUE Value
;
1190 Status
= PopExpression (&Value
);
1191 if (EFI_ERROR (Status
)) {
1194 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1195 return EFI_UNSUPPORTED
;
1197 Base
= (UINTN
) Value
.Value
.u64
;
1200 // String[0] - Charset
1201 // String[1] - The string to search
1205 for (Index
= 0; Index
< 2; Index
++) {
1206 Status
= PopExpression (&Value
);
1207 if (EFI_ERROR (Status
)) {
1211 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
1212 Status
= EFI_UNSUPPORTED
;
1216 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->UnicodeBinary
);
1217 if (String
[Index
] == NULL
) {
1218 Status
= EFI_NOT_FOUND
;
1223 if (Base
>= FceStrLen (String
[1])) {
1224 Status
= EFI_UNSUPPORTED
;
1229 StringPtr
= String
[1] + Base
;
1230 Charset
= String
[0];
1231 while (*StringPtr
!= 0 && !Found
) {
1233 while (Charset
[Index
] != 0) {
1234 if ((*StringPtr
>= Charset
[Index
]) && (*StringPtr
<= Charset
[Index
+ 1])) {
1235 if (Flags
== EFI_IFR_FLAGS_FIRST_MATCHING
) {
1240 if (Flags
== EFI_IFR_FLAGS_FIRST_NON_MATCHING
) {
1246 // Skip characters pair representing low-end of a range and high-end of a range
1256 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1257 Result
->Value
.u64
= StringPtr
- String
[1];
1260 if (String
[0] != NULL
) {
1261 FreePool (String
[0]);
1263 if (String
[1] != NULL
) {
1264 FreePool (String
[1]);
1272 Zero extend integer/boolean/date/time to UINT64 for comparing.
1274 @param Value HII Value to be converted.
1279 IN EFI_HII_VALUE
*Value
1285 switch (Value
->Type
) {
1286 case EFI_IFR_TYPE_NUM_SIZE_8
:
1287 Temp
= Value
->Value
.u8
;
1290 case EFI_IFR_TYPE_NUM_SIZE_16
:
1291 Temp
= Value
->Value
.u16
;
1294 case EFI_IFR_TYPE_NUM_SIZE_32
:
1295 Temp
= Value
->Value
.u32
;
1298 case EFI_IFR_TYPE_BOOLEAN
:
1299 Temp
= Value
->Value
.b
;
1302 case EFI_IFR_TYPE_TIME
:
1303 Temp
= Value
->Value
.u32
& 0xffffff;
1306 case EFI_IFR_TYPE_DATE
:
1307 Temp
= Value
->Value
.u32
;
1314 Value
->Value
.u64
= Temp
;
1319 Compare two Hii value.
1321 @param Value1 Expression value to compare on left-hand.
1322 @param Value2 Expression value to compare on right-hand.
1323 @param FormSet The pointer to the Formset.
1325 @retval EFI_INVALID_PARAMETER Could not perform compare on two values.
1326 @retval 0 Two operators equal.
1327 @return Positive value if Value1 is greater than Value2.
1328 @retval Negative value if Value1 is less than Value2.
1333 IN EFI_HII_VALUE
*Value1
,
1334 IN EFI_HII_VALUE
*Value2
,
1335 IN FORM_BROWSER_FORMSET
*FormSet
1343 if ((Value1
->Type
>= EFI_IFR_TYPE_OTHER
) || (Value2
->Type
>= EFI_IFR_TYPE_OTHER
) ) {
1344 return EFI_INVALID_PARAMETER
;
1347 if ((Value1
->Type
== EFI_IFR_TYPE_STRING
) || (Value2
->Type
== EFI_IFR_TYPE_STRING
) ) {
1348 if (Value1
->Type
!= Value2
->Type
) {
1350 // Both Operator should be type of String
1352 return EFI_INVALID_PARAMETER
;
1355 if ((Value1
->Value
.string
== 0) || (Value2
->Value
.string
== 0)) {
1357 // StringId 0 is reserved
1359 return EFI_INVALID_PARAMETER
;
1362 if (Value1
->Value
.string
== Value2
->Value
.string
) {
1366 Str1
= GetToken (Value1
->Value
.string
, FormSet
->UnicodeBinary
);
1371 return EFI_INVALID_PARAMETER
;
1374 Str2
= GetToken (Value2
->Value
.string
, FormSet
->UnicodeBinary
);
1377 return EFI_INVALID_PARAMETER
;
1380 Result
= FceStrCmp (Str1
, Str2
);
1389 // Take remain types(integer, boolean, date/time) as integer
1391 Temp64
= (INT64
) (Value1
->Value
.u64
- Value2
->Value
.u64
);
1394 } else if (Temp64
< 0) {
1404 Tell whether this Operand is an constant Expression or not
1406 @param Operand Operand of an IFR OpCode.
1408 @retval TRUE This is an Expression OpCode.
1409 @retval FALSE Not an Expression OpCode.
1413 IsConstantExpressionOpCode (
1417 if ((Operand
== EFI_IFR_EQ_ID_VAL_OP
) ||
1418 (Operand
== EFI_IFR_EQ_ID_ID_OP
) ||
1419 (Operand
== EFI_IFR_EQ_ID_VAL_LIST_OP
)||
1420 (Operand
== EFI_IFR_QUESTION_REF1_OP
) ||
1421 (Operand
== EFI_IFR_QUESTION_REF2_OP
) ||
1422 (Operand
== EFI_IFR_QUESTION_REF3_OP
) ||
1423 (Operand
== EFI_IFR_THIS_OP
) ||
1424 (Operand
== EFI_IFR_SECURITY_OP
) ||
1425 (Operand
== EFI_IFR_GET_OP
) ||
1426 (Operand
== EFI_IFR_SET_OP
)
1435 Update the HiiValue of question from its variable.
1437 @param FormSet FormSet associated with this expression.
1438 @param Question The pointer to the Question
1441 @return EFI_NOT_FOUND
1445 IN FORM_BROWSER_FORMSET
*FormSet
,
1446 IN FORM_BROWSER_STATEMENT
*Question
1450 FORMSET_STORAGE
*VarList
;
1452 EFI_HII_VALUE
*HiiValue
;
1454 Status
= EFI_SUCCESS
;
1455 HiiValue
= &Question
->HiiValue
;
1457 Status
= SearchVarStorage (
1460 Question
->VarStoreInfo
.VarOffset
,
1461 FormSet
->StorageListHead
,
1462 (CHAR8
**)&VarBuffer
,
1465 if (EFI_ERROR(Status
)) {
1468 if (Question
->QuestionReferToBitField
) {
1469 GetBitsQuestionValue (Question
, VarBuffer
, &HiiValue
->Value
.u32
);
1471 CopyMem (&HiiValue
->Value
.u64
, VarBuffer
, Question
->StorageWidth
);
1476 Evaluate the result of a HII expression.
1478 If Expression is NULL, then ASSERT.
1480 @param FormSet FormSet associated with this expression.
1481 @param Form Form associated with this expression.
1482 @param Expression Expression to be evaluated.
1483 @param ConstantExpression The pointer to the flag of constant expression. If constant, will return TRUE.
1485 @retval EFI_SUCCESS The expression evaluated successfuly
1486 @retval EFI_NOT_FOUND The Question which referenced by a QuestionId
1488 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
1490 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
1491 @retval EFI_INVALID_PARAMETER Syntax error with the Expression
1495 EvaluateExpression (
1496 IN FORM_BROWSER_FORMSET
*FormSet
,
1497 IN FORM_BROWSER_FORM
*Form
,
1498 IN OUT FORM_EXPRESSION
*Expression
,
1499 IN OUT BOOLEAN
*ConstantExpression
1504 EXPRESSION_OPCODE
*OpCode
;
1505 FORM_BROWSER_STATEMENT
*Question
;
1506 FORM_BROWSER_STATEMENT
*Question2
;
1508 EFI_HII_VALUE Data1
;
1509 EFI_HII_VALUE Data2
;
1510 EFI_HII_VALUE Data3
;
1511 FORM_EXPRESSION
*RuleExpression
;
1512 EFI_HII_VALUE
*Value
;
1516 LIST_ENTRY
*SubExpressionLink
;
1517 FORM_EXPRESSION
*SubExpression
;
1525 // Save current stack offset.
1527 StackOffset
= SaveExpressionEvaluationStackOffset ();
1529 ASSERT (Expression
!= NULL
);
1530 Expression
->Result
.Type
= EFI_IFR_TYPE_OTHER
;
1532 Link
= GetFirstNode (&Expression
->OpCodeListHead
);
1533 while (!IsNull (&Expression
->OpCodeListHead
, Link
)) {
1534 OpCode
= EXPRESSION_OPCODE_FROM_LINK (Link
);
1536 Link
= GetNextNode (&Expression
->OpCodeListHead
, Link
);
1538 ZeroMem (&Data1
, sizeof (EFI_HII_VALUE
));
1539 ZeroMem (&Data2
, sizeof (EFI_HII_VALUE
));
1540 ZeroMem (&Data3
, sizeof (EFI_HII_VALUE
));
1543 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
1544 Status
= EFI_SUCCESS
;
1547 // Check whether it is a constant expression or not
1549 if (*ConstantExpression
) {
1550 *ConstantExpression
= IsConstantExpressionOpCode (OpCode
->Operand
);
1553 switch (OpCode
->Operand
) {
1555 // Built-in functions
1557 case EFI_IFR_EQ_ID_VAL_OP
:
1558 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
1559 if (Question
== NULL
) {
1560 Status
= EFI_NOT_FOUND
;
1563 UpdateHiiValue (FormSet
, Question
);
1564 Result
= CompareHiiValue (&Question
->HiiValue
, &OpCode
->Value
, FormSet
);
1565 if ((EFI_STATUS
)Result
== EFI_INVALID_PARAMETER
) {
1566 Status
= EFI_INVALID_PARAMETER
;
1569 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
1572 case EFI_IFR_EQ_ID_ID_OP
:
1573 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
1574 if (Question
== NULL
) {
1575 Status
= EFI_NOT_FOUND
;
1579 Question2
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId2
);
1580 if (Question2
== NULL
) {
1581 Status
= EFI_NOT_FOUND
;
1584 UpdateHiiValue (FormSet
, Question
);
1585 UpdateHiiValue (FormSet
, Question2
);
1586 Result
= CompareHiiValue (&Question
->HiiValue
, &Question2
->HiiValue
, FormSet
);
1587 if ((EFI_STATUS
)Result
== EFI_INVALID_PARAMETER
) {
1588 Status
= EFI_INVALID_PARAMETER
;
1591 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
1594 case EFI_IFR_EQ_ID_VAL_LIST_OP
:
1596 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
1597 if (Question
== NULL
) {
1598 Status
= EFI_NOT_FOUND
;
1601 UpdateHiiValue (FormSet
, Question
);
1602 Value
->Value
.b
= FALSE
;
1603 for (Index
=0; Index
< OpCode
->ListLength
; Index
++) {
1604 if (Question
->HiiValue
.Value
.u16
== OpCode
->ValueList
[Index
]) {
1605 Value
->Value
.b
= TRUE
;
1611 case EFI_IFR_DUP_OP
:
1612 Status
= PopExpression (Value
);
1613 if (EFI_ERROR (Status
)) {
1617 Status
= PushExpression (Value
);
1620 case EFI_IFR_QUESTION_REF1_OP
:
1621 case EFI_IFR_THIS_OP
:
1622 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
1623 if (Question
== NULL
) {
1624 Status
= EFI_NOT_FOUND
;
1627 UpdateHiiValue (FormSet
, Question
);
1628 Value
= &Question
->HiiValue
;
1631 case EFI_IFR_SECURITY_OP
:
1633 // Do nothing, as no need for static scaning
1637 case EFI_IFR_GET_OP
:
1639 // Get Value from VarStore buffer, EFI VarStore, Name/Value VarStore.
1641 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1642 Value
->Value
.u8
= 0;
1643 if (OpCode
->VarStorage
!= NULL
) {
1644 switch (OpCode
->VarStorage
->Type
) {
1645 case EFI_IFR_VARSTORE_OP
:
1647 // Get value from Buffer
1649 Value
->Type
= OpCode
->ValueType
;
1650 CopyMem (&Value
->Value
, OpCode
->VarStorage
->Buffer
+ OpCode
->VarStoreInfo
.VarOffset
, OpCode
->ValueWidth
);
1653 case EFI_IFR_VARSTORE_EFI_OP
:
1655 // Get value from Buffer
1657 if (OpCode
->VarStorage
->NewEfiVarstore
) {
1658 Value
->Type
= OpCode
->ValueType
;
1659 CopyMem (&Value
->Value
, OpCode
->VarStorage
->Buffer
+ OpCode
->VarStoreInfo
.VarOffset
, OpCode
->ValueWidth
);
1661 CopyMem (&Value
->Value
, OpCode
->VarStorage
->Buffer
, OpCode
->ValueWidth
);
1666 case EFI_HII_VARSTORE_NAME_VALUE
:
1667 if (OpCode
->ValueType
!= EFI_IFR_TYPE_STRING
) {
1669 // Get value from string except for STRING value.
1671 Status
= GetValueByName (OpCode
->VarStorage
, OpCode
->ValueName
, &StrPtr
);
1672 if (!EFI_ERROR (Status
)) {
1673 ASSERT (StrPtr
!= NULL
);
1674 TempLength
= FceStrLen (StrPtr
);
1675 if (OpCode
->ValueWidth
>= ((TempLength
+ 1) / 2)) {
1676 Value
->Type
= OpCode
->ValueType
;
1677 TempBuffer
= (UINT8
*) &Value
->Value
;
1678 ZeroMem (TempStr
, sizeof (TempStr
));
1679 for (Index
= 0; Index
< TempLength
; Index
++) {
1680 TempStr
[0] = StrPtr
[TempLength
- Index
- 1];
1681 DigitUint8
= (UINT8
) FceStrHexToUint64 (TempStr
);
1682 if ((Index
& 1) == 0) {
1683 TempBuffer
[Index
/2] = DigitUint8
;
1685 TempBuffer
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + TempBuffer
[Index
/2]);
1696 // Not recognize storage.
1698 Status
= EFI_UNSUPPORTED
;
1705 case EFI_IFR_QUESTION_REF3_OP
:
1706 if (OpCode
->DevicePath
== 0) {
1708 // EFI_IFR_QUESTION_REF3
1709 // Pop an expression from the expression stack
1711 Status
= PopExpression (Value
);
1712 if (EFI_ERROR (Status
)) {
1717 // Validate the expression value
1719 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
1720 Status
= EFI_NOT_FOUND
;
1724 Question
= IdToQuestion (FormSet
, Form
, Value
->Value
.u16
);
1725 if (Question
== NULL
) {
1726 Status
= EFI_NOT_FOUND
;
1731 // push the questions' value on to the expression stack
1733 Value
= &Question
->HiiValue
;
1736 // BUGBUG: push 0 for EFI_IFR_QUESTION_REF3_2 and EFI_IFR_QUESTION_REF3_3,
1737 // since it is impractical to evaluate the value of a Question in another
1738 // Hii Package list.
1740 ZeroMem (Value
, sizeof (EFI_HII_VALUE
));
1744 case EFI_IFR_RULE_REF_OP
:
1746 // Find expression for this rule
1748 RuleExpression
= RuleIdToExpression (Form
, OpCode
->RuleId
);
1749 if (RuleExpression
== NULL
) {
1750 Status
= EFI_NOT_FOUND
;
1755 // Evaluate this rule expression
1757 Status
= EvaluateExpression (FormSet
, Form
, RuleExpression
, ConstantExpression
);
1758 if (EFI_ERROR (Status
)) {
1762 Value
= &RuleExpression
->Result
;
1765 case EFI_IFR_STRING_REF1_OP
:
1766 Value
->Type
= EFI_IFR_TYPE_STRING
;
1767 Value
->Value
.string
= OpCode
->Value
.Value
.string
;
1773 case EFI_IFR_TRUE_OP
:
1774 case EFI_IFR_FALSE_OP
:
1775 case EFI_IFR_ONE_OP
:
1776 case EFI_IFR_ONES_OP
:
1777 case EFI_IFR_UINT8_OP
:
1778 case EFI_IFR_UINT16_OP
:
1779 case EFI_IFR_UINT32_OP
:
1780 case EFI_IFR_UINT64_OP
:
1781 case EFI_IFR_UNDEFINED_OP
:
1782 case EFI_IFR_VERSION_OP
:
1783 case EFI_IFR_ZERO_OP
:
1784 Value
= &OpCode
->Value
;
1790 case EFI_IFR_LENGTH_OP
:
1791 Status
= PopExpression (Value
);
1792 if (EFI_ERROR (Status
)) {
1795 if (Value
->Type
!= EFI_IFR_TYPE_STRING
) {
1796 Status
= EFI_INVALID_PARAMETER
;
1800 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->UnicodeBinary
);
1801 if (StrPtr
== NULL
) {
1802 Status
= EFI_INVALID_PARAMETER
;
1806 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1807 Value
->Value
.u64
= FceStrLen (StrPtr
);
1811 case EFI_IFR_NOT_OP
:
1812 Status
= PopExpression (Value
);
1813 if (EFI_ERROR (Status
)) {
1816 if (Value
->Type
!= EFI_IFR_TYPE_BOOLEAN
) {
1817 Status
= EFI_INVALID_PARAMETER
;
1820 Value
->Value
.b
= (BOOLEAN
) (!Value
->Value
.b
);
1823 case EFI_IFR_QUESTION_REF2_OP
:
1825 // Pop an expression from the expression stack
1827 Status
= PopExpression (Value
);
1828 if (EFI_ERROR (Status
)) {
1833 // Validate the expression value
1835 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
1836 Status
= EFI_NOT_FOUND
;
1840 Question
= IdToQuestion (FormSet
, Form
, Value
->Value
.u16
);
1841 if (Question
== NULL
) {
1842 Status
= EFI_NOT_FOUND
;
1846 Value
= &Question
->HiiValue
;
1849 case EFI_IFR_STRING_REF2_OP
:
1851 // Pop an expression from the expression stack
1853 Status
= PopExpression (Value
);
1854 if (EFI_ERROR (Status
)) {
1859 // Validate the expression value
1861 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
1862 Status
= EFI_NOT_FOUND
;
1866 Value
->Type
= EFI_IFR_TYPE_STRING
;
1867 StrPtr
= GetToken (Value
->Value
.u16
, FormSet
->UnicodeBinary
);
1868 if (StrPtr
== NULL
) {
1870 // If String not exit, push an empty string
1872 //Value->Value.string = NewString (gEmptyString, FormSet->HiiHandle);
1874 Index
= (UINT16
) Value
->Value
.u64
;
1875 Value
->Value
.string
= Index
;
1880 case EFI_IFR_TO_BOOLEAN_OP
:
1882 // Pop an expression from the expression stack
1884 Status
= PopExpression (Value
);
1885 if (EFI_ERROR (Status
)) {
1890 // Convert an expression to a Boolean
1892 if (Value
->Type
<= EFI_IFR_TYPE_DATE
) {
1894 // When converting from an unsigned integer, zero will be converted to
1895 // FALSE and any other value will be converted to TRUE.
1897 Value
->Value
.b
= (BOOLEAN
) (Value
->Value
.u64
!= 0);
1899 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
1900 } else if (Value
->Type
== EFI_IFR_TYPE_STRING
) {
1902 // When converting from a string, if case-insensitive compare
1903 // with "true" is True, then push True. If a case-insensitive compare
1904 // with "false" is True, then push False. Otherwise, push Undefined.
1906 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->UnicodeBinary
);
1907 if (StrPtr
== NULL
) {
1908 Status
= EFI_INVALID_PARAMETER
;
1912 IfrStrToUpper (StrPtr
);
1913 if (FceStrCmp (StrPtr
, L
"TRUE") == 0){
1914 Value
->Value
.b
= TRUE
;
1915 } else if (FceStrCmp (StrPtr
, L
"FALSE") == 0) {
1916 Value
->Value
.b
= FALSE
;
1918 Status
= EFI_INVALID_PARAMETER
;
1923 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
1927 case EFI_IFR_TO_STRING_OP
:
1928 //Status = IfrToString (FormSet, OpCode->Format, Value);
1931 case EFI_IFR_TO_UINT_OP
:
1932 Status
= IfrToUint (FormSet
, Value
);
1935 case EFI_IFR_TO_LOWER_OP
:
1936 case EFI_IFR_TO_UPPER_OP
:
1938 Status
= PopExpression (Value
);
1939 if (EFI_ERROR (Status
)) {
1943 if (Value
->Type
!= EFI_IFR_TYPE_STRING
) {
1944 Status
= EFI_UNSUPPORTED
;
1948 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->UnicodeBinary
);
1949 if (StrPtr
== NULL
) {
1950 Status
= EFI_NOT_FOUND
;
1954 // Do nothing here, as these two Opcode are to change or update the String Package
1959 case EFI_IFR_BITWISE_NOT_OP
:
1961 // Pop an expression from the expression stack
1963 Status
= PopExpression (Value
);
1964 if (EFI_ERROR (Status
)) {
1967 if (Value
->Type
> EFI_IFR_TYPE_DATE
) {
1968 Status
= EFI_INVALID_PARAMETER
;
1972 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1973 Value
->Value
.u64
= ~Value
->Value
.u64
;
1976 case EFI_IFR_SET_OP
:
1978 // Pop an expression from the expression stack
1980 Status
= PopExpression (Value
);
1981 if (EFI_ERROR (Status
)) {
1984 Data1
.Type
= EFI_IFR_TYPE_BOOLEAN
;
1985 Data1
.Value
.b
= FALSE
;
1987 // Not support SetOpcode for static scaning
1989 if (OpCode
->VarStorage
!= NULL
) {
1990 switch (OpCode
->VarStorage
->Type
) {
1992 case EFI_IFR_VARSTORE_OP
:
1993 CopyMem (OpCode
->VarStorage
->Buffer
+ OpCode
->VarStoreInfo
.VarOffset
, &Value
->Value
, OpCode
->ValueWidth
);
1994 Data1
.Value
.b
= TRUE
;
1996 case EFI_IFR_VARSTORE_EFI_OP
:
1997 if (OpCode
->VarStorage
->NewEfiVarstore
) {
1998 CopyMem (OpCode
->VarStorage
->Buffer
+ OpCode
->VarStoreInfo
.VarOffset
, &Value
->Value
, OpCode
->ValueWidth
);
1999 Data1
.Value
.b
= TRUE
;
2001 CopyMem (OpCode
->VarStorage
->Buffer
, &Value
->Value
, OpCode
->ValueWidth
);
2002 Data1
.Value
.b
= TRUE
;
2005 case EFI_HII_VARSTORE_NAME_VALUE
:
2011 // Not recognize storage.
2013 Status
= EFI_UNSUPPORTED
;
2024 case EFI_IFR_ADD_OP
:
2025 case EFI_IFR_SUBTRACT_OP
:
2026 case EFI_IFR_MULTIPLY_OP
:
2027 case EFI_IFR_DIVIDE_OP
:
2028 case EFI_IFR_MODULO_OP
:
2029 case EFI_IFR_BITWISE_AND_OP
:
2030 case EFI_IFR_BITWISE_OR_OP
:
2031 case EFI_IFR_SHIFT_LEFT_OP
:
2032 case EFI_IFR_SHIFT_RIGHT_OP
:
2034 // Pop an expression from the expression stack
2036 Status
= PopExpression (&Data2
);
2037 if (EFI_ERROR (Status
)) {
2040 if (Data2
.Type
> EFI_IFR_TYPE_DATE
) {
2041 Status
= EFI_INVALID_PARAMETER
;
2046 // Pop another expression from the expression stack
2048 Status
= PopExpression (&Data1
);
2049 if (EFI_ERROR (Status
)) {
2052 if (Data1
.Type
> EFI_IFR_TYPE_DATE
) {
2053 Status
= EFI_INVALID_PARAMETER
;
2057 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
2059 switch (OpCode
->Operand
) {
2060 case EFI_IFR_ADD_OP
:
2061 Value
->Value
.u64
= Data1
.Value
.u64
+ Data2
.Value
.u64
;
2064 case EFI_IFR_SUBTRACT_OP
:
2065 Value
->Value
.u64
= Data1
.Value
.u64
- Data2
.Value
.u64
;
2068 case EFI_IFR_MULTIPLY_OP
:
2069 Value
->Value
.u64
= MultU64x32 (Data1
.Value
.u64
, (UINT32
) Data2
.Value
.u64
);
2072 case EFI_IFR_DIVIDE_OP
:
2073 Value
->Value
.u64
= DivU64x32 (Data1
.Value
.u64
, (UINT32
) Data2
.Value
.u64
);
2076 case EFI_IFR_MODULO_OP
:
2077 DivU64x32Remainder (Data1
.Value
.u64
, (UINT32
) Data2
.Value
.u64
, &TempValue
);
2078 Value
->Value
.u64
= TempValue
;
2081 case EFI_IFR_BITWISE_AND_OP
:
2082 Value
->Value
.u64
= Data1
.Value
.u64
& Data2
.Value
.u64
;
2085 case EFI_IFR_BITWISE_OR_OP
:
2086 Value
->Value
.u64
= Data1
.Value
.u64
| Data2
.Value
.u64
;
2089 case EFI_IFR_SHIFT_LEFT_OP
:
2090 Value
->Value
.u64
= LShiftU64 (Data1
.Value
.u64
, (UINTN
) Data2
.Value
.u64
);
2093 case EFI_IFR_SHIFT_RIGHT_OP
:
2094 Value
->Value
.u64
= RShiftU64 (Data1
.Value
.u64
, (UINTN
) Data2
.Value
.u64
);
2102 case EFI_IFR_AND_OP
:
2105 // Two Boolean operator
2107 Status
= PopExpression (&Data2
);
2108 if (EFI_ERROR (Status
)) {
2111 if (Data2
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
2112 Status
= EFI_INVALID_PARAMETER
;
2117 // Pop another expression from the expression stack
2119 Status
= PopExpression (&Data1
);
2120 if (EFI_ERROR (Status
)) {
2123 if (Data1
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
2124 Status
= EFI_INVALID_PARAMETER
;
2128 if (OpCode
->Operand
== EFI_IFR_AND_OP
) {
2129 Value
->Value
.b
= (BOOLEAN
) (Data1
.Value
.b
&& Data2
.Value
.b
);
2131 Value
->Value
.b
= (BOOLEAN
) (Data1
.Value
.b
|| Data2
.Value
.b
);
2135 case EFI_IFR_EQUAL_OP
:
2136 case EFI_IFR_NOT_EQUAL_OP
:
2137 case EFI_IFR_GREATER_EQUAL_OP
:
2138 case EFI_IFR_GREATER_THAN_OP
:
2139 case EFI_IFR_LESS_EQUAL_OP
:
2140 case EFI_IFR_LESS_THAN_OP
:
2142 // Compare two integer, string, boolean or date/time
2144 Status
= PopExpression (&Data2
);
2145 if (EFI_ERROR (Status
)) {
2148 if ((Data2
.Type
> EFI_IFR_TYPE_BOOLEAN
) && (Data2
.Type
!= EFI_IFR_TYPE_STRING
)) {
2149 Status
= EFI_INVALID_PARAMETER
;
2154 // Pop another expression from the expression stack
2156 Status
= PopExpression (&Data1
);
2157 if (EFI_ERROR (Status
)) {
2161 Result
= CompareHiiValue (&Data1
, &Data2
, FormSet
);
2162 if ((EFI_STATUS
)Result
== EFI_INVALID_PARAMETER
) {
2163 Status
= EFI_INVALID_PARAMETER
;
2167 switch (OpCode
->Operand
) {
2168 case EFI_IFR_EQUAL_OP
:
2169 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
2172 case EFI_IFR_NOT_EQUAL_OP
:
2173 Value
->Value
.b
= (BOOLEAN
) ((Result
!= 0) ? TRUE
: FALSE
);
2176 case EFI_IFR_GREATER_EQUAL_OP
:
2177 Value
->Value
.b
= (BOOLEAN
) ((Result
>= 0) ? TRUE
: FALSE
);
2180 case EFI_IFR_GREATER_THAN_OP
:
2181 Value
->Value
.b
= (BOOLEAN
) ((Result
> 0) ? TRUE
: FALSE
);
2184 case EFI_IFR_LESS_EQUAL_OP
:
2185 Value
->Value
.b
= (BOOLEAN
) ((Result
<= 0) ? TRUE
: FALSE
);
2188 case EFI_IFR_LESS_THAN_OP
:
2189 Value
->Value
.b
= (BOOLEAN
) ((Result
< 0) ? TRUE
: FALSE
);
2197 case EFI_IFR_MATCH_OP
:
2198 Status
= IfrMatch (FormSet
, Value
);
2201 case EFI_IFR_CATENATE_OP
:
2202 Status
= IfrCatenate (FormSet
, Value
);
2208 case EFI_IFR_CONDITIONAL_OP
:
2210 // Pop third expression from the expression stack
2212 Status
= PopExpression (&Data3
);
2213 if (EFI_ERROR (Status
)) {
2218 // Pop second expression from the expression stack
2220 Status
= PopExpression (&Data2
);
2221 if (EFI_ERROR (Status
)) {
2226 // Pop first expression from the expression stack
2228 Status
= PopExpression (&Data1
);
2229 if (EFI_ERROR (Status
)) {
2232 if (Data1
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
2233 Status
= EFI_INVALID_PARAMETER
;
2237 if (Data1
.Value
.b
) {
2244 case EFI_IFR_FIND_OP
:
2245 Status
= IfrFind (FormSet
, OpCode
->Format
, Value
);
2248 case EFI_IFR_MID_OP
:
2249 Status
= IfrMid (FormSet
, Value
);
2252 case EFI_IFR_TOKEN_OP
:
2253 Status
= IfrToken (FormSet
, Value
);
2256 case EFI_IFR_SPAN_OP
:
2257 Status
= IfrSpan (FormSet
, OpCode
->Flags
, Value
);
2260 case EFI_IFR_MAP_OP
:
2262 // Pop the check value
2264 Status
= PopExpression (&Data1
);
2265 if (EFI_ERROR (Status
)) {
2269 // Check MapExpression list is valid.
2271 if (OpCode
->MapExpressionList
.ForwardLink
== NULL
) {
2272 Status
= EFI_INVALID_PARAMETER
;
2276 // Go through map expression list.
2278 SubExpressionLink
= GetFirstNode(&OpCode
->MapExpressionList
);
2279 while (!IsNull (&OpCode
->MapExpressionList
, SubExpressionLink
)) {
2280 SubExpression
= FORM_EXPRESSION_FROM_LINK (SubExpressionLink
);
2282 // Evaluate the first expression in this pair.
2284 Status
= EvaluateExpression (FormSet
, Form
, SubExpression
, ConstantExpression
);
2285 if (EFI_ERROR (Status
)) {
2289 // Compare the expression value with current value
2291 if (CompareHiiValue (&Data1
, &SubExpression
->Result
, FormSet
) == 0) {
2293 // Try get the map value.
2295 SubExpressionLink
= GetNextNode (&OpCode
->MapExpressionList
, SubExpressionLink
);
2296 if (IsNull (&OpCode
->MapExpressionList
, SubExpressionLink
)) {
2297 Status
= EFI_INVALID_PARAMETER
;
2300 SubExpression
= FORM_EXPRESSION_FROM_LINK (SubExpressionLink
);
2301 Status
= EvaluateExpression (FormSet
, Form
, SubExpression
, ConstantExpression
);
2302 if (EFI_ERROR (Status
)) {
2305 Value
= &SubExpression
->Result
;
2309 // Skip the second expression on this pair.
2311 SubExpressionLink
= GetNextNode (&OpCode
->MapExpressionList
, SubExpressionLink
);
2312 if (IsNull (&OpCode
->MapExpressionList
, SubExpressionLink
)) {
2313 Status
= EFI_INVALID_PARAMETER
;
2317 // Goto the first expression on next pair.
2319 SubExpressionLink
= GetNextNode (&OpCode
->MapExpressionList
, SubExpressionLink
);
2323 // No map value is found.
2325 if (IsNull (&OpCode
->MapExpressionList
, SubExpressionLink
)) {
2326 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2327 Value
->Value
.u8
= 0;
2334 if (EFI_ERROR (Status
)) {
2338 Status
= PushExpression (Value
);
2339 if (EFI_ERROR (Status
)) {
2345 // Pop the final result from expression stack
2348 Status
= PopExpression (Value
);
2349 if (EFI_ERROR (Status
)) {
2354 // After evaluating an expression, there should be only one value left on the expression stack
2356 if (PopExpression (Value
) != EFI_ACCESS_DENIED
) {
2357 Status
= EFI_INVALID_PARAMETER
;
2361 RestoreExpressionEvaluationStackOffset (StackOffset
);
2362 if (!EFI_ERROR (Status
)) {
2363 CopyMem (&Expression
->Result
, Value
, sizeof (EFI_HII_VALUE
));