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.
18 // Global stack used to evaluate boolean expresions
20 EFI_HII_VALUE
*mOpCodeScopeStack
= NULL
;
21 EFI_HII_VALUE
*mOpCodeScopeStackEnd
= NULL
;
22 EFI_HII_VALUE
*mOpCodeScopeStackPointer
= NULL
;
24 EFI_HII_VALUE
*mExpressionEvaluationStack
= NULL
;
25 EFI_HII_VALUE
*mExpressionEvaluationStackEnd
= NULL
;
26 EFI_HII_VALUE
*mExpressionEvaluationStackPointer
= NULL
;
29 // Unicode collation protocol interface
31 EFI_UNICODE_COLLATION_PROTOCOL
*mUnicodeCollation
= NULL
;
35 Grow size of the stack.
37 This is an internal function.
39 @param Stack On input: old stack; On output: new stack
40 @param StackPtr On input: old stack pointer; On output: new stack
42 @param StackEnd On input: old stack end; On output: new stack end
44 @retval EFI_SUCCESS Grow stack success.
45 @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.
50 IN OUT EFI_HII_VALUE
**Stack
,
51 IN OUT EFI_HII_VALUE
**StackPtr
,
52 IN OUT EFI_HII_VALUE
**StackEnd
56 EFI_HII_VALUE
*NewStack
;
58 Size
= EXPRESSION_STACK_SIZE_INCREMENT
;
59 if (*StackPtr
!= NULL
) {
60 Size
= Size
+ (*StackEnd
- *Stack
);
63 NewStack
= AllocatePool (Size
* sizeof (EFI_HII_VALUE
));
64 if (NewStack
== NULL
) {
65 return EFI_OUT_OF_RESOURCES
;
68 if (*StackPtr
!= NULL
) {
70 // Copy from Old Stack to the New Stack
75 (*StackEnd
- *Stack
) * sizeof (EFI_HII_VALUE
)
85 // Make the Stack pointer point to the old data in the new stack
87 *StackPtr
= NewStack
+ (*StackPtr
- *Stack
);
89 *StackEnd
= NewStack
+ Size
;
96 Push an element onto the Boolean Stack.
98 @param Stack On input: old stack; On output: new stack
99 @param StackPtr On input: old stack pointer; On output: new stack
101 @param StackEnd On input: old stack end; On output: new stack end
102 @param Data Data to push.
104 @retval EFI_SUCCESS Push stack success.
109 IN OUT EFI_HII_VALUE
**Stack
,
110 IN OUT EFI_HII_VALUE
**StackPtr
,
111 IN OUT EFI_HII_VALUE
**StackEnd
,
112 IN EFI_HII_VALUE
*Data
118 // Check for a stack overflow condition
120 if (*StackPtr
>= *StackEnd
) {
124 Status
= GrowStack (Stack
, StackPtr
, StackEnd
);
125 if (EFI_ERROR (Status
)) {
131 // Push the item onto the stack
133 CopyMem (*StackPtr
, Data
, sizeof (EFI_HII_VALUE
));
134 *StackPtr
= *StackPtr
+ 1;
141 Pop an element from the stack.
143 @param Stack On input: old stack; On output: new stack
144 @param StackPtr On input: old stack pointer; On output: new stack
146 @param StackEnd On input: old stack end; On output: new stack end
147 @param Data Data to pop.
149 @retval EFI_SUCCESS The value was popped onto the stack.
150 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
155 IN OUT EFI_HII_VALUE
**Stack
,
156 IN OUT EFI_HII_VALUE
**StackPtr
,
157 IN OUT EFI_HII_VALUE
**StackEnd
,
158 OUT EFI_HII_VALUE
*Data
162 // Check for a stack underflow condition
164 if (*StackPtr
== *Stack
) {
165 return EFI_ACCESS_DENIED
;
169 // Pop the item off the stack
171 *StackPtr
= *StackPtr
- 1;
172 CopyMem (Data
, *StackPtr
, sizeof (EFI_HII_VALUE
));
178 Reset stack pointer to begin of the stack.
186 mOpCodeScopeStackPointer
= mOpCodeScopeStack
;
191 Push an Operand onto the Stack
193 @param Operand Operand to push.
195 @retval EFI_SUCCESS The value was pushed onto the stack.
196 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
207 Data
.Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
208 Data
.Value
.u8
= Operand
;
212 &mOpCodeScopeStackPointer
,
213 &mOpCodeScopeStackEnd
,
220 Pop an Operand from the Stack
222 @param Operand Operand to pop.
224 @retval EFI_SUCCESS The value was pushed onto the stack.
225 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
239 &mOpCodeScopeStackPointer
,
240 &mOpCodeScopeStackEnd
,
244 *Operand
= Data
.Value
.u8
;
251 Reset stack pointer to begin of the stack.
255 ResetExpressionStack (
259 mExpressionEvaluationStackPointer
= mExpressionEvaluationStack
;
264 Push an Expression value onto the Stack
266 @param Value Expression value to push.
268 @retval EFI_SUCCESS The value was pushed onto the stack.
269 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
275 IN EFI_HII_VALUE
*Value
279 &mExpressionEvaluationStack
,
280 &mExpressionEvaluationStackPointer
,
281 &mExpressionEvaluationStackEnd
,
288 Pop an Expression value from the stack.
290 @param Value Expression value to pop.
292 @retval EFI_SUCCESS The value was popped onto the stack.
293 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
298 OUT EFI_HII_VALUE
*Value
302 &mExpressionEvaluationStack
,
303 &mExpressionEvaluationStackPointer
,
304 &mExpressionEvaluationStackEnd
,
311 Get Form given its FormId.
313 @param FormSet The formset which contains this form.
314 @param FormId Id of this form.
316 @retval Pointer The form.
317 @retval NULL Specified Form is not found in the formset.
322 IN FORM_BROWSER_FORMSET
*FormSet
,
327 FORM_BROWSER_FORM
*Form
;
329 Link
= GetFirstNode (&FormSet
->FormListHead
);
330 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
331 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
333 if (Form
->FormId
== FormId
) {
337 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
345 Search a Question in Form scope using its QuestionId.
347 @param Form The form which contains this Question.
348 @param QuestionId Id of this Question.
350 @retval Pointer The Question.
351 @retval NULL Specified Question not found in the form.
354 FORM_BROWSER_STATEMENT
*
356 IN FORM_BROWSER_FORM
*Form
,
361 FORM_BROWSER_STATEMENT
*Question
;
363 if (QuestionId
== 0) {
365 // The value of zero is reserved
370 Link
= GetFirstNode (&Form
->StatementListHead
);
371 while (!IsNull (&Form
->StatementListHead
, Link
)) {
372 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
374 if (Question
->QuestionId
== QuestionId
) {
378 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
386 Search a Question in Formset scope using its QuestionId.
388 @param FormSet The formset which contains this form.
389 @param Form The form which contains this Question.
390 @param QuestionId Id of this Question.
392 @retval Pointer The Question.
393 @retval NULL Specified Question not found in the form.
396 FORM_BROWSER_STATEMENT
*
398 IN FORM_BROWSER_FORMSET
*FormSet
,
399 IN FORM_BROWSER_FORM
*Form
,
404 FORM_BROWSER_STATEMENT
*Question
;
407 // Search in the form scope first
409 Question
= IdToQuestion2 (Form
, QuestionId
);
410 if (Question
!= NULL
) {
415 // Search in the formset scope
417 Link
= GetFirstNode (&FormSet
->FormListHead
);
418 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
419 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
421 Question
= IdToQuestion2 (Form
, QuestionId
);
422 if (Question
!= NULL
) {
424 // EFI variable storage may be updated by Callback() asynchronous,
425 // to keep synchronous, always reload the Question Value.
427 if (Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
428 GetQuestionValue (FormSet
, Form
, Question
, FALSE
);
434 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
442 Get Expression given its RuleId.
444 @param Form The form which contains this Expression.
445 @param RuleId Id of this Expression.
447 @retval Pointer The Expression.
448 @retval NULL Specified Expression not found in the form.
453 IN FORM_BROWSER_FORM
*Form
,
458 FORM_EXPRESSION
*Expression
;
460 Link
= GetFirstNode (&Form
->ExpressionListHead
);
461 while (!IsNull (&Form
->ExpressionListHead
, Link
)) {
462 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
464 if (Expression
->Type
== EFI_HII_EXPRESSION_RULE
&& Expression
->RuleId
== RuleId
) {
468 Link
= GetNextNode (&Form
->ExpressionListHead
, Link
);
476 Locate the Unicode Collation Protocol interface for later use.
478 @retval EFI_SUCCESS Protocol interface initialize success.
479 @retval Other Protocol interface initialize failed.
483 InitializeUnicodeCollationProtocol (
489 if (mUnicodeCollation
!= NULL
) {
494 // BUGBUG: Proper impelmentation is to locate all Unicode Collation Protocol
495 // instances first and then select one which support English language.
496 // Current implementation just pick the first instance.
498 Status
= gBS
->LocateProtocol (
499 &gEfiUnicodeCollation2ProtocolGuid
,
501 (VOID
**) &mUnicodeCollation
507 Convert the input Unicode character to upper.
509 @param String Th Unicode character to be converted.
517 while (*String
!= 0) {
518 if ((*String
>= 'a') && (*String
<= 'z')) {
519 *String
= (UINT16
) ((*String
) & ((UINT16
) ~0x20));
527 Evaluate opcode EFI_IFR_TO_STRING.
529 @param FormSet Formset which contains this opcode.
530 @param Format String format in EFI_IFR_TO_STRING.
531 @param Result Evaluation result for this opcode.
533 @retval EFI_SUCCESS Opcode evaluation success.
534 @retval Other Opcode evaluation failed.
539 IN FORM_BROWSER_FORMSET
*FormSet
,
541 OUT EFI_HII_VALUE
*Result
548 CHAR16 Buffer
[MAXIMUM_VALUE_CHARACTERS
];
551 Status
= PopExpression (&Value
);
552 if (EFI_ERROR (Status
)) {
556 switch (Value
.Type
) {
557 case EFI_IFR_TYPE_NUM_SIZE_8
:
558 case EFI_IFR_TYPE_NUM_SIZE_16
:
559 case EFI_IFR_TYPE_NUM_SIZE_32
:
560 case EFI_IFR_TYPE_NUM_SIZE_64
:
561 BufferSize
= MAXIMUM_VALUE_CHARACTERS
* sizeof (CHAR16
);
563 case EFI_IFR_STRING_UNSIGNED_DEC
:
564 case EFI_IFR_STRING_SIGNED_DEC
:
565 PrintFormat
= L
"%ld";
568 case EFI_IFR_STRING_LOWERCASE_HEX
:
569 PrintFormat
= L
"%lx";
572 case EFI_IFR_STRING_UPPERCASE_HEX
:
573 PrintFormat
= L
"%lX";
577 return EFI_UNSUPPORTED
;
579 UnicodeSPrint (Buffer
, BufferSize
, PrintFormat
, Value
.Value
.u64
);
583 case EFI_IFR_TYPE_STRING
:
584 CopyMem (Result
, &Value
, sizeof (EFI_HII_VALUE
));
587 case EFI_IFR_TYPE_BOOLEAN
:
588 String
= (Value
.Value
.b
) ? L
"True" : L
"False";
592 return EFI_UNSUPPORTED
;
595 Result
->Type
= EFI_IFR_TYPE_STRING
;
596 Result
->Value
.string
= NewString (String
, FormSet
->HiiHandle
);
602 Evaluate opcode EFI_IFR_TO_UINT.
604 @param FormSet Formset which contains this opcode.
605 @param Result Evaluation result for this opcode.
607 @retval EFI_SUCCESS Opcode evaluation success.
608 @retval Other Opcode evaluation failed.
613 IN FORM_BROWSER_FORMSET
*FormSet
,
614 OUT EFI_HII_VALUE
*Result
622 Status
= PopExpression (&Value
);
623 if (EFI_ERROR (Status
)) {
627 if (Value
.Type
>= EFI_IFR_TYPE_OTHER
) {
628 return EFI_UNSUPPORTED
;
631 Status
= EFI_SUCCESS
;
632 if (Value
.Type
== EFI_IFR_TYPE_STRING
) {
633 String
= GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
634 if (String
== NULL
) {
635 return EFI_NOT_FOUND
;
638 IfrStrToUpper (String
);
639 StringPtr
= StrStr (String
, L
"0X");
640 if (StringPtr
!= NULL
) {
644 Result
->Value
.u64
= StrHexToUint64 (String
);
649 Result
->Value
.u64
= StrDecimalToUint64 (String
);
653 CopyMem (Result
, &Value
, sizeof (EFI_HII_VALUE
));
656 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
662 Evaluate opcode EFI_IFR_CATENATE.
664 @param FormSet Formset which contains this opcode.
665 @param Result Evaluation result for this opcode.
667 @retval EFI_SUCCESS Opcode evaluation success.
668 @retval Other Opcode evaluation failed.
673 IN FORM_BROWSER_FORMSET
*FormSet
,
674 OUT EFI_HII_VALUE
*Result
685 // String[0] - The second string
686 // String[1] - The first string
691 Status
= EFI_SUCCESS
;
693 for (Index
= 0; Index
< 2; Index
++) {
694 Status
= PopExpression (&Value
);
695 if (EFI_ERROR (Status
)) {
699 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
700 Status
= EFI_UNSUPPORTED
;
704 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
705 if (String
[Index
] == NULL
) {
706 Status
= EFI_NOT_FOUND
;
711 Size
= StrSize (String
[0]);
712 StringPtr
= AllocatePool (StrSize (String
[1]) + Size
);
713 ASSERT (StringPtr
!= NULL
);
714 StrCpy (StringPtr
, String
[1]);
715 StrCat (StringPtr
, String
[0]);
717 Result
->Type
= EFI_IFR_TYPE_STRING
;
718 Result
->Value
.string
= NewString (StringPtr
, FormSet
->HiiHandle
);
721 if (String
[0] != NULL
) {
722 FreePool (String
[0]);
724 if (String
[1] != NULL
) {
725 FreePool (String
[1]);
727 if (StringPtr
!= NULL
) {
728 FreePool (StringPtr
);
736 Evaluate opcode EFI_IFR_MATCH.
738 @param FormSet Formset which contains this opcode.
739 @param Result Evaluation result for this opcode.
741 @retval EFI_SUCCESS Opcode evaluation success.
742 @retval Other Opcode evaluation failed.
747 IN FORM_BROWSER_FORMSET
*FormSet
,
748 OUT EFI_HII_VALUE
*Result
757 // String[0] - The string to search
758 // String[1] - pattern
762 Status
= EFI_SUCCESS
;
763 for (Index
= 0; Index
< 2; Index
++) {
764 Status
= PopExpression (&Value
);
765 if (EFI_ERROR (Status
)) {
769 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
770 Status
= EFI_UNSUPPORTED
;
774 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
775 if (String
[Index
] == NULL
) {
776 Status
= EFI_NOT_FOUND
;
781 Result
->Type
= EFI_IFR_TYPE_BOOLEAN
;
782 Result
->Value
.b
= mUnicodeCollation
->MetaiMatch (mUnicodeCollation
, String
[0], String
[1]);
785 if (String
[0] != NULL
) {
786 FreePool (String
[0]);
788 if (String
[1] != NULL
) {
789 FreePool (String
[1]);
797 Evaluate opcode EFI_IFR_FIND.
799 @param FormSet Formset which contains this opcode.
800 @param Format Case sensitive or insensitive.
801 @param Result Evaluation result for this opcode.
803 @retval EFI_SUCCESS Opcode evaluation success.
804 @retval Other Opcode evaluation failed.
809 IN FORM_BROWSER_FORMSET
*FormSet
,
811 OUT EFI_HII_VALUE
*Result
821 if (Format
> EFI_IFR_FF_CASE_INSENSITIVE
) {
822 return EFI_UNSUPPORTED
;
825 Status
= PopExpression (&Value
);
826 if (EFI_ERROR (Status
)) {
829 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
830 return EFI_UNSUPPORTED
;
832 Base
= (UINTN
) Value
.Value
.u64
;
835 // String[0] - sub-string
836 // String[1] - The string to search
840 for (Index
= 0; Index
< 2; Index
++) {
841 Status
= PopExpression (&Value
);
842 if (EFI_ERROR (Status
)) {
846 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
847 Status
= EFI_UNSUPPORTED
;
851 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
852 if (String
[Index
] == NULL
) {
853 Status
= EFI_NOT_FOUND
;
857 if (Format
== EFI_IFR_FF_CASE_INSENSITIVE
) {
859 // Case insensitive, convert both string to upper case
861 IfrStrToUpper (String
[Index
]);
865 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
866 if (Base
>= StrLen (String
[1])) {
867 Result
->Value
.u64
= 0xFFFFFFFFFFFFFFFFULL
;
869 StringPtr
= StrStr (String
[1] + Base
, String
[0]);
870 Result
->Value
.u64
= (StringPtr
== NULL
) ? 0xFFFFFFFFFFFFFFFFULL
: (StringPtr
- String
[1]);
874 if (String
[0] != NULL
) {
875 FreePool (String
[0]);
877 if (String
[1] != NULL
) {
878 FreePool (String
[1]);
886 Evaluate opcode EFI_IFR_MID.
888 @param FormSet Formset which contains this opcode.
889 @param Result Evaluation result for this opcode.
891 @retval EFI_SUCCESS Opcode evaluation success.
892 @retval Other Opcode evaluation failed.
897 IN FORM_BROWSER_FORMSET
*FormSet
,
898 OUT EFI_HII_VALUE
*Result
908 Status
= PopExpression (&Value
);
909 if (EFI_ERROR (Status
)) {
912 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
913 return EFI_UNSUPPORTED
;
915 Length
= (UINTN
) Value
.Value
.u64
;
917 Status
= PopExpression (&Value
);
918 if (EFI_ERROR (Status
)) {
921 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
922 return EFI_UNSUPPORTED
;
924 Base
= (UINTN
) Value
.Value
.u64
;
926 Status
= PopExpression (&Value
);
927 if (EFI_ERROR (Status
)) {
930 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
931 return EFI_UNSUPPORTED
;
933 String
= GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
934 if (String
== NULL
) {
935 return EFI_NOT_FOUND
;
938 if (Length
== 0 || Base
>= StrLen (String
)) {
939 SubString
= gEmptyString
;
941 SubString
= String
+ Base
;
942 if ((Base
+ Length
) < StrLen (String
)) {
943 SubString
[Length
] = L
'\0';
947 Result
->Type
= EFI_IFR_TYPE_STRING
;
948 Result
->Value
.string
= NewString (SubString
, FormSet
->HiiHandle
);
957 Evaluate opcode EFI_IFR_TOKEN.
959 @param FormSet Formset which contains this opcode.
960 @param Result Evaluation result for this opcode.
962 @retval EFI_SUCCESS Opcode evaluation success.
963 @retval Other Opcode evaluation failed.
968 IN FORM_BROWSER_FORMSET
*FormSet
,
969 OUT EFI_HII_VALUE
*Result
981 Status
= PopExpression (&Value
);
982 if (EFI_ERROR (Status
)) {
985 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
986 return EFI_UNSUPPORTED
;
988 Count
= (UINTN
) Value
.Value
.u64
;
991 // String[0] - Delimiter
992 // String[1] - The string to search
996 for (Index
= 0; Index
< 2; Index
++) {
997 Status
= PopExpression (&Value
);
998 if (EFI_ERROR (Status
)) {
1002 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
1003 Status
= EFI_UNSUPPORTED
;
1007 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
1008 if (String
[Index
] == NULL
) {
1009 Status
= EFI_NOT_FOUND
;
1014 Delimiter
= String
[0];
1015 SubString
= String
[1];
1017 SubString
= StrStr (SubString
, Delimiter
);
1018 if (SubString
!= NULL
) {
1020 // Skip over the delimiter
1022 SubString
= SubString
+ StrLen (Delimiter
);
1029 if (SubString
== NULL
) {
1031 // nth delimited sub-string not found, push an empty string
1033 SubString
= gEmptyString
;
1036 // Put a NULL terminator for nth delimited sub-string
1038 StringPtr
= StrStr (SubString
, Delimiter
);
1039 if (StringPtr
!= NULL
) {
1044 Result
->Type
= EFI_IFR_TYPE_STRING
;
1045 Result
->Value
.string
= NewString (SubString
, FormSet
->HiiHandle
);
1048 if (String
[0] != NULL
) {
1049 FreePool (String
[0]);
1051 if (String
[1] != NULL
) {
1052 FreePool (String
[1]);
1060 Evaluate opcode EFI_IFR_SPAN.
1062 @param FormSet Formset which contains this opcode.
1063 @param Flags FIRST_MATCHING or FIRST_NON_MATCHING.
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
,
1074 OUT EFI_HII_VALUE
*Result
1078 EFI_HII_VALUE Value
;
1086 Status
= PopExpression (&Value
);
1087 if (EFI_ERROR (Status
)) {
1090 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1091 return EFI_UNSUPPORTED
;
1093 Base
= (UINTN
) Value
.Value
.u64
;
1096 // String[0] - Charset
1097 // String[1] - The string to search
1101 for (Index
= 0; Index
< 2; Index
++) {
1102 Status
= PopExpression (&Value
);
1103 if (EFI_ERROR (Status
)) {
1107 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
1108 Status
= EFI_UNSUPPORTED
;
1112 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
1113 if (String
[Index
] == NULL
) {
1114 Status
= EFI_NOT_FOUND
;
1119 if (Base
>= StrLen (String
[1])) {
1120 Status
= EFI_UNSUPPORTED
;
1125 StringPtr
= String
[1] + Base
;
1126 Charset
= String
[0];
1127 while (*StringPtr
!= 0 && !Found
) {
1129 while (Charset
[Index
] != 0) {
1130 if (*StringPtr
>= Charset
[Index
] && *StringPtr
<= Charset
[Index
+ 1]) {
1131 if (Flags
== EFI_IFR_FLAGS_FIRST_MATCHING
) {
1136 if (Flags
== EFI_IFR_FLAGS_FIRST_NON_MATCHING
) {
1142 // Skip characters pair representing low-end of a range and high-end of a range
1152 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1153 Result
->Value
.u64
= StringPtr
- String
[1];
1156 if (String
[0] != NULL
) {
1157 FreePool (String
[0]);
1159 if (String
[1] != NULL
) {
1160 FreePool (String
[1]);
1168 Zero extend integer/boolean/date/time to UINT64 for comparing.
1170 @param Value HII Value to be converted.
1175 IN EFI_HII_VALUE
*Value
1181 switch (Value
->Type
) {
1182 case EFI_IFR_TYPE_NUM_SIZE_8
:
1183 Temp
= Value
->Value
.u8
;
1186 case EFI_IFR_TYPE_NUM_SIZE_16
:
1187 Temp
= Value
->Value
.u16
;
1190 case EFI_IFR_TYPE_NUM_SIZE_32
:
1191 Temp
= Value
->Value
.u32
;
1194 case EFI_IFR_TYPE_BOOLEAN
:
1195 Temp
= Value
->Value
.b
;
1198 case EFI_IFR_TYPE_TIME
:
1199 Temp
= Value
->Value
.u32
& 0xffffff;
1202 case EFI_IFR_TYPE_DATE
:
1203 Temp
= Value
->Value
.u32
;
1210 Value
->Value
.u64
= Temp
;
1215 Compare two Hii value.
1217 @param Value1 Expression value to compare on left-hand.
1218 @param Value2 Expression value to compare on right-hand.
1219 @param HiiHandle Only required for string compare.
1221 @retval EFI_INVALID_PARAMETER Could not perform comparation on two values.
1222 @retval 0 Two operators equeal.
1223 @return Positive value if Value1 is greater than Value2.
1224 @retval Negative value if Value1 is less than Value2.
1229 IN EFI_HII_VALUE
*Value1
,
1230 IN EFI_HII_VALUE
*Value2
,
1231 IN EFI_HII_HANDLE HiiHandle OPTIONAL
1239 if (Value1
->Type
>= EFI_IFR_TYPE_OTHER
|| Value2
->Type
>= EFI_IFR_TYPE_OTHER
) {
1240 return EFI_INVALID_PARAMETER
;
1243 if (Value1
->Type
== EFI_IFR_TYPE_STRING
|| Value2
->Type
== EFI_IFR_TYPE_STRING
) {
1244 if (Value1
->Type
!= Value2
->Type
) {
1246 // Both Operator should be type of String
1248 return EFI_INVALID_PARAMETER
;
1251 if (Value1
->Value
.string
== 0 || Value2
->Value
.string
== 0) {
1253 // StringId 0 is reserved
1255 return EFI_INVALID_PARAMETER
;
1258 if (Value1
->Value
.string
== Value2
->Value
.string
) {
1262 Str1
= GetToken (Value1
->Value
.string
, HiiHandle
);
1267 return EFI_INVALID_PARAMETER
;
1270 Str2
= GetToken (Value2
->Value
.string
, HiiHandle
);
1273 return EFI_INVALID_PARAMETER
;
1276 Result
= StrCmp (Str1
, Str2
);
1285 // Take remain types(integer, boolean, date/time) as integer
1287 Temp64
= (INT64
) (Value1
->Value
.u64
- Value2
->Value
.u64
);
1290 } else if (Temp64
< 0) {
1301 Evaluate the result of a HII expression.
1303 If Expression is NULL, then ASSERT.
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 ASSERT (Expression
!= NULL
);
1346 Expression
->Result
.Type
= EFI_IFR_TYPE_OTHER
;
1348 Link
= GetFirstNode (&Expression
->OpCodeListHead
);
1349 while (!IsNull (&Expression
->OpCodeListHead
, Link
)) {
1350 OpCode
= EXPRESSION_OPCODE_FROM_LINK (Link
);
1352 Link
= GetNextNode (&Expression
->OpCodeListHead
, Link
);
1354 ZeroMem (&Data1
, sizeof (EFI_HII_VALUE
));
1355 ZeroMem (&Data2
, sizeof (EFI_HII_VALUE
));
1356 ZeroMem (&Data3
, sizeof (EFI_HII_VALUE
));
1359 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
1360 Status
= EFI_SUCCESS
;
1362 switch (OpCode
->Operand
) {
1364 // Built-in functions
1366 case EFI_IFR_EQ_ID_VAL_OP
:
1367 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
1368 if (Question
== NULL
) {
1369 return EFI_NOT_FOUND
;
1372 Result
= CompareHiiValue (&Question
->HiiValue
, &OpCode
->Value
, NULL
);
1373 if (Result
== EFI_INVALID_PARAMETER
) {
1374 return EFI_INVALID_PARAMETER
;
1376 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
1379 case EFI_IFR_EQ_ID_ID_OP
:
1380 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
1381 if (Question
== NULL
) {
1382 return EFI_NOT_FOUND
;
1385 Question2
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId2
);
1386 if (Question2
== NULL
) {
1387 return EFI_NOT_FOUND
;
1390 Result
= CompareHiiValue (&Question
->HiiValue
, &Question2
->HiiValue
, FormSet
->HiiHandle
);
1391 if (Result
== EFI_INVALID_PARAMETER
) {
1392 return EFI_INVALID_PARAMETER
;
1394 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
1397 case EFI_IFR_EQ_ID_LIST_OP
:
1398 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
1399 if (Question
== NULL
) {
1400 return EFI_NOT_FOUND
;
1403 Value
->Value
.b
= FALSE
;
1404 for (Index
=0; Index
< OpCode
->ListLength
; Index
++) {
1405 if (Question
->HiiValue
.Value
.u16
== OpCode
->ValueList
[Index
]) {
1406 Value
->Value
.b
= TRUE
;
1412 case EFI_IFR_DUP_OP
:
1413 Status
= PopExpression (Value
);
1414 if (EFI_ERROR (Status
)) {
1418 Status
= PushExpression (Value
);
1421 case EFI_IFR_QUESTION_REF1_OP
:
1422 case EFI_IFR_THIS_OP
:
1423 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
1424 if (Question
== NULL
) {
1425 return EFI_NOT_FOUND
;
1428 Value
= &Question
->HiiValue
;
1431 case EFI_IFR_QUESTION_REF3_OP
:
1432 if (OpCode
->DevicePath
== 0) {
1434 // EFI_IFR_QUESTION_REF3
1435 // Pop an expression from the expression stack
1437 Status
= PopExpression (Value
);
1438 if (EFI_ERROR (Status
)) {
1443 // Validate the expression value
1445 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
1446 return EFI_NOT_FOUND
;
1449 Question
= IdToQuestion (FormSet
, Form
, Value
->Value
.u16
);
1450 if (Question
== NULL
) {
1451 return EFI_NOT_FOUND
;
1455 // push the questions' value on to the expression stack
1457 Value
= &Question
->HiiValue
;
1460 // BUGBUG: push 0 for EFI_IFR_QUESTION_REF3_2 and EFI_IFR_QUESTION_REF3_3,
1461 // since it is impractical to evaluate the value of a Question in another
1462 // Hii Package list.
1464 ZeroMem (Value
, sizeof (EFI_HII_VALUE
));
1468 case EFI_IFR_RULE_REF_OP
:
1470 // Find expression for this rule
1472 RuleExpression
= RuleIdToExpression (Form
, OpCode
->RuleId
);
1473 if (RuleExpression
== NULL
) {
1474 return EFI_NOT_FOUND
;
1478 // Evaluate this rule expression
1480 Status
= EvaluateExpression (FormSet
, Form
, RuleExpression
);
1481 if (EFI_ERROR (Status
)) {
1485 Value
= &RuleExpression
->Result
;
1488 case EFI_IFR_STRING_REF1_OP
:
1489 Value
->Type
= EFI_IFR_TYPE_STRING
;
1490 Value
->Value
.string
= OpCode
->Value
.Value
.string
;
1496 case EFI_IFR_TRUE_OP
:
1497 case EFI_IFR_FALSE_OP
:
1498 case EFI_IFR_ONE_OP
:
1499 case EFI_IFR_ONES_OP
:
1500 case EFI_IFR_UINT8_OP
:
1501 case EFI_IFR_UINT16_OP
:
1502 case EFI_IFR_UINT32_OP
:
1503 case EFI_IFR_UINT64_OP
:
1504 case EFI_IFR_UNDEFINED_OP
:
1505 case EFI_IFR_VERSION_OP
:
1506 case EFI_IFR_ZERO_OP
:
1507 Value
= &OpCode
->Value
;
1513 case EFI_IFR_LENGTH_OP
:
1514 Status
= PopExpression (Value
);
1515 if (EFI_ERROR (Status
)) {
1518 if (Value
->Type
!= EFI_IFR_TYPE_STRING
) {
1519 return EFI_INVALID_PARAMETER
;
1522 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->HiiHandle
);
1523 if (StrPtr
== NULL
) {
1524 return EFI_INVALID_PARAMETER
;
1527 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1528 Value
->Value
.u64
= StrLen (StrPtr
);
1532 case EFI_IFR_NOT_OP
:
1533 Status
= PopExpression (Value
);
1534 if (EFI_ERROR (Status
)) {
1537 if (Value
->Type
!= EFI_IFR_TYPE_BOOLEAN
) {
1538 return EFI_INVALID_PARAMETER
;
1540 Value
->Value
.b
= (BOOLEAN
) (!Value
->Value
.b
);
1543 case EFI_IFR_QUESTION_REF2_OP
:
1545 // Pop an expression from the expression stack
1547 Status
= PopExpression (Value
);
1548 if (EFI_ERROR (Status
)) {
1553 // Validate the expression value
1555 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
1556 return EFI_NOT_FOUND
;
1559 Question
= IdToQuestion (FormSet
, Form
, Value
->Value
.u16
);
1560 if (Question
== NULL
) {
1561 return EFI_NOT_FOUND
;
1564 Value
= &Question
->HiiValue
;
1567 case EFI_IFR_STRING_REF2_OP
:
1569 // Pop an expression from the expression stack
1571 Status
= PopExpression (Value
);
1572 if (EFI_ERROR (Status
)) {
1577 // Validate the expression value
1579 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
1580 return EFI_NOT_FOUND
;
1583 Value
->Type
= EFI_IFR_TYPE_STRING
;
1584 StrPtr
= GetToken (Value
->Value
.u16
, FormSet
->HiiHandle
);
1585 if (StrPtr
== NULL
) {
1587 // If String not exit, push an empty string
1589 Value
->Value
.string
= NewString (gEmptyString
, FormSet
->HiiHandle
);
1591 Index
= (UINT16
) Value
->Value
.u64
;
1592 Value
->Value
.string
= Index
;
1597 case EFI_IFR_TO_BOOLEAN_OP
:
1599 // Pop an expression from the expression stack
1601 Status
= PopExpression (Value
);
1602 if (EFI_ERROR (Status
)) {
1607 // Convert an expression to a Boolean
1609 if (Value
->Type
<= EFI_IFR_TYPE_DATE
) {
1611 // When converting from an unsigned integer, zero will be converted to
1612 // FALSE and any other value will be converted to TRUE.
1614 Value
->Value
.b
= (BOOLEAN
) ((Value
->Value
.u64
) ? TRUE
: FALSE
);
1616 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
1617 } else if (Value
->Type
== EFI_IFR_TYPE_STRING
) {
1619 // When converting from a string, if case-insensitive compare
1620 // with "true" is True, then push True. If a case-insensitive compare
1621 // with "false" is True, then push False.
1623 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->HiiHandle
);
1624 if (StrPtr
== NULL
) {
1625 return EFI_INVALID_PARAMETER
;
1628 if ((StrCmp (StrPtr
, L
"true") == 0) || (StrCmp (StrPtr
, L
"false") == 0)){
1629 Value
->Value
.b
= TRUE
;
1631 Value
->Value
.b
= FALSE
;
1634 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
1638 case EFI_IFR_TO_STRING_OP
:
1639 Status
= IfrToString (FormSet
, OpCode
->Format
, Value
);
1642 case EFI_IFR_TO_UINT_OP
:
1643 Status
= IfrToUint (FormSet
, Value
);
1646 case EFI_IFR_TO_LOWER_OP
:
1647 case EFI_IFR_TO_UPPER_OP
:
1648 Status
= InitializeUnicodeCollationProtocol ();
1649 if (EFI_ERROR (Status
)) {
1653 Status
= PopExpression (Value
);
1654 if (EFI_ERROR (Status
)) {
1658 if (Value
->Type
!= EFI_IFR_TYPE_STRING
) {
1659 return EFI_UNSUPPORTED
;
1662 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->HiiHandle
);
1663 if (StrPtr
== NULL
) {
1664 return EFI_NOT_FOUND
;
1667 if (OpCode
->Operand
== EFI_IFR_TO_LOWER_OP
) {
1668 mUnicodeCollation
->StrLwr (mUnicodeCollation
, StrPtr
);
1670 mUnicodeCollation
->StrUpr (mUnicodeCollation
, StrPtr
);
1672 Value
->Value
.string
= NewString (StrPtr
, FormSet
->HiiHandle
);
1676 case EFI_IFR_BITWISE_NOT_OP
:
1678 // Pop an expression from the expression stack
1680 Status
= PopExpression (Value
);
1681 if (EFI_ERROR (Status
)) {
1684 if (Value
->Type
> EFI_IFR_TYPE_DATE
) {
1685 return EFI_INVALID_PARAMETER
;
1688 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1689 Value
->Value
.u64
= ~Value
->Value
.u64
;
1695 case EFI_IFR_ADD_OP
:
1696 case EFI_IFR_SUBTRACT_OP
:
1697 case EFI_IFR_MULTIPLY_OP
:
1698 case EFI_IFR_DIVIDE_OP
:
1699 case EFI_IFR_MODULO_OP
:
1700 case EFI_IFR_BITWISE_AND_OP
:
1701 case EFI_IFR_BITWISE_OR_OP
:
1702 case EFI_IFR_SHIFT_LEFT_OP
:
1703 case EFI_IFR_SHIFT_RIGHT_OP
:
1705 // Pop an expression from the expression stack
1707 Status
= PopExpression (&Data2
);
1708 if (EFI_ERROR (Status
)) {
1711 if (Data2
.Type
> EFI_IFR_TYPE_DATE
) {
1712 return EFI_INVALID_PARAMETER
;
1716 // Pop another expression from the expression stack
1718 Status
= PopExpression (&Data1
);
1719 if (EFI_ERROR (Status
)) {
1722 if (Data1
.Type
> EFI_IFR_TYPE_DATE
) {
1723 return EFI_INVALID_PARAMETER
;
1726 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1728 switch (OpCode
->Operand
) {
1729 case EFI_IFR_ADD_OP
:
1730 Value
->Value
.u64
= Data1
.Value
.u64
+ Data2
.Value
.u64
;
1733 case EFI_IFR_SUBTRACT_OP
:
1734 Value
->Value
.u64
= Data1
.Value
.u64
- Data2
.Value
.u64
;
1737 case EFI_IFR_MULTIPLY_OP
:
1738 Value
->Value
.u64
= MultU64x32 (Data1
.Value
.u64
, (UINT32
) Data2
.Value
.u64
);
1741 case EFI_IFR_DIVIDE_OP
:
1742 Value
->Value
.u64
= DivU64x32 (Data1
.Value
.u64
, (UINT32
) Data2
.Value
.u64
);
1745 case EFI_IFR_MODULO_OP
:
1746 DivU64x32Remainder (Data1
.Value
.u64
, (UINT32
) Data2
.Value
.u64
, &TempValue
);
1747 Value
->Value
.u64
= TempValue
;
1750 case EFI_IFR_BITWISE_AND_OP
:
1751 Value
->Value
.u64
= Data1
.Value
.u64
& Data2
.Value
.u64
;
1754 case EFI_IFR_BITWISE_OR_OP
:
1755 Value
->Value
.u64
= Data1
.Value
.u64
| Data2
.Value
.u64
;
1758 case EFI_IFR_SHIFT_LEFT_OP
:
1759 Value
->Value
.u64
= LShiftU64 (Data1
.Value
.u64
, (UINTN
) Data2
.Value
.u64
);
1762 case EFI_IFR_SHIFT_RIGHT_OP
:
1763 Value
->Value
.u64
= RShiftU64 (Data1
.Value
.u64
, (UINTN
) Data2
.Value
.u64
);
1771 case EFI_IFR_AND_OP
:
1774 // Two Boolean operator
1776 Status
= PopExpression (&Data2
);
1777 if (EFI_ERROR (Status
)) {
1780 if (Data2
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
1781 return EFI_INVALID_PARAMETER
;
1785 // Pop another expression from the expression stack
1787 Status
= PopExpression (&Data1
);
1788 if (EFI_ERROR (Status
)) {
1791 if (Data1
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
1792 return EFI_INVALID_PARAMETER
;
1795 if (OpCode
->Operand
== EFI_IFR_AND_OP
) {
1796 Value
->Value
.b
= (BOOLEAN
) (Data1
.Value
.b
&& Data2
.Value
.b
);
1798 Value
->Value
.b
= (BOOLEAN
) (Data1
.Value
.b
|| Data2
.Value
.b
);
1802 case EFI_IFR_EQUAL_OP
:
1803 case EFI_IFR_NOT_EQUAL_OP
:
1804 case EFI_IFR_GREATER_EQUAL_OP
:
1805 case EFI_IFR_GREATER_THAN_OP
:
1806 case EFI_IFR_LESS_EQUAL_OP
:
1807 case EFI_IFR_LESS_THAN_OP
:
1809 // Compare two integer, string, boolean or date/time
1811 Status
= PopExpression (&Data2
);
1812 if (EFI_ERROR (Status
)) {
1815 if (Data2
.Type
> EFI_IFR_TYPE_BOOLEAN
&& Data2
.Type
!= EFI_IFR_TYPE_STRING
) {
1816 return EFI_INVALID_PARAMETER
;
1820 // Pop another expression from the expression stack
1822 Status
= PopExpression (&Data1
);
1823 if (EFI_ERROR (Status
)) {
1827 Result
= CompareHiiValue (&Data1
, &Data2
, FormSet
->HiiHandle
);
1828 if (Result
== EFI_INVALID_PARAMETER
) {
1829 return EFI_INVALID_PARAMETER
;
1832 switch (OpCode
->Operand
) {
1833 case EFI_IFR_EQUAL_OP
:
1834 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
1837 case EFI_IFR_NOT_EQUAL_OP
:
1838 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
1841 case EFI_IFR_GREATER_EQUAL_OP
:
1842 Value
->Value
.b
= (BOOLEAN
) ((Result
>= 0) ? TRUE
: FALSE
);
1845 case EFI_IFR_GREATER_THAN_OP
:
1846 Value
->Value
.b
= (BOOLEAN
) ((Result
> 0) ? TRUE
: FALSE
);
1849 case EFI_IFR_LESS_EQUAL_OP
:
1850 Value
->Value
.b
= (BOOLEAN
) ((Result
<= 0) ? TRUE
: FALSE
);
1853 case EFI_IFR_LESS_THAN_OP
:
1854 Value
->Value
.b
= (BOOLEAN
) ((Result
< 0) ? TRUE
: FALSE
);
1862 case EFI_IFR_MATCH_OP
:
1863 Status
= IfrMatch (FormSet
, Value
);
1866 case EFI_IFR_CATENATE_OP
:
1867 Status
= IfrCatenate (FormSet
, Value
);
1873 case EFI_IFR_CONDITIONAL_OP
:
1875 // Pop third expression from the expression stack
1877 Status
= PopExpression (&Data3
);
1878 if (EFI_ERROR (Status
)) {
1883 // Pop second expression from the expression stack
1885 Status
= PopExpression (&Data2
);
1886 if (EFI_ERROR (Status
)) {
1891 // Pop first expression from the expression stack
1893 Status
= PopExpression (&Data1
);
1894 if (EFI_ERROR (Status
)) {
1897 if (Data1
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
1898 return EFI_INVALID_PARAMETER
;
1901 if (Data1
.Value
.b
) {
1908 case EFI_IFR_FIND_OP
:
1909 Status
= IfrFind (FormSet
, OpCode
->Format
, Value
);
1912 case EFI_IFR_MID_OP
:
1913 Status
= IfrMid (FormSet
, Value
);
1916 case EFI_IFR_TOKEN_OP
:
1917 Status
= IfrToken (FormSet
, Value
);
1920 case EFI_IFR_SPAN_OP
:
1921 Status
= IfrSpan (FormSet
, OpCode
->Flags
, Value
);
1927 if (EFI_ERROR (Status
)) {
1931 Status
= PushExpression (Value
);
1932 if (EFI_ERROR (Status
)) {
1938 // Pop the final result from expression stack
1941 Status
= PopExpression (Value
);
1942 if (EFI_ERROR (Status
)) {
1947 // After evaluating an expression, there should be only one value left on the expression stack
1949 if (PopExpression (Value
) != EFI_ACCESS_DENIED
) {
1950 return EFI_INVALID_PARAMETER
;
1953 CopyMem (&Expression
->Result
, Value
, sizeof (EFI_HII_VALUE
));