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
)
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
623 Status
= PopExpression (&Value
);
624 if (EFI_ERROR (Status
)) {
628 if (Value
.Type
>= EFI_IFR_TYPE_OTHER
) {
629 return EFI_UNSUPPORTED
;
632 Status
= EFI_SUCCESS
;
633 if (Value
.Type
== EFI_IFR_TYPE_STRING
) {
634 String
= GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
635 if (String
== NULL
) {
636 return EFI_NOT_FOUND
;
639 IfrStrToUpper (String
);
640 StringPtr
= StrStr (String
, L
"0X");
641 if (StringPtr
!= NULL
) {
645 Result
->Value
.u64
= StrHexToUint64 (String
);
650 Result
->Value
.u64
= StrDecimalToUint64 (String
);
654 CopyMem (Result
, &Value
, sizeof (EFI_HII_VALUE
));
657 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
663 Evaluate opcode EFI_IFR_CATENATE.
665 @param FormSet Formset which contains this opcode.
666 @param Result Evaluation result for this opcode.
668 @retval EFI_SUCCESS Opcode evaluation success.
669 @retval Other Opcode evaluation failed.
674 IN FORM_BROWSER_FORMSET
*FormSet
,
675 OUT EFI_HII_VALUE
*Result
686 // String[0] - The second string
687 // String[1] - The first string
692 Status
= EFI_SUCCESS
;
694 for (Index
= 0; Index
< 2; Index
++) {
695 Status
= PopExpression (&Value
);
696 if (EFI_ERROR (Status
)) {
700 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
701 Status
= EFI_UNSUPPORTED
;
705 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
706 if (String
[Index
] == NULL
) {
707 Status
= EFI_NOT_FOUND
;
712 Size
= StrSize (String
[0]);
713 StringPtr
= AllocatePool (StrSize (String
[1]) + Size
);
714 ASSERT (StringPtr
!= NULL
);
715 StrCpy (StringPtr
, String
[1]);
716 StrCat (StringPtr
, String
[0]);
718 Result
->Type
= EFI_IFR_TYPE_STRING
;
719 Result
->Value
.string
= NewString (StringPtr
, FormSet
->HiiHandle
);
722 if (String
[0] != NULL
) {
723 FreePool (String
[0]);
725 if (String
[1] != NULL
) {
726 FreePool (String
[1]);
728 if (StringPtr
!= NULL
) {
729 FreePool (StringPtr
);
737 Evaluate opcode EFI_IFR_MATCH.
739 @param FormSet Formset which contains this opcode.
740 @param Result Evaluation result for this opcode.
742 @retval EFI_SUCCESS Opcode evaluation success.
743 @retval Other Opcode evaluation failed.
748 IN FORM_BROWSER_FORMSET
*FormSet
,
749 OUT EFI_HII_VALUE
*Result
758 // String[0] - The string to search
759 // String[1] - pattern
763 Status
= EFI_SUCCESS
;
764 for (Index
= 0; Index
< 2; Index
++) {
765 Status
= PopExpression (&Value
);
766 if (EFI_ERROR (Status
)) {
770 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
771 Status
= EFI_UNSUPPORTED
;
775 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
776 if (String
[Index
] == NULL
) {
777 Status
= EFI_NOT_FOUND
;
782 Result
->Type
= EFI_IFR_TYPE_BOOLEAN
;
783 Result
->Value
.b
= mUnicodeCollation
->MetaiMatch (mUnicodeCollation
, String
[0], String
[1]);
786 if (String
[0] != NULL
) {
787 FreePool (String
[0]);
789 if (String
[1] != NULL
) {
790 FreePool (String
[1]);
798 Evaluate opcode EFI_IFR_FIND.
800 @param FormSet Formset which contains this opcode.
801 @param Format Case sensitive or insensitive.
802 @param Result Evaluation result for this opcode.
804 @retval EFI_SUCCESS Opcode evaluation success.
805 @retval Other Opcode evaluation failed.
810 IN FORM_BROWSER_FORMSET
*FormSet
,
812 OUT EFI_HII_VALUE
*Result
822 if (Format
> EFI_IFR_FF_CASE_INSENSITIVE
) {
823 return EFI_UNSUPPORTED
;
826 Status
= PopExpression (&Value
);
827 if (EFI_ERROR (Status
)) {
830 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
831 return EFI_UNSUPPORTED
;
833 Base
= (UINTN
) Value
.Value
.u64
;
836 // String[0] - sub-string
837 // String[1] - The string to search
841 for (Index
= 0; Index
< 2; Index
++) {
842 Status
= PopExpression (&Value
);
843 if (EFI_ERROR (Status
)) {
847 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
848 Status
= EFI_UNSUPPORTED
;
852 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
853 if (String
[Index
] == NULL
) {
854 Status
= EFI_NOT_FOUND
;
858 if (Format
== EFI_IFR_FF_CASE_INSENSITIVE
) {
860 // Case insensitive, convert both string to upper case
862 IfrStrToUpper (String
[Index
]);
866 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
867 if (Base
>= StrLen (String
[1])) {
868 Result
->Value
.u64
= 0xFFFFFFFFFFFFFFFFULL
;
870 StringPtr
= StrStr (String
[1] + Base
, String
[0]);
871 Result
->Value
.u64
= (StringPtr
== NULL
) ? 0xFFFFFFFFFFFFFFFFULL
: (StringPtr
- String
[1]);
875 if (String
[0] != NULL
) {
876 FreePool (String
[0]);
878 if (String
[1] != NULL
) {
879 FreePool (String
[1]);
887 Evaluate opcode EFI_IFR_MID.
889 @param FormSet Formset which contains this opcode.
890 @param Result Evaluation result for this opcode.
892 @retval EFI_SUCCESS Opcode evaluation success.
893 @retval Other Opcode evaluation failed.
898 IN FORM_BROWSER_FORMSET
*FormSet
,
899 OUT EFI_HII_VALUE
*Result
909 Status
= PopExpression (&Value
);
910 if (EFI_ERROR (Status
)) {
913 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
914 return EFI_UNSUPPORTED
;
916 Length
= (UINTN
) Value
.Value
.u64
;
918 Status
= PopExpression (&Value
);
919 if (EFI_ERROR (Status
)) {
922 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
923 return EFI_UNSUPPORTED
;
925 Base
= (UINTN
) Value
.Value
.u64
;
927 Status
= PopExpression (&Value
);
928 if (EFI_ERROR (Status
)) {
931 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
932 return EFI_UNSUPPORTED
;
934 String
= GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
935 if (String
== NULL
) {
936 return EFI_NOT_FOUND
;
939 if (Length
== 0 || Base
>= StrLen (String
)) {
940 SubString
= gEmptyString
;
942 SubString
= String
+ Base
;
943 if ((Base
+ Length
) < StrLen (String
)) {
944 SubString
[Length
] = L
'\0';
948 Result
->Type
= EFI_IFR_TYPE_STRING
;
949 Result
->Value
.string
= NewString (SubString
, FormSet
->HiiHandle
);
958 Evaluate opcode EFI_IFR_TOKEN.
960 @param FormSet Formset which contains this opcode.
961 @param Result Evaluation result for this opcode.
963 @retval EFI_SUCCESS Opcode evaluation success.
964 @retval Other Opcode evaluation failed.
969 IN FORM_BROWSER_FORMSET
*FormSet
,
970 OUT EFI_HII_VALUE
*Result
982 Status
= PopExpression (&Value
);
983 if (EFI_ERROR (Status
)) {
986 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
987 return EFI_UNSUPPORTED
;
989 Count
= (UINTN
) Value
.Value
.u64
;
992 // String[0] - Delimiter
993 // String[1] - The string to search
997 for (Index
= 0; Index
< 2; Index
++) {
998 Status
= PopExpression (&Value
);
999 if (EFI_ERROR (Status
)) {
1003 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
1004 Status
= EFI_UNSUPPORTED
;
1008 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
1009 if (String
[Index
] == NULL
) {
1010 Status
= EFI_NOT_FOUND
;
1015 Delimiter
= String
[0];
1016 SubString
= String
[1];
1018 SubString
= StrStr (SubString
, Delimiter
);
1019 if (SubString
!= NULL
) {
1021 // Skip over the delimiter
1023 SubString
= SubString
+ StrLen (Delimiter
);
1030 if (SubString
== NULL
) {
1032 // nth delimited sub-string not found, push an empty string
1034 SubString
= gEmptyString
;
1037 // Put a NULL terminator for nth delimited sub-string
1039 StringPtr
= StrStr (SubString
, Delimiter
);
1040 if (StringPtr
!= NULL
) {
1045 Result
->Type
= EFI_IFR_TYPE_STRING
;
1046 Result
->Value
.string
= NewString (SubString
, FormSet
->HiiHandle
);
1049 if (String
[0] != NULL
) {
1050 FreePool (String
[0]);
1052 if (String
[1] != NULL
) {
1053 FreePool (String
[1]);
1061 Evaluate opcode EFI_IFR_SPAN.
1063 @param FormSet Formset which contains this opcode.
1064 @param Flags FIRST_MATCHING or FIRST_NON_MATCHING.
1065 @param Result Evaluation result for this opcode.
1067 @retval EFI_SUCCESS Opcode evaluation success.
1068 @retval Other Opcode evaluation failed.
1073 IN FORM_BROWSER_FORMSET
*FormSet
,
1075 OUT EFI_HII_VALUE
*Result
1079 EFI_HII_VALUE Value
;
1087 Status
= PopExpression (&Value
);
1088 if (EFI_ERROR (Status
)) {
1091 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1092 return EFI_UNSUPPORTED
;
1094 Base
= (UINTN
) Value
.Value
.u64
;
1097 // String[0] - Charset
1098 // String[1] - The string to search
1102 for (Index
= 0; Index
< 2; Index
++) {
1103 Status
= PopExpression (&Value
);
1104 if (EFI_ERROR (Status
)) {
1108 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
1109 Status
= EFI_UNSUPPORTED
;
1113 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
1114 if (String
[Index
] == NULL
) {
1115 Status
= EFI_NOT_FOUND
;
1120 if (Base
>= StrLen (String
[1])) {
1121 Status
= EFI_UNSUPPORTED
;
1126 StringPtr
= String
[1] + Base
;
1127 Charset
= String
[0];
1128 while (*StringPtr
!= 0 && !Found
) {
1130 while (Charset
[Index
] != 0) {
1131 if (*StringPtr
>= Charset
[Index
] && *StringPtr
<= Charset
[Index
+ 1]) {
1132 if (Flags
== EFI_IFR_FLAGS_FIRST_MATCHING
) {
1137 if (Flags
== EFI_IFR_FLAGS_FIRST_NON_MATCHING
) {
1143 // Skip characters pair representing low-end of a range and high-end of a range
1153 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1154 Result
->Value
.u64
= StringPtr
- String
[1];
1157 if (String
[0] != NULL
) {
1158 FreePool (String
[0]);
1160 if (String
[1] != NULL
) {
1161 FreePool (String
[1]);
1169 Zero extend integer/boolean/date/time to UINT64 for comparing.
1171 @param Value HII Value to be converted.
1176 IN EFI_HII_VALUE
*Value
1182 switch (Value
->Type
) {
1183 case EFI_IFR_TYPE_NUM_SIZE_8
:
1184 Temp
= Value
->Value
.u8
;
1187 case EFI_IFR_TYPE_NUM_SIZE_16
:
1188 Temp
= Value
->Value
.u16
;
1191 case EFI_IFR_TYPE_NUM_SIZE_32
:
1192 Temp
= Value
->Value
.u32
;
1195 case EFI_IFR_TYPE_BOOLEAN
:
1196 Temp
= Value
->Value
.b
;
1199 case EFI_IFR_TYPE_TIME
:
1200 Temp
= Value
->Value
.u32
& 0xffffff;
1203 case EFI_IFR_TYPE_DATE
:
1204 Temp
= Value
->Value
.u32
;
1211 Value
->Value
.u64
= Temp
;
1216 Compare two Hii value.
1218 @param Value1 Expression value to compare on left-hand.
1219 @param Value2 Expression value to compare on right-hand.
1220 @param HiiHandle Only required for string compare.
1222 @retval EFI_INVALID_PARAMETER Could not perform comparation on two values.
1223 @retval 0 Two operators equeal.
1224 @return Positive value if Value1 is greater than Value2.
1225 @retval Negative value if Value1 is less than Value2.
1230 IN EFI_HII_VALUE
*Value1
,
1231 IN EFI_HII_VALUE
*Value2
,
1232 IN EFI_HII_HANDLE HiiHandle OPTIONAL
1240 if (Value1
->Type
>= EFI_IFR_TYPE_OTHER
|| Value2
->Type
>= EFI_IFR_TYPE_OTHER
) {
1241 return EFI_INVALID_PARAMETER
;
1244 if (Value1
->Type
== EFI_IFR_TYPE_STRING
|| Value2
->Type
== EFI_IFR_TYPE_STRING
) {
1245 if (Value1
->Type
!= Value2
->Type
) {
1247 // Both Operator should be type of String
1249 return EFI_INVALID_PARAMETER
;
1252 if (Value1
->Value
.string
== 0 || Value2
->Value
.string
== 0) {
1254 // StringId 0 is reserved
1256 return EFI_INVALID_PARAMETER
;
1259 if (Value1
->Value
.string
== Value2
->Value
.string
) {
1263 Str1
= GetToken (Value1
->Value
.string
, HiiHandle
);
1268 return EFI_INVALID_PARAMETER
;
1271 Str2
= GetToken (Value2
->Value
.string
, HiiHandle
);
1274 return EFI_INVALID_PARAMETER
;
1277 Result
= StrCmp (Str1
, Str2
);
1286 // Take remain types(integer, boolean, date/time) as integer
1288 Temp64
= (INT64
) (Value1
->Value
.u64
- Value2
->Value
.u64
);
1291 } else if (Temp64
< 0) {
1302 Evaluate the result of a HII expression.
1304 If Expression is NULL, then ASSERT.
1306 @param FormSet FormSet associated with this expression.
1307 @param Form Form associated with this expression.
1308 @param Expression Expression to be evaluated.
1310 @retval EFI_SUCCESS The expression evaluated successfuly
1311 @retval EFI_NOT_FOUND The Question which referenced by a QuestionId
1313 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
1315 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
1316 @retval EFI_INVALID_PARAMETER Syntax error with the Expression
1320 EvaluateExpression (
1321 IN FORM_BROWSER_FORMSET
*FormSet
,
1322 IN FORM_BROWSER_FORM
*Form
,
1323 IN OUT FORM_EXPRESSION
*Expression
1328 EXPRESSION_OPCODE
*OpCode
;
1329 FORM_BROWSER_STATEMENT
*Question
;
1330 FORM_BROWSER_STATEMENT
*Question2
;
1332 EFI_HII_VALUE Data1
;
1333 EFI_HII_VALUE Data2
;
1334 EFI_HII_VALUE Data3
;
1335 FORM_EXPRESSION
*RuleExpression
;
1336 EFI_HII_VALUE
*Value
;
1342 // Always reset the stack before evaluating an Expression
1344 ResetExpressionStack ();
1346 ASSERT (Expression
!= NULL
);
1347 Expression
->Result
.Type
= EFI_IFR_TYPE_OTHER
;
1349 Link
= GetFirstNode (&Expression
->OpCodeListHead
);
1350 while (!IsNull (&Expression
->OpCodeListHead
, Link
)) {
1351 OpCode
= EXPRESSION_OPCODE_FROM_LINK (Link
);
1353 Link
= GetNextNode (&Expression
->OpCodeListHead
, Link
);
1355 ZeroMem (&Data1
, sizeof (EFI_HII_VALUE
));
1356 ZeroMem (&Data2
, sizeof (EFI_HII_VALUE
));
1357 ZeroMem (&Data3
, sizeof (EFI_HII_VALUE
));
1360 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
1361 Status
= EFI_SUCCESS
;
1363 switch (OpCode
->Operand
) {
1365 // Built-in functions
1367 case EFI_IFR_EQ_ID_VAL_OP
:
1368 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
1369 if (Question
== NULL
) {
1370 return EFI_NOT_FOUND
;
1373 Result
= CompareHiiValue (&Question
->HiiValue
, &OpCode
->Value
, NULL
);
1374 if (Result
== EFI_INVALID_PARAMETER
) {
1375 return EFI_INVALID_PARAMETER
;
1377 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
1380 case EFI_IFR_EQ_ID_ID_OP
:
1381 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
1382 if (Question
== NULL
) {
1383 return EFI_NOT_FOUND
;
1386 Question2
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId2
);
1387 if (Question2
== NULL
) {
1388 return EFI_NOT_FOUND
;
1391 Result
= CompareHiiValue (&Question
->HiiValue
, &Question2
->HiiValue
, FormSet
->HiiHandle
);
1392 if (Result
== EFI_INVALID_PARAMETER
) {
1393 return EFI_INVALID_PARAMETER
;
1395 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
1398 case EFI_IFR_EQ_ID_LIST_OP
:
1399 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
1400 if (Question
== NULL
) {
1401 return EFI_NOT_FOUND
;
1404 Value
->Value
.b
= FALSE
;
1405 for (Index
=0; Index
< OpCode
->ListLength
; Index
++) {
1406 if (Question
->HiiValue
.Value
.u16
== OpCode
->ValueList
[Index
]) {
1407 Value
->Value
.b
= TRUE
;
1413 case EFI_IFR_DUP_OP
:
1414 Status
= PopExpression (Value
);
1415 if (EFI_ERROR (Status
)) {
1419 Status
= PushExpression (Value
);
1422 case EFI_IFR_QUESTION_REF1_OP
:
1423 case EFI_IFR_THIS_OP
:
1424 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
1425 if (Question
== NULL
) {
1426 return EFI_NOT_FOUND
;
1429 Value
= &Question
->HiiValue
;
1432 case EFI_IFR_QUESTION_REF3_OP
:
1433 if (OpCode
->DevicePath
== 0) {
1435 // EFI_IFR_QUESTION_REF3
1436 // Pop an expression from the expression stack
1438 Status
= PopExpression (Value
);
1439 if (EFI_ERROR (Status
)) {
1444 // Validate the expression value
1446 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
1447 return EFI_NOT_FOUND
;
1450 Question
= IdToQuestion (FormSet
, Form
, Value
->Value
.u16
);
1451 if (Question
== NULL
) {
1452 return EFI_NOT_FOUND
;
1456 // push the questions' value on to the expression stack
1458 Value
= &Question
->HiiValue
;
1461 // BUGBUG: push 0 for EFI_IFR_QUESTION_REF3_2 and EFI_IFR_QUESTION_REF3_3,
1462 // since it is impractical to evaluate the value of a Question in another
1463 // Hii Package list.
1465 ZeroMem (Value
, sizeof (EFI_HII_VALUE
));
1469 case EFI_IFR_RULE_REF_OP
:
1471 // Find expression for this rule
1473 RuleExpression
= RuleIdToExpression (Form
, OpCode
->RuleId
);
1474 if (RuleExpression
== NULL
) {
1475 return EFI_NOT_FOUND
;
1479 // Evaluate this rule expression
1481 Status
= EvaluateExpression (FormSet
, Form
, RuleExpression
);
1482 if (EFI_ERROR (Status
)) {
1486 Value
= &RuleExpression
->Result
;
1489 case EFI_IFR_STRING_REF1_OP
:
1490 Value
->Type
= EFI_IFR_TYPE_STRING
;
1491 Value
->Value
.string
= OpCode
->Value
.Value
.string
;
1497 case EFI_IFR_TRUE_OP
:
1498 case EFI_IFR_FALSE_OP
:
1499 case EFI_IFR_ONE_OP
:
1500 case EFI_IFR_ONES_OP
:
1501 case EFI_IFR_UINT8_OP
:
1502 case EFI_IFR_UINT16_OP
:
1503 case EFI_IFR_UINT32_OP
:
1504 case EFI_IFR_UINT64_OP
:
1505 case EFI_IFR_UNDEFINED_OP
:
1506 case EFI_IFR_VERSION_OP
:
1507 case EFI_IFR_ZERO_OP
:
1508 Value
= &OpCode
->Value
;
1514 case EFI_IFR_LENGTH_OP
:
1515 Status
= PopExpression (Value
);
1516 if (EFI_ERROR (Status
)) {
1519 if (Value
->Type
!= EFI_IFR_TYPE_STRING
) {
1520 return EFI_INVALID_PARAMETER
;
1523 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->HiiHandle
);
1524 if (StrPtr
== NULL
) {
1525 return EFI_INVALID_PARAMETER
;
1528 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1529 Value
->Value
.u64
= StrLen (StrPtr
);
1533 case EFI_IFR_NOT_OP
:
1534 Status
= PopExpression (Value
);
1535 if (EFI_ERROR (Status
)) {
1538 if (Value
->Type
!= EFI_IFR_TYPE_BOOLEAN
) {
1539 return EFI_INVALID_PARAMETER
;
1541 Value
->Value
.b
= (BOOLEAN
) (!Value
->Value
.b
);
1544 case EFI_IFR_QUESTION_REF2_OP
:
1546 // Pop an expression from the expression stack
1548 Status
= PopExpression (Value
);
1549 if (EFI_ERROR (Status
)) {
1554 // Validate the expression value
1556 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
1557 return EFI_NOT_FOUND
;
1560 Question
= IdToQuestion (FormSet
, Form
, Value
->Value
.u16
);
1561 if (Question
== NULL
) {
1562 return EFI_NOT_FOUND
;
1565 Value
= &Question
->HiiValue
;
1568 case EFI_IFR_STRING_REF2_OP
:
1570 // Pop an expression from the expression stack
1572 Status
= PopExpression (Value
);
1573 if (EFI_ERROR (Status
)) {
1578 // Validate the expression value
1580 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
1581 return EFI_NOT_FOUND
;
1584 Value
->Type
= EFI_IFR_TYPE_STRING
;
1585 StrPtr
= GetToken (Value
->Value
.u16
, FormSet
->HiiHandle
);
1586 if (StrPtr
== NULL
) {
1588 // If String not exit, push an empty string
1590 Value
->Value
.string
= NewString (gEmptyString
, FormSet
->HiiHandle
);
1592 Index
= (UINT16
) Value
->Value
.u64
;
1593 Value
->Value
.string
= Index
;
1598 case EFI_IFR_TO_BOOLEAN_OP
:
1600 // Pop an expression from the expression stack
1602 Status
= PopExpression (Value
);
1603 if (EFI_ERROR (Status
)) {
1608 // Convert an expression to a Boolean
1610 if (Value
->Type
<= EFI_IFR_TYPE_DATE
) {
1612 // When converting from an unsigned integer, zero will be converted to
1613 // FALSE and any other value will be converted to TRUE.
1615 Value
->Value
.b
= (BOOLEAN
) ((Value
->Value
.u64
) ? TRUE
: FALSE
);
1617 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
1618 } else if (Value
->Type
== EFI_IFR_TYPE_STRING
) {
1620 // When converting from a string, if case-insensitive compare
1621 // with "true" is True, then push True. If a case-insensitive compare
1622 // with "false" is True, then push False.
1624 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->HiiHandle
);
1625 if (StrPtr
== NULL
) {
1626 return EFI_INVALID_PARAMETER
;
1629 if ((StrCmp (StrPtr
, L
"true") == 0) || (StrCmp (StrPtr
, L
"false") == 0)){
1630 Value
->Value
.b
= TRUE
;
1632 Value
->Value
.b
= FALSE
;
1635 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
1639 case EFI_IFR_TO_STRING_OP
:
1640 Status
= IfrToString (FormSet
, OpCode
->Format
, Value
);
1643 case EFI_IFR_TO_UINT_OP
:
1644 Status
= IfrToUint (FormSet
, Value
);
1647 case EFI_IFR_TO_LOWER_OP
:
1648 case EFI_IFR_TO_UPPER_OP
:
1649 Status
= InitializeUnicodeCollationProtocol ();
1650 if (EFI_ERROR (Status
)) {
1654 Status
= PopExpression (Value
);
1655 if (EFI_ERROR (Status
)) {
1659 if (Value
->Type
!= EFI_IFR_TYPE_STRING
) {
1660 return EFI_UNSUPPORTED
;
1663 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->HiiHandle
);
1664 if (StrPtr
== NULL
) {
1665 return EFI_NOT_FOUND
;
1668 if (OpCode
->Operand
== EFI_IFR_TO_LOWER_OP
) {
1669 mUnicodeCollation
->StrLwr (mUnicodeCollation
, StrPtr
);
1671 mUnicodeCollation
->StrUpr (mUnicodeCollation
, StrPtr
);
1673 Value
->Value
.string
= NewString (StrPtr
, FormSet
->HiiHandle
);
1677 case EFI_IFR_BITWISE_NOT_OP
:
1679 // Pop an expression from the expression stack
1681 Status
= PopExpression (Value
);
1682 if (EFI_ERROR (Status
)) {
1685 if (Value
->Type
> EFI_IFR_TYPE_DATE
) {
1686 return EFI_INVALID_PARAMETER
;
1689 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1690 Value
->Value
.u64
= ~Value
->Value
.u64
;
1696 case EFI_IFR_ADD_OP
:
1697 case EFI_IFR_SUBTRACT_OP
:
1698 case EFI_IFR_MULTIPLY_OP
:
1699 case EFI_IFR_DIVIDE_OP
:
1700 case EFI_IFR_MODULO_OP
:
1701 case EFI_IFR_BITWISE_AND_OP
:
1702 case EFI_IFR_BITWISE_OR_OP
:
1703 case EFI_IFR_SHIFT_LEFT_OP
:
1704 case EFI_IFR_SHIFT_RIGHT_OP
:
1706 // Pop an expression from the expression stack
1708 Status
= PopExpression (&Data2
);
1709 if (EFI_ERROR (Status
)) {
1712 if (Data2
.Type
> EFI_IFR_TYPE_DATE
) {
1713 return EFI_INVALID_PARAMETER
;
1717 // Pop another expression from the expression stack
1719 Status
= PopExpression (&Data1
);
1720 if (EFI_ERROR (Status
)) {
1723 if (Data1
.Type
> EFI_IFR_TYPE_DATE
) {
1724 return EFI_INVALID_PARAMETER
;
1727 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1729 switch (OpCode
->Operand
) {
1730 case EFI_IFR_ADD_OP
:
1731 Value
->Value
.u64
= Data1
.Value
.u64
+ Data2
.Value
.u64
;
1734 case EFI_IFR_SUBTRACT_OP
:
1735 Value
->Value
.u64
= Data1
.Value
.u64
- Data2
.Value
.u64
;
1738 case EFI_IFR_MULTIPLY_OP
:
1739 Value
->Value
.u64
= MultU64x32 (Data1
.Value
.u64
, (UINT32
) Data2
.Value
.u64
);
1742 case EFI_IFR_DIVIDE_OP
:
1743 Value
->Value
.u64
= DivU64x32 (Data1
.Value
.u64
, (UINT32
) Data2
.Value
.u64
);
1746 case EFI_IFR_MODULO_OP
:
1747 DivU64x32Remainder (Data1
.Value
.u64
, (UINT32
) Data2
.Value
.u64
, &TempValue
);
1748 Value
->Value
.u64
= TempValue
;
1751 case EFI_IFR_BITWISE_AND_OP
:
1752 Value
->Value
.u64
= Data1
.Value
.u64
& Data2
.Value
.u64
;
1755 case EFI_IFR_BITWISE_OR_OP
:
1756 Value
->Value
.u64
= Data1
.Value
.u64
| Data2
.Value
.u64
;
1759 case EFI_IFR_SHIFT_LEFT_OP
:
1760 Value
->Value
.u64
= LShiftU64 (Data1
.Value
.u64
, (UINTN
) Data2
.Value
.u64
);
1763 case EFI_IFR_SHIFT_RIGHT_OP
:
1764 Value
->Value
.u64
= RShiftU64 (Data1
.Value
.u64
, (UINTN
) Data2
.Value
.u64
);
1772 case EFI_IFR_AND_OP
:
1775 // Two Boolean operator
1777 Status
= PopExpression (&Data2
);
1778 if (EFI_ERROR (Status
)) {
1781 if (Data2
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
1782 return EFI_INVALID_PARAMETER
;
1786 // Pop another expression from the expression stack
1788 Status
= PopExpression (&Data1
);
1789 if (EFI_ERROR (Status
)) {
1792 if (Data1
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
1793 return EFI_INVALID_PARAMETER
;
1796 if (OpCode
->Operand
== EFI_IFR_AND_OP
) {
1797 Value
->Value
.b
= (BOOLEAN
) (Data1
.Value
.b
&& Data2
.Value
.b
);
1799 Value
->Value
.b
= (BOOLEAN
) (Data1
.Value
.b
|| Data2
.Value
.b
);
1803 case EFI_IFR_EQUAL_OP
:
1804 case EFI_IFR_NOT_EQUAL_OP
:
1805 case EFI_IFR_GREATER_EQUAL_OP
:
1806 case EFI_IFR_GREATER_THAN_OP
:
1807 case EFI_IFR_LESS_EQUAL_OP
:
1808 case EFI_IFR_LESS_THAN_OP
:
1810 // Compare two integer, string, boolean or date/time
1812 Status
= PopExpression (&Data2
);
1813 if (EFI_ERROR (Status
)) {
1816 if (Data2
.Type
> EFI_IFR_TYPE_BOOLEAN
&& Data2
.Type
!= EFI_IFR_TYPE_STRING
) {
1817 return EFI_INVALID_PARAMETER
;
1821 // Pop another expression from the expression stack
1823 Status
= PopExpression (&Data1
);
1824 if (EFI_ERROR (Status
)) {
1828 Result
= CompareHiiValue (&Data1
, &Data2
, FormSet
->HiiHandle
);
1829 if (Result
== EFI_INVALID_PARAMETER
) {
1830 return EFI_INVALID_PARAMETER
;
1833 switch (OpCode
->Operand
) {
1834 case EFI_IFR_EQUAL_OP
:
1835 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
1838 case EFI_IFR_NOT_EQUAL_OP
:
1839 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
1842 case EFI_IFR_GREATER_EQUAL_OP
:
1843 Value
->Value
.b
= (BOOLEAN
) ((Result
>= 0) ? TRUE
: FALSE
);
1846 case EFI_IFR_GREATER_THAN_OP
:
1847 Value
->Value
.b
= (BOOLEAN
) ((Result
> 0) ? TRUE
: FALSE
);
1850 case EFI_IFR_LESS_EQUAL_OP
:
1851 Value
->Value
.b
= (BOOLEAN
) ((Result
<= 0) ? TRUE
: FALSE
);
1854 case EFI_IFR_LESS_THAN_OP
:
1855 Value
->Value
.b
= (BOOLEAN
) ((Result
< 0) ? TRUE
: FALSE
);
1863 case EFI_IFR_MATCH_OP
:
1864 Status
= IfrMatch (FormSet
, Value
);
1867 case EFI_IFR_CATENATE_OP
:
1868 Status
= IfrCatenate (FormSet
, Value
);
1874 case EFI_IFR_CONDITIONAL_OP
:
1876 // Pop third expression from the expression stack
1878 Status
= PopExpression (&Data3
);
1879 if (EFI_ERROR (Status
)) {
1884 // Pop second expression from the expression stack
1886 Status
= PopExpression (&Data2
);
1887 if (EFI_ERROR (Status
)) {
1892 // Pop first expression from the expression stack
1894 Status
= PopExpression (&Data1
);
1895 if (EFI_ERROR (Status
)) {
1898 if (Data1
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
1899 return EFI_INVALID_PARAMETER
;
1902 if (Data1
.Value
.b
) {
1909 case EFI_IFR_FIND_OP
:
1910 Status
= IfrFind (FormSet
, OpCode
->Format
, Value
);
1913 case EFI_IFR_MID_OP
:
1914 Status
= IfrMid (FormSet
, Value
);
1917 case EFI_IFR_TOKEN_OP
:
1918 Status
= IfrToken (FormSet
, Value
);
1921 case EFI_IFR_SPAN_OP
:
1922 Status
= IfrSpan (FormSet
, OpCode
->Flags
, Value
);
1928 if (EFI_ERROR (Status
)) {
1932 Status
= PushExpression (Value
);
1933 if (EFI_ERROR (Status
)) {
1939 // Pop the final result from expression stack
1942 Status
= PopExpression (Value
);
1943 if (EFI_ERROR (Status
)) {
1948 // After evaluating an expression, there should be only one value left on the expression stack
1950 if (PopExpression (Value
) != EFI_ACCESS_DENIED
) {
1951 return EFI_INVALID_PARAMETER
;
1954 CopyMem (&Expression
->Result
, Value
, sizeof (EFI_HII_VALUE
));