2 Utility functions for expression evaluation.
4 Copyright (c) 2007 - 2008, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 // Global stack used to evaluate boolean expresions
21 EFI_HII_VALUE
*mOpCodeScopeStack
= NULL
;
22 EFI_HII_VALUE
*mOpCodeScopeStackEnd
= NULL
;
23 EFI_HII_VALUE
*mOpCodeScopeStackPointer
= NULL
;
25 EFI_HII_VALUE
*mExpressionEvaluationStack
= NULL
;
26 EFI_HII_VALUE
*mExpressionEvaluationStackEnd
= NULL
;
27 EFI_HII_VALUE
*mExpressionEvaluationStackPointer
= NULL
;
30 // Unicode collation protocol interface
32 EFI_UNICODE_COLLATION_PROTOCOL
*mUnicodeCollation
= NULL
;
36 Grow size of the stack.
38 This is an internal function.
40 @param Stack On input: old stack; On output: new stack
41 @param StackPtr On input: old stack pointer; On output: new stack
43 @param StackEnd On input: old stack end; On output: new stack end
45 @retval EFI_SUCCESS Grow stack success.
46 @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.
51 IN OUT EFI_HII_VALUE
**Stack
,
52 IN OUT EFI_HII_VALUE
**StackPtr
,
53 IN OUT EFI_HII_VALUE
**StackEnd
57 EFI_HII_VALUE
*NewStack
;
59 Size
= EXPRESSION_STACK_SIZE_INCREMENT
;
60 if (*StackPtr
!= NULL
) {
61 Size
= Size
+ (*StackEnd
- *Stack
);
64 NewStack
= AllocatePool (Size
* sizeof (EFI_HII_VALUE
));
65 if (NewStack
== NULL
) {
66 return EFI_OUT_OF_RESOURCES
;
69 if (*StackPtr
!= NULL
) {
71 // Copy from Old Stack to the New Stack
76 (*StackEnd
- *Stack
) * sizeof (EFI_HII_VALUE
)
82 gBS
->FreePool (*Stack
);
86 // Make the Stack pointer point to the old data in the new stack
88 *StackPtr
= NewStack
+ (*StackPtr
- *Stack
);
90 *StackEnd
= NewStack
+ Size
;
97 Push an element onto the Boolean Stack.
99 @param Stack On input: old stack; On output: new stack
100 @param StackPtr On input: old stack pointer; On output: new stack
102 @param StackEnd On input: old stack end; On output: new stack end
103 @param Data Data to push.
105 @retval EFI_SUCCESS Push stack success.
110 IN OUT EFI_HII_VALUE
**Stack
,
111 IN OUT EFI_HII_VALUE
**StackPtr
,
112 IN OUT EFI_HII_VALUE
**StackEnd
,
113 IN EFI_HII_VALUE
*Data
119 // Check for a stack overflow condition
121 if (*StackPtr
>= *StackEnd
) {
125 Status
= GrowStack (Stack
, StackPtr
, StackEnd
);
126 if (EFI_ERROR (Status
)) {
132 // Push the item onto the stack
134 CopyMem (*StackPtr
, Data
, sizeof (EFI_HII_VALUE
));
135 *StackPtr
= *StackPtr
+ 1;
142 Pop an element from the stack.
144 @param Stack On input: old stack; On output: new stack
145 @param StackPtr On input: old stack pointer; On output: new stack
147 @param StackEnd On input: old stack end; On output: new stack end
148 @param Data Data to pop.
150 @retval EFI_SUCCESS The value was popped onto the stack.
151 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
156 IN OUT EFI_HII_VALUE
**Stack
,
157 IN OUT EFI_HII_VALUE
**StackPtr
,
158 IN OUT EFI_HII_VALUE
**StackEnd
,
159 OUT EFI_HII_VALUE
*Data
163 // Check for a stack underflow condition
165 if (*StackPtr
== *Stack
) {
166 return EFI_ACCESS_DENIED
;
170 // Pop the item off the stack
172 *StackPtr
= *StackPtr
- 1;
173 CopyMem (Data
, *StackPtr
, sizeof (EFI_HII_VALUE
));
179 Reset stack pointer to begin of the stack.
187 mOpCodeScopeStackPointer
= mOpCodeScopeStack
;
192 Push an Operand onto the Stack
194 @param Operand Operand to push.
196 @retval EFI_SUCCESS The value was pushed onto the stack.
197 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
208 Data
.Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
209 Data
.Value
.u8
= Operand
;
213 &mOpCodeScopeStackPointer
,
214 &mOpCodeScopeStackEnd
,
221 Pop an Operand from the Stack
223 @param Operand Operand to pop.
225 @retval EFI_SUCCESS The value was pushed onto the stack.
226 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
240 &mOpCodeScopeStackPointer
,
241 &mOpCodeScopeStackEnd
,
245 *Operand
= Data
.Value
.u8
;
252 Reset stack pointer to begin of the stack.
256 ResetExpressionStack (
260 mExpressionEvaluationStackPointer
= mExpressionEvaluationStack
;
265 Push an Expression value onto the Stack
267 @param Value Expression value to push.
269 @retval EFI_SUCCESS The value was pushed onto the stack.
270 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
276 IN EFI_HII_VALUE
*Value
280 &mExpressionEvaluationStack
,
281 &mExpressionEvaluationStackPointer
,
282 &mExpressionEvaluationStackEnd
,
289 Pop an Expression value from the stack.
291 @param Value Expression value to pop.
293 @retval EFI_SUCCESS The value was popped onto the stack.
294 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
299 OUT EFI_HII_VALUE
*Value
303 &mExpressionEvaluationStack
,
304 &mExpressionEvaluationStackPointer
,
305 &mExpressionEvaluationStackEnd
,
312 Get Form given its FormId.
314 @param FormSet The formset which contains this form.
315 @param FormId Id of this form.
317 @retval Pointer The form.
318 @retval NULL Specified Form is not found in the formset.
323 IN FORM_BROWSER_FORMSET
*FormSet
,
328 FORM_BROWSER_FORM
*Form
;
330 Link
= GetFirstNode (&FormSet
->FormListHead
);
331 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
332 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
334 if (Form
->FormId
== FormId
) {
338 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
346 Search a Question in Form scope using its QuestionId.
348 @param Form The form which contains this Question.
349 @param QuestionId Id of this Question.
351 @retval Pointer The Question.
352 @retval NULL Specified Question not found in the form.
355 FORM_BROWSER_STATEMENT
*
357 IN FORM_BROWSER_FORM
*Form
,
362 FORM_BROWSER_STATEMENT
*Question
;
364 if (QuestionId
== 0) {
366 // The value of zero is reserved
371 Link
= GetFirstNode (&Form
->StatementListHead
);
372 while (!IsNull (&Form
->StatementListHead
, Link
)) {
373 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
375 if (Question
->QuestionId
== QuestionId
) {
379 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
387 Search a Question in Formset scope using its QuestionId.
389 @param FormSet The formset which contains this form.
390 @param Form The form which contains this Question.
391 @param QuestionId Id of this Question.
393 @retval Pointer The Question.
394 @retval NULL Specified Question not found in the form.
397 FORM_BROWSER_STATEMENT
*
399 IN FORM_BROWSER_FORMSET
*FormSet
,
400 IN FORM_BROWSER_FORM
*Form
,
405 FORM_BROWSER_STATEMENT
*Question
;
408 // Search in the form scope first
410 Question
= IdToQuestion2 (Form
, QuestionId
);
411 if (Question
!= NULL
) {
416 // Search in the formset scope
418 Link
= GetFirstNode (&FormSet
->FormListHead
);
419 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
420 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
422 Question
= IdToQuestion2 (Form
, QuestionId
);
423 if (Question
!= NULL
) {
425 // EFI variable storage may be updated by Callback() asynchronous,
426 // to keep synchronous, always reload the Question Value.
428 if (Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
429 GetQuestionValue (FormSet
, Form
, Question
, FALSE
);
435 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
443 Get Expression given its RuleId.
445 @param Form The form which contains this Expression.
446 @param RuleId Id of this Expression.
448 @retval Pointer The Expression.
449 @retval NULL Specified Expression not found in the form.
454 IN FORM_BROWSER_FORM
*Form
,
459 FORM_EXPRESSION
*Expression
;
461 Link
= GetFirstNode (&Form
->ExpressionListHead
);
462 while (!IsNull (&Form
->ExpressionListHead
, Link
)) {
463 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
465 if (Expression
->Type
== EFI_HII_EXPRESSION_RULE
&& Expression
->RuleId
== RuleId
) {
469 Link
= GetNextNode (&Form
->ExpressionListHead
, Link
);
477 Locate the Unicode Collation Protocol interface for later use.
479 @retval EFI_SUCCESS Protocol interface initialize success.
480 @retval Other Protocol interface initialize failed.
484 InitializeUnicodeCollationProtocol (
490 if (mUnicodeCollation
!= NULL
) {
495 // BUGBUG: Proper impelmentation is to locate all Unicode Collation Protocol
496 // instances first and then select one which support English language.
497 // Current implementation just pick the first instance.
499 Status
= gBS
->LocateProtocol (
500 &gEfiUnicodeCollation2ProtocolGuid
,
502 (VOID
**) &mUnicodeCollation
508 Convert the input Unicode character to upper.
510 @param String Th Unicode character to be converted.
518 while (*String
!= 0) {
519 if ((*String
>= 'a') && (*String
<= 'z')) {
520 *String
= (UINT16
) ((*String
) & ((UINT16
) ~0x20));
528 Evaluate opcode EFI_IFR_TO_STRING.
530 @param FormSet Formset which contains this opcode.
531 @param Format String format in EFI_IFR_TO_STRING.
532 @param Result Evaluation result for this opcode.
534 @retval EFI_SUCCESS Opcode evaluation success.
535 @retval Other Opcode evaluation failed.
540 IN FORM_BROWSER_FORMSET
*FormSet
,
542 OUT EFI_HII_VALUE
*Result
549 CHAR16 Buffer
[MAXIMUM_VALUE_CHARACTERS
];
552 Status
= PopExpression (&Value
);
553 if (EFI_ERROR (Status
)) {
557 switch (Value
.Type
) {
558 case EFI_IFR_TYPE_NUM_SIZE_8
:
559 case EFI_IFR_TYPE_NUM_SIZE_16
:
560 case EFI_IFR_TYPE_NUM_SIZE_32
:
561 case EFI_IFR_TYPE_NUM_SIZE_64
:
562 BufferSize
= MAXIMUM_VALUE_CHARACTERS
* sizeof (CHAR16
);
564 case EFI_IFR_STRING_UNSIGNED_DEC
:
565 case EFI_IFR_STRING_SIGNED_DEC
:
566 PrintFormat
= L
"%ld";
569 case EFI_IFR_STRING_LOWERCASE_HEX
:
570 PrintFormat
= L
"%lx";
573 case EFI_IFR_STRING_UPPERCASE_HEX
:
574 PrintFormat
= L
"%lX";
578 return EFI_UNSUPPORTED
;
580 UnicodeSPrint (Buffer
, BufferSize
, PrintFormat
, Value
.Value
.u64
);
584 case EFI_IFR_TYPE_STRING
:
585 CopyMem (Result
, &Value
, sizeof (EFI_HII_VALUE
));
588 case EFI_IFR_TYPE_BOOLEAN
:
589 String
= (Value
.Value
.b
) ? L
"True" : L
"False";
593 return EFI_UNSUPPORTED
;
596 Result
->Type
= EFI_IFR_TYPE_STRING
;
597 Result
->Value
.string
= NewString (String
, FormSet
->HiiHandle
);
603 Evaluate opcode EFI_IFR_TO_UINT.
605 @param FormSet Formset which contains this opcode.
606 @param Result Evaluation result for this opcode.
608 @retval EFI_SUCCESS Opcode evaluation success.
609 @retval Other Opcode evaluation failed.
614 IN FORM_BROWSER_FORMSET
*FormSet
,
615 OUT EFI_HII_VALUE
*Result
624 Status
= PopExpression (&Value
);
625 if (EFI_ERROR (Status
)) {
629 if (Value
.Type
>= EFI_IFR_TYPE_OTHER
) {
630 return EFI_UNSUPPORTED
;
633 Status
= EFI_SUCCESS
;
634 if (Value
.Type
== EFI_IFR_TYPE_STRING
) {
635 String
= GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
636 if (String
== NULL
) {
637 return EFI_NOT_FOUND
;
640 IfrStrToUpper (String
);
641 StringPtr
= StrStr (String
, L
"0X");
642 if (StringPtr
!= NULL
) {
646 BufferSize
= sizeof (UINT64
);
647 Status
= HexStringToBuf ((UINT8
*) &Result
->Value
.u64
, &BufferSize
, StringPtr
+ 2, NULL
);
650 // BUGBUG: Need handle decimal string
653 gBS
->FreePool (String
);
655 CopyMem (Result
, &Value
, sizeof (EFI_HII_VALUE
));
658 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
664 Evaluate opcode EFI_IFR_CATENATE.
666 @param FormSet Formset which contains this opcode.
667 @param Result Evaluation result for this opcode.
669 @retval EFI_SUCCESS Opcode evaluation success.
670 @retval Other Opcode evaluation failed.
675 IN FORM_BROWSER_FORMSET
*FormSet
,
676 OUT EFI_HII_VALUE
*Result
687 // String[0] - The second string
688 // String[1] - The first string
693 Status
= EFI_SUCCESS
;
695 for (Index
= 0; Index
< 2; Index
++) {
696 Status
= PopExpression (&Value
);
697 if (EFI_ERROR (Status
)) {
701 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
702 Status
= EFI_UNSUPPORTED
;
706 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
708 Status
= EFI_NOT_FOUND
;
713 Size
= StrSize (String
[0]);
714 StringPtr
= AllocatePool (StrSize (String
[1]) + Size
);
715 ASSERT (StringPtr
!= NULL
);
716 StrCpy (StringPtr
, String
[1]);
717 StrCat (StringPtr
, String
[0]);
719 Result
->Type
= EFI_IFR_TYPE_STRING
;
720 Result
->Value
.string
= NewString (StringPtr
, FormSet
->HiiHandle
);
723 if (String
[0] != NULL
) {
724 FreePool (String
[0]);
726 if (String
[1] != NULL
) {
727 FreePool (String
[1]);
729 if (StringPtr
!= NULL
) {
730 FreePool (StringPtr
);
738 Evaluate opcode EFI_IFR_MATCH.
740 @param FormSet Formset which contains this opcode.
741 @param Result Evaluation result for this opcode.
743 @retval EFI_SUCCESS Opcode evaluation success.
744 @retval Other Opcode evaluation failed.
749 IN FORM_BROWSER_FORMSET
*FormSet
,
750 OUT EFI_HII_VALUE
*Result
759 // String[0] - The string to search
760 // String[1] - pattern
764 Status
= EFI_SUCCESS
;
765 for (Index
= 0; Index
< 2; Index
++) {
766 Status
= PopExpression (&Value
);
767 if (EFI_ERROR (Status
)) {
771 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
772 Status
= EFI_UNSUPPORTED
;
776 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
778 Status
= EFI_NOT_FOUND
;
783 Result
->Type
= EFI_IFR_TYPE_BOOLEAN
;
784 Result
->Value
.b
= mUnicodeCollation
->MetaiMatch (mUnicodeCollation
, String
[0], String
[1]);
787 if (String
[0] != NULL
) {
788 FreePool (String
[0]);
790 if (String
[1] != NULL
) {
791 FreePool (String
[1]);
799 Evaluate opcode EFI_IFR_FIND.
801 @param FormSet Formset which contains this opcode.
802 @param Format Case sensitive or insensitive.
803 @param Result Evaluation result for this opcode.
805 @retval EFI_SUCCESS Opcode evaluation success.
806 @retval Other Opcode evaluation failed.
811 IN FORM_BROWSER_FORMSET
*FormSet
,
813 OUT EFI_HII_VALUE
*Result
823 if (Format
> EFI_IFR_FF_CASE_INSENSITIVE
) {
824 return EFI_UNSUPPORTED
;
827 Status
= PopExpression (&Value
);
828 if (EFI_ERROR (Status
)) {
831 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
832 return EFI_UNSUPPORTED
;
834 Base
= (UINTN
) Value
.Value
.u64
;
837 // String[0] - sub-string
838 // String[1] - The string to search
842 for (Index
= 0; Index
< 2; Index
++) {
843 Status
= PopExpression (&Value
);
844 if (EFI_ERROR (Status
)) {
848 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
849 Status
= EFI_UNSUPPORTED
;
853 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
855 Status
= EFI_NOT_FOUND
;
859 if (Format
== EFI_IFR_FF_CASE_INSENSITIVE
) {
861 // Case insensitive, convert both string to upper case
863 IfrStrToUpper (String
[Index
]);
867 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
868 if (Base
>= StrLen (String
[1])) {
869 Result
->Value
.u64
= 0xFFFFFFFFFFFFFFFFULL
;
871 StringPtr
= StrStr (String
[1] + Base
, String
[0]);
872 Result
->Value
.u64
= (StringPtr
== NULL
) ? 0xFFFFFFFFFFFFFFFFULL
: (StringPtr
- String
[1]);
876 if (String
[0] != NULL
) {
877 FreePool (String
[0]);
879 if (String
[1] != NULL
) {
880 FreePool (String
[1]);
888 Evaluate opcode EFI_IFR_MID.
890 @param FormSet Formset which contains this opcode.
891 @param Result Evaluation result for this opcode.
893 @retval EFI_SUCCESS Opcode evaluation success.
894 @retval Other Opcode evaluation failed.
899 IN FORM_BROWSER_FORMSET
*FormSet
,
900 OUT EFI_HII_VALUE
*Result
910 Status
= PopExpression (&Value
);
911 if (EFI_ERROR (Status
)) {
914 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
915 return EFI_UNSUPPORTED
;
917 Length
= (UINTN
) Value
.Value
.u64
;
919 Status
= PopExpression (&Value
);
920 if (EFI_ERROR (Status
)) {
923 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
924 return EFI_UNSUPPORTED
;
926 Base
= (UINTN
) Value
.Value
.u64
;
928 Status
= PopExpression (&Value
);
929 if (EFI_ERROR (Status
)) {
932 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
933 return EFI_UNSUPPORTED
;
935 String
= GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
936 if (String
== NULL
) {
937 return EFI_NOT_FOUND
;
940 if (Length
== 0 || Base
>= StrLen (String
)) {
941 SubString
= gEmptyString
;
943 SubString
= String
+ Base
;
944 if ((Base
+ Length
) < StrLen (String
)) {
945 SubString
[Length
] = L
'\0';
949 Result
->Type
= EFI_IFR_TYPE_STRING
;
950 Result
->Value
.string
= NewString (SubString
, FormSet
->HiiHandle
);
952 gBS
->FreePool (String
);
959 Evaluate opcode EFI_IFR_TOKEN.
961 @param FormSet Formset which contains this opcode.
962 @param Result Evaluation result for this opcode.
964 @retval EFI_SUCCESS Opcode evaluation success.
965 @retval Other Opcode evaluation failed.
970 IN FORM_BROWSER_FORMSET
*FormSet
,
971 OUT EFI_HII_VALUE
*Result
983 Status
= PopExpression (&Value
);
984 if (EFI_ERROR (Status
)) {
987 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
988 return EFI_UNSUPPORTED
;
990 Count
= (UINTN
) Value
.Value
.u64
;
993 // String[0] - Delimiter
994 // String[1] - The string to search
998 for (Index
= 0; Index
< 2; Index
++) {
999 Status
= PopExpression (&Value
);
1000 if (EFI_ERROR (Status
)) {
1004 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
1005 Status
= EFI_UNSUPPORTED
;
1009 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
1010 if (String
== NULL
) {
1011 Status
= EFI_NOT_FOUND
;
1016 Delimiter
= String
[0];
1017 SubString
= String
[1];
1019 SubString
= StrStr (SubString
, Delimiter
);
1020 if (SubString
!= NULL
) {
1022 // Skip over the delimiter
1024 SubString
= SubString
+ StrLen (Delimiter
);
1031 if (SubString
== NULL
) {
1033 // nth delimited sub-string not found, push an empty string
1035 SubString
= gEmptyString
;
1038 // Put a NULL terminator for nth delimited sub-string
1040 StringPtr
= StrStr (SubString
, Delimiter
);
1041 if (StringPtr
!= NULL
) {
1046 Result
->Type
= EFI_IFR_TYPE_STRING
;
1047 Result
->Value
.string
= NewString (SubString
, FormSet
->HiiHandle
);
1050 if (String
[0] != NULL
) {
1051 FreePool (String
[0]);
1053 if (String
[1] != NULL
) {
1054 FreePool (String
[1]);
1062 Evaluate opcode EFI_IFR_SPAN.
1064 @param FormSet Formset which contains this opcode.
1065 @param Flags FIRST_MATCHING or FIRST_NON_MATCHING.
1066 @param Result Evaluation result for this opcode.
1068 @retval EFI_SUCCESS Opcode evaluation success.
1069 @retval Other Opcode evaluation failed.
1074 IN FORM_BROWSER_FORMSET
*FormSet
,
1076 OUT EFI_HII_VALUE
*Result
1080 EFI_HII_VALUE Value
;
1088 Status
= PopExpression (&Value
);
1089 if (EFI_ERROR (Status
)) {
1092 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1093 return EFI_UNSUPPORTED
;
1095 Base
= (UINTN
) Value
.Value
.u64
;
1098 // String[0] - Charset
1099 // String[1] - The string to search
1103 for (Index
= 0; Index
< 2; Index
++) {
1104 Status
= PopExpression (&Value
);
1105 if (EFI_ERROR (Status
)) {
1109 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
1110 Status
= EFI_UNSUPPORTED
;
1114 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
1115 if (String
== NULL
) {
1116 Status
= EFI_NOT_FOUND
;
1121 if (Base
>= StrLen (String
[1])) {
1122 Status
= EFI_UNSUPPORTED
;
1127 StringPtr
= String
[1] + Base
;
1128 Charset
= String
[0];
1129 while (*StringPtr
!= 0 && !Found
) {
1131 while (Charset
[Index
] != 0) {
1132 if (*StringPtr
>= Charset
[Index
] && *StringPtr
<= Charset
[Index
+ 1]) {
1133 if (Flags
== EFI_IFR_FLAGS_FIRST_MATCHING
) {
1138 if (Flags
== EFI_IFR_FLAGS_FIRST_NON_MATCHING
) {
1144 // Skip characters pair representing low-end of a range and high-end of a range
1154 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1155 Result
->Value
.u64
= StringPtr
- String
[1];
1158 if (String
[0] != NULL
) {
1159 FreePool (String
[0]);
1161 if (String
[1] != NULL
) {
1162 FreePool (String
[1]);
1170 Zero extend integer/boolean/date/time to UINT64 for comparing.
1172 @param Value HII Value to be converted.
1177 IN EFI_HII_VALUE
*Value
1183 switch (Value
->Type
) {
1184 case EFI_IFR_TYPE_NUM_SIZE_8
:
1185 Temp
= Value
->Value
.u8
;
1188 case EFI_IFR_TYPE_NUM_SIZE_16
:
1189 Temp
= Value
->Value
.u16
;
1192 case EFI_IFR_TYPE_NUM_SIZE_32
:
1193 Temp
= Value
->Value
.u32
;
1196 case EFI_IFR_TYPE_BOOLEAN
:
1197 Temp
= Value
->Value
.b
;
1200 case EFI_IFR_TYPE_TIME
:
1201 Temp
= Value
->Value
.u32
& 0xffffff;
1204 case EFI_IFR_TYPE_DATE
:
1205 Temp
= Value
->Value
.u32
;
1212 Value
->Value
.u64
= Temp
;
1217 Compare two Hii value.
1219 @param Value1 Expression value to compare on left-hand.
1220 @param Value2 Expression value to compare on right-hand.
1221 @param HiiHandle Only required for string compare.
1223 @retval EFI_INVALID_PARAMETER Could not perform comparation on two values.
1224 @retval 0 Two operators equeal.
1225 @return Positive value if Value1 is greater than Value2.
1226 @retval Negative value if Value1 is less than Value2.
1231 IN EFI_HII_VALUE
*Value1
,
1232 IN EFI_HII_VALUE
*Value2
,
1233 IN EFI_HII_HANDLE HiiHandle OPTIONAL
1241 if (Value1
->Type
>= EFI_IFR_TYPE_OTHER
|| Value2
->Type
>= EFI_IFR_TYPE_OTHER
) {
1242 return EFI_INVALID_PARAMETER
;
1245 if (Value1
->Type
== EFI_IFR_TYPE_STRING
|| Value2
->Type
== EFI_IFR_TYPE_STRING
) {
1246 if (Value1
->Type
!= Value2
->Type
) {
1248 // Both Operator should be type of String
1250 return EFI_INVALID_PARAMETER
;
1253 if (Value1
->Value
.string
== 0 || Value2
->Value
.string
== 0) {
1255 // StringId 0 is reserved
1257 return EFI_INVALID_PARAMETER
;
1260 if (Value1
->Value
.string
== Value2
->Value
.string
) {
1264 Str1
= GetToken (Value1
->Value
.string
, HiiHandle
);
1269 return EFI_INVALID_PARAMETER
;
1272 Str2
= GetToken (Value2
->Value
.string
, HiiHandle
);
1274 gBS
->FreePool (Str1
);
1275 return EFI_INVALID_PARAMETER
;
1278 Result
= StrCmp (Str1
, Str2
);
1280 gBS
->FreePool (Str1
);
1281 gBS
->FreePool (Str2
);
1287 // Take remain types(integer, boolean, date/time) as integer
1289 Temp64
= (INT64
) (Value1
->Value
.u64
- Value2
->Value
.u64
);
1292 } else if (Temp64
< 0) {
1303 Evaluate the result of a HII expression
1305 @param FormSet FormSet associated with this expression.
1306 @param Form Form associated with this expression.
1307 @param Expression Expression to be evaluated.
1309 @retval EFI_SUCCESS The expression evaluated successfuly
1310 @retval EFI_NOT_FOUND The Question which referenced by a QuestionId
1312 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
1314 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
1315 @retval EFI_INVALID_PARAMETER Syntax error with the Expression
1319 EvaluateExpression (
1320 IN FORM_BROWSER_FORMSET
*FormSet
,
1321 IN FORM_BROWSER_FORM
*Form
,
1322 IN OUT FORM_EXPRESSION
*Expression
1327 EXPRESSION_OPCODE
*OpCode
;
1328 FORM_BROWSER_STATEMENT
*Question
;
1329 FORM_BROWSER_STATEMENT
*Question2
;
1331 EFI_HII_VALUE Data1
;
1332 EFI_HII_VALUE Data2
;
1333 EFI_HII_VALUE Data3
;
1334 FORM_EXPRESSION
*RuleExpression
;
1335 EFI_HII_VALUE
*Value
;
1341 // Always reset the stack before evaluating an Expression
1343 ResetExpressionStack ();
1345 Expression
->Result
.Type
= EFI_IFR_TYPE_OTHER
;
1347 Link
= GetFirstNode (&Expression
->OpCodeListHead
);
1348 while (!IsNull (&Expression
->OpCodeListHead
, Link
)) {
1349 OpCode
= EXPRESSION_OPCODE_FROM_LINK (Link
);
1351 Link
= GetNextNode (&Expression
->OpCodeListHead
, Link
);
1353 ZeroMem (&Data1
, sizeof (EFI_HII_VALUE
));
1354 ZeroMem (&Data2
, sizeof (EFI_HII_VALUE
));
1355 ZeroMem (&Data3
, sizeof (EFI_HII_VALUE
));
1358 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
1359 Status
= EFI_SUCCESS
;
1361 switch (OpCode
->Operand
) {
1363 // Built-in functions
1365 case EFI_IFR_EQ_ID_VAL_OP
:
1366 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
1367 if (Question
== NULL
) {
1368 return EFI_NOT_FOUND
;
1371 Result
= CompareHiiValue (&Question
->HiiValue
, &OpCode
->Value
, NULL
);
1372 if (Result
== EFI_INVALID_PARAMETER
) {
1373 return EFI_INVALID_PARAMETER
;
1375 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
1378 case EFI_IFR_EQ_ID_ID_OP
:
1379 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
1380 if (Question
== NULL
) {
1381 return EFI_NOT_FOUND
;
1384 Question2
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId2
);
1385 if (Question2
== NULL
) {
1386 return EFI_NOT_FOUND
;
1389 Result
= CompareHiiValue (&Question
->HiiValue
, &Question2
->HiiValue
, FormSet
->HiiHandle
);
1390 if (Result
== EFI_INVALID_PARAMETER
) {
1391 return EFI_INVALID_PARAMETER
;
1393 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
1396 case EFI_IFR_EQ_ID_LIST_OP
:
1397 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
1398 if (Question
== NULL
) {
1399 return EFI_NOT_FOUND
;
1402 Value
->Value
.b
= FALSE
;
1403 for (Index
=0; Index
< OpCode
->ListLength
; Index
++) {
1404 if (Question
->HiiValue
.Value
.u16
== OpCode
->ValueList
[Index
]) {
1405 Value
->Value
.b
= TRUE
;
1411 case EFI_IFR_DUP_OP
:
1412 Status
= PopExpression (Value
);
1413 if (EFI_ERROR (Status
)) {
1417 Status
= PushExpression (Value
);
1420 case EFI_IFR_QUESTION_REF1_OP
:
1421 case EFI_IFR_THIS_OP
:
1422 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
1423 if (Question
== NULL
) {
1424 return EFI_NOT_FOUND
;
1427 Value
= &Question
->HiiValue
;
1430 case EFI_IFR_QUESTION_REF3_OP
:
1431 if (OpCode
->DevicePath
== 0) {
1433 // EFI_IFR_QUESTION_REF3
1434 // Pop an expression from the expression stack
1436 Status
= PopExpression (Value
);
1437 if (EFI_ERROR (Status
)) {
1442 // Validate the expression value
1444 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
1445 return EFI_NOT_FOUND
;
1448 Question
= IdToQuestion (FormSet
, Form
, Value
->Value
.u16
);
1449 if (Question
== NULL
) {
1450 return EFI_NOT_FOUND
;
1454 // push the questions' value on to the expression stack
1456 Value
= &Question
->HiiValue
;
1459 // BUGBUG: push 0 for EFI_IFR_QUESTION_REF3_2 and EFI_IFR_QUESTION_REF3_3,
1460 // since it is impractical to evaluate the value of a Question in another
1461 // Hii Package list.
1463 ZeroMem (Value
, sizeof (EFI_HII_VALUE
));
1467 case EFI_IFR_RULE_REF_OP
:
1469 // Find expression for this rule
1471 RuleExpression
= RuleIdToExpression (Form
, OpCode
->RuleId
);
1472 if (RuleExpression
== NULL
) {
1473 return EFI_NOT_FOUND
;
1477 // Evaluate this rule expression
1479 Status
= EvaluateExpression (FormSet
, Form
, RuleExpression
);
1480 if (EFI_ERROR (Status
)) {
1484 Value
= &RuleExpression
->Result
;
1487 case EFI_IFR_STRING_REF1_OP
:
1488 Value
->Type
= EFI_IFR_TYPE_STRING
;
1489 Value
->Value
.string
= OpCode
->Value
.Value
.string
;
1495 case EFI_IFR_TRUE_OP
:
1496 case EFI_IFR_FALSE_OP
:
1497 case EFI_IFR_ONE_OP
:
1498 case EFI_IFR_ONES_OP
:
1499 case EFI_IFR_UINT8_OP
:
1500 case EFI_IFR_UINT16_OP
:
1501 case EFI_IFR_UINT32_OP
:
1502 case EFI_IFR_UINT64_OP
:
1503 case EFI_IFR_UNDEFINED_OP
:
1504 case EFI_IFR_VERSION_OP
:
1505 case EFI_IFR_ZERO_OP
:
1506 Value
= &OpCode
->Value
;
1512 case EFI_IFR_LENGTH_OP
:
1513 Status
= PopExpression (Value
);
1514 if (EFI_ERROR (Status
)) {
1517 if (Value
->Type
!= EFI_IFR_TYPE_STRING
) {
1518 return EFI_INVALID_PARAMETER
;
1521 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->HiiHandle
);
1522 if (StrPtr
== NULL
) {
1523 return EFI_INVALID_PARAMETER
;
1526 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1527 Value
->Value
.u64
= StrLen (StrPtr
);
1528 gBS
->FreePool (StrPtr
);
1531 case EFI_IFR_NOT_OP
:
1532 Status
= PopExpression (Value
);
1533 if (EFI_ERROR (Status
)) {
1536 if (Value
->Type
!= EFI_IFR_TYPE_BOOLEAN
) {
1537 return EFI_INVALID_PARAMETER
;
1539 Value
->Value
.b
= (BOOLEAN
) (!Value
->Value
.b
);
1542 case EFI_IFR_QUESTION_REF2_OP
:
1544 // Pop an expression from the expression stack
1546 Status
= PopExpression (Value
);
1547 if (EFI_ERROR (Status
)) {
1552 // Validate the expression value
1554 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
1555 return EFI_NOT_FOUND
;
1558 Question
= IdToQuestion (FormSet
, Form
, Value
->Value
.u16
);
1559 if (Question
== NULL
) {
1560 return EFI_NOT_FOUND
;
1563 Value
= &Question
->HiiValue
;
1566 case EFI_IFR_STRING_REF2_OP
:
1568 // Pop an expression from the expression stack
1570 Status
= PopExpression (Value
);
1571 if (EFI_ERROR (Status
)) {
1576 // Validate the expression value
1578 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
1579 return EFI_NOT_FOUND
;
1582 Value
->Type
= EFI_IFR_TYPE_STRING
;
1583 StrPtr
= GetToken (Value
->Value
.u16
, FormSet
->HiiHandle
);
1584 if (StrPtr
== NULL
) {
1586 // If String not exit, push an empty string
1588 Value
->Value
.string
= NewString (gEmptyString
, FormSet
->HiiHandle
);
1590 Index
= (UINT16
) Value
->Value
.u64
;
1591 Value
->Value
.string
= Index
;
1592 gBS
->FreePool (StrPtr
);
1596 case EFI_IFR_TO_BOOLEAN_OP
:
1598 // Pop an expression from the expression stack
1600 Status
= PopExpression (Value
);
1601 if (EFI_ERROR (Status
)) {
1606 // Convert an expression to a Boolean
1608 if (Value
->Type
<= EFI_IFR_TYPE_DATE
) {
1610 // When converting from an unsigned integer, zero will be converted to
1611 // FALSE and any other value will be converted to TRUE.
1613 Value
->Value
.b
= (BOOLEAN
) ((Value
->Value
.u64
) ? TRUE
: FALSE
);
1615 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
1616 } else if (Value
->Type
== EFI_IFR_TYPE_STRING
) {
1618 // When converting from a string, if case-insensitive compare
1619 // with "true" is True, then push True. If a case-insensitive compare
1620 // with "false" is True, then push False.
1622 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->HiiHandle
);
1623 if (StrPtr
== NULL
) {
1624 return EFI_INVALID_PARAMETER
;
1627 if ((StrCmp (StrPtr
, L
"true") == 0) || (StrCmp (StrPtr
, L
"false") == 0)){
1628 Value
->Value
.b
= TRUE
;
1630 Value
->Value
.b
= FALSE
;
1632 gBS
->FreePool (StrPtr
);
1633 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
1637 case EFI_IFR_TO_STRING_OP
:
1638 Status
= IfrToString (FormSet
, OpCode
->Format
, Value
);
1641 case EFI_IFR_TO_UINT_OP
:
1642 Status
= IfrToUint (FormSet
, Value
);
1645 case EFI_IFR_TO_LOWER_OP
:
1646 case EFI_IFR_TO_UPPER_OP
:
1647 Status
= InitializeUnicodeCollationProtocol ();
1648 if (EFI_ERROR (Status
)) {
1652 Status
= PopExpression (Value
);
1653 if (EFI_ERROR (Status
)) {
1657 if (Value
->Type
!= EFI_IFR_TYPE_STRING
) {
1658 return EFI_UNSUPPORTED
;
1661 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->HiiHandle
);
1662 if (StrPtr
== NULL
) {
1663 return EFI_NOT_FOUND
;
1666 if (OpCode
->Operand
== EFI_IFR_TO_LOWER_OP
) {
1667 mUnicodeCollation
->StrLwr (mUnicodeCollation
, StrPtr
);
1669 mUnicodeCollation
->StrUpr (mUnicodeCollation
, StrPtr
);
1671 Value
->Value
.string
= NewString (StrPtr
, FormSet
->HiiHandle
);
1672 gBS
->FreePool (StrPtr
);
1675 case EFI_IFR_BITWISE_NOT_OP
:
1677 // Pop an expression from the expression stack
1679 Status
= PopExpression (Value
);
1680 if (EFI_ERROR (Status
)) {
1683 if (Value
->Type
> EFI_IFR_TYPE_DATE
) {
1684 return EFI_INVALID_PARAMETER
;
1687 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1688 Value
->Value
.u64
= ~Value
->Value
.u64
;
1694 case EFI_IFR_ADD_OP
:
1695 case EFI_IFR_SUBTRACT_OP
:
1696 case EFI_IFR_MULTIPLY_OP
:
1697 case EFI_IFR_DIVIDE_OP
:
1698 case EFI_IFR_MODULO_OP
:
1699 case EFI_IFR_BITWISE_AND_OP
:
1700 case EFI_IFR_BITWISE_OR_OP
:
1701 case EFI_IFR_SHIFT_LEFT_OP
:
1702 case EFI_IFR_SHIFT_RIGHT_OP
:
1704 // Pop an expression from the expression stack
1706 Status
= PopExpression (&Data2
);
1707 if (EFI_ERROR (Status
)) {
1710 if (Data2
.Type
> EFI_IFR_TYPE_DATE
) {
1711 return EFI_INVALID_PARAMETER
;
1715 // Pop another expression from the expression stack
1717 Status
= PopExpression (&Data1
);
1718 if (EFI_ERROR (Status
)) {
1721 if (Data1
.Type
> EFI_IFR_TYPE_DATE
) {
1722 return EFI_INVALID_PARAMETER
;
1725 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1727 switch (OpCode
->Operand
) {
1728 case EFI_IFR_ADD_OP
:
1729 Value
->Value
.u64
= Data1
.Value
.u64
+ Data2
.Value
.u64
;
1732 case EFI_IFR_SUBTRACT_OP
:
1733 Value
->Value
.u64
= Data1
.Value
.u64
- Data2
.Value
.u64
;
1736 case EFI_IFR_MULTIPLY_OP
:
1737 Value
->Value
.u64
= MultU64x32 (Data1
.Value
.u64
, (UINT32
) Data2
.Value
.u64
);
1740 case EFI_IFR_DIVIDE_OP
:
1741 Value
->Value
.u64
= DivU64x32 (Data1
.Value
.u64
, (UINT32
) Data2
.Value
.u64
);
1744 case EFI_IFR_MODULO_OP
:
1745 DivU64x32Remainder (Data1
.Value
.u64
, (UINT32
) Data2
.Value
.u64
, &TempValue
);
1746 Value
->Value
.u64
= TempValue
;
1749 case EFI_IFR_BITWISE_AND_OP
:
1750 Value
->Value
.u64
= Data1
.Value
.u64
& Data2
.Value
.u64
;
1753 case EFI_IFR_BITWISE_OR_OP
:
1754 Value
->Value
.u64
= Data1
.Value
.u64
| Data2
.Value
.u64
;
1757 case EFI_IFR_SHIFT_LEFT_OP
:
1758 Value
->Value
.u64
= LShiftU64 (Data1
.Value
.u64
, (UINTN
) Data2
.Value
.u64
);
1761 case EFI_IFR_SHIFT_RIGHT_OP
:
1762 Value
->Value
.u64
= RShiftU64 (Data1
.Value
.u64
, (UINTN
) Data2
.Value
.u64
);
1770 case EFI_IFR_AND_OP
:
1773 // Two Boolean operator
1775 Status
= PopExpression (&Data2
);
1776 if (EFI_ERROR (Status
)) {
1779 if (Data2
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
1780 return EFI_INVALID_PARAMETER
;
1784 // Pop another expression from the expression stack
1786 Status
= PopExpression (&Data1
);
1787 if (EFI_ERROR (Status
)) {
1790 if (Data1
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
1791 return EFI_INVALID_PARAMETER
;
1794 if (OpCode
->Operand
== EFI_IFR_AND_OP
) {
1795 Value
->Value
.b
= (BOOLEAN
) (Data1
.Value
.b
&& Data2
.Value
.b
);
1797 Value
->Value
.b
= (BOOLEAN
) (Data1
.Value
.b
|| Data2
.Value
.b
);
1801 case EFI_IFR_EQUAL_OP
:
1802 case EFI_IFR_NOT_EQUAL_OP
:
1803 case EFI_IFR_GREATER_EQUAL_OP
:
1804 case EFI_IFR_GREATER_THAN_OP
:
1805 case EFI_IFR_LESS_EQUAL_OP
:
1806 case EFI_IFR_LESS_THAN_OP
:
1808 // Compare two integer, string, boolean or date/time
1810 Status
= PopExpression (&Data2
);
1811 if (EFI_ERROR (Status
)) {
1814 if (Data2
.Type
> EFI_IFR_TYPE_BOOLEAN
&& Data2
.Type
!= EFI_IFR_TYPE_STRING
) {
1815 return EFI_INVALID_PARAMETER
;
1819 // Pop another expression from the expression stack
1821 Status
= PopExpression (&Data1
);
1822 if (EFI_ERROR (Status
)) {
1826 Result
= CompareHiiValue (&Data1
, &Data2
, FormSet
->HiiHandle
);
1827 if (Result
== EFI_INVALID_PARAMETER
) {
1828 return EFI_INVALID_PARAMETER
;
1831 switch (OpCode
->Operand
) {
1832 case EFI_IFR_EQUAL_OP
:
1833 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
1836 case EFI_IFR_NOT_EQUAL_OP
:
1837 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
1840 case EFI_IFR_GREATER_EQUAL_OP
:
1841 Value
->Value
.b
= (BOOLEAN
) ((Result
>= 0) ? TRUE
: FALSE
);
1844 case EFI_IFR_GREATER_THAN_OP
:
1845 Value
->Value
.b
= (BOOLEAN
) ((Result
> 0) ? TRUE
: FALSE
);
1848 case EFI_IFR_LESS_EQUAL_OP
:
1849 Value
->Value
.b
= (BOOLEAN
) ((Result
<= 0) ? TRUE
: FALSE
);
1852 case EFI_IFR_LESS_THAN_OP
:
1853 Value
->Value
.b
= (BOOLEAN
) ((Result
< 0) ? TRUE
: FALSE
);
1861 case EFI_IFR_MATCH_OP
:
1862 Status
= IfrMatch (FormSet
, Value
);
1865 case EFI_IFR_CATENATE_OP
:
1866 Status
= IfrCatenate (FormSet
, Value
);
1872 case EFI_IFR_CONDITIONAL_OP
:
1874 // Pop third expression from the expression stack
1876 Status
= PopExpression (&Data3
);
1877 if (EFI_ERROR (Status
)) {
1882 // Pop second expression from the expression stack
1884 Status
= PopExpression (&Data2
);
1885 if (EFI_ERROR (Status
)) {
1890 // Pop first expression from the expression stack
1892 Status
= PopExpression (&Data1
);
1893 if (EFI_ERROR (Status
)) {
1896 if (Data1
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
1897 return EFI_INVALID_PARAMETER
;
1900 if (Data1
.Value
.b
) {
1907 case EFI_IFR_FIND_OP
:
1908 Status
= IfrFind (FormSet
, OpCode
->Format
, Value
);
1911 case EFI_IFR_MID_OP
:
1912 Status
= IfrMid (FormSet
, Value
);
1915 case EFI_IFR_TOKEN_OP
:
1916 Status
= IfrToken (FormSet
, Value
);
1919 case EFI_IFR_SPAN_OP
:
1920 Status
= IfrSpan (FormSet
, OpCode
->Flags
, Value
);
1926 if (EFI_ERROR (Status
)) {
1930 Status
= PushExpression (Value
);
1931 if (EFI_ERROR (Status
)) {
1937 // Pop the final result from expression stack
1940 Status
= PopExpression (Value
);
1941 if (EFI_ERROR (Status
)) {
1946 // After evaluating an expression, there should be only one value left on the expression stack
1948 if (PopExpression (Value
) != EFI_ACCESS_DENIED
) {
1949 return EFI_INVALID_PARAMETER
;
1952 CopyMem (&Expression
->Result
, Value
, sizeof (EFI_HII_VALUE
));