2 Utility functions for expression evaluation.
4 Copyright (c) 2007, 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
) {
427 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
435 Get Expression given its RuleId.
437 @param Form The form which contains this Expression.
438 @param RuleId Id of this Expression.
440 @retval Pointer The Expression.
441 @retval NULL Specified Expression not found in the form.
446 IN FORM_BROWSER_FORM
*Form
,
451 FORM_EXPRESSION
*Expression
;
453 Link
= GetFirstNode (&Form
->ExpressionListHead
);
454 while (!IsNull (&Form
->ExpressionListHead
, Link
)) {
455 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
457 if (Expression
->Type
== EFI_HII_EXPRESSION_RULE
&& Expression
->RuleId
== RuleId
) {
461 Link
= GetNextNode (&Form
->ExpressionListHead
, Link
);
469 Locate the Unicode Collation Protocol interface for later use.
471 @retval EFI_SUCCESS Protocol interface initialize success.
472 @retval Other Protocol interface initialize failed.
476 InitializeUnicodeCollationProtocol (
482 if (mUnicodeCollation
!= NULL
) {
487 // BUGBUG: Proper impelmentation is to locate all Unicode Collation Protocol
488 // instances first and then select one which support English language.
489 // Current implementation just pick the first instance.
491 Status
= gBS
->LocateProtocol (
492 &gEfiUnicodeCollation2ProtocolGuid
,
494 (VOID
**) &mUnicodeCollation
500 Convert the input Unicode character to upper.
502 @param String Th Unicode character to be converted.
510 while (*String
!= 0) {
511 if ((*String
>= 'a') && (*String
<= 'z')) {
512 *String
= (UINT16
) ((*String
) & ((UINT16
) ~0x20));
520 Evaluate opcode EFI_IFR_TO_STRING.
522 @param FormSet Formset which contains this opcode.
523 @param Format String format in EFI_IFR_TO_STRING.
524 @param Result Evaluation result for this opcode.
526 @retval EFI_SUCCESS Opcode evaluation success.
527 @retval Other Opcode evaluation failed.
532 IN FORM_BROWSER_FORMSET
*FormSet
,
534 OUT EFI_HII_VALUE
*Result
541 CHAR16 Buffer
[MAXIMUM_VALUE_CHARACTERS
];
544 Status
= PopExpression (&Value
);
545 if (EFI_ERROR (Status
)) {
549 switch (Value
.Type
) {
550 case EFI_IFR_TYPE_NUM_SIZE_8
:
551 case EFI_IFR_TYPE_NUM_SIZE_16
:
552 case EFI_IFR_TYPE_NUM_SIZE_32
:
553 case EFI_IFR_TYPE_NUM_SIZE_64
:
554 BufferSize
= MAXIMUM_VALUE_CHARACTERS
* sizeof (CHAR16
);
556 case EFI_IFR_STRING_UNSIGNED_DEC
:
557 case EFI_IFR_STRING_SIGNED_DEC
:
558 PrintFormat
= L
"%ld";
561 case EFI_IFR_STRING_LOWERCASE_HEX
:
562 PrintFormat
= L
"%lx";
565 case EFI_IFR_STRING_UPPERCASE_HEX
:
566 PrintFormat
= L
"%lX";
570 return EFI_UNSUPPORTED
;
572 UnicodeSPrint (Buffer
, BufferSize
, PrintFormat
, Value
.Value
.u64
);
576 case EFI_IFR_TYPE_STRING
:
577 CopyMem (Result
, &Value
, sizeof (EFI_HII_VALUE
));
580 case EFI_IFR_TYPE_BOOLEAN
:
581 String
= (Value
.Value
.b
) ? L
"True" : L
"False";
585 return EFI_UNSUPPORTED
;
588 Result
->Type
= EFI_IFR_TYPE_STRING
;
589 Result
->Value
.string
= NewString (String
, FormSet
->HiiHandle
);
595 Evaluate opcode EFI_IFR_TO_UINT.
597 @param FormSet Formset which contains this opcode.
598 @param Result Evaluation result for this opcode.
600 @retval EFI_SUCCESS Opcode evaluation success.
601 @retval Other Opcode evaluation failed.
606 IN FORM_BROWSER_FORMSET
*FormSet
,
607 OUT EFI_HII_VALUE
*Result
616 Status
= PopExpression (&Value
);
617 if (EFI_ERROR (Status
)) {
621 if (Value
.Type
>= EFI_IFR_TYPE_OTHER
) {
622 return EFI_UNSUPPORTED
;
625 Status
= EFI_SUCCESS
;
626 if (Value
.Type
== EFI_IFR_TYPE_STRING
) {
627 String
= GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
628 if (String
== NULL
) {
629 return EFI_NOT_FOUND
;
632 IfrStrToUpper (String
);
633 StringPtr
= StrStr (String
, L
"0X");
634 if (StringPtr
!= NULL
) {
638 BufferSize
= sizeof (UINT64
);
639 Status
= HexStringToBuf ((UINT8
*) &Result
->Value
.u64
, &BufferSize
, StringPtr
+ 2, NULL
);
642 // BUGBUG: Need handle decimal string
645 gBS
->FreePool (String
);
647 CopyMem (Result
, &Value
, sizeof (EFI_HII_VALUE
));
650 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
656 Evaluate opcode EFI_IFR_CATENATE.
658 @param FormSet Formset which contains this opcode.
659 @param Result Evaluation result for this opcode.
661 @retval EFI_SUCCESS Opcode evaluation success.
662 @retval Other Opcode evaluation failed.
667 IN FORM_BROWSER_FORMSET
*FormSet
,
668 OUT EFI_HII_VALUE
*Result
679 // String[0] - The second string
680 // String[1] - The first string
685 Status
= EFI_SUCCESS
;
687 for (Index
= 0; Index
< 2; Index
++) {
688 Status
= PopExpression (&Value
);
689 if (EFI_ERROR (Status
)) {
693 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
694 Status
= EFI_UNSUPPORTED
;
698 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
700 Status
= EFI_NOT_FOUND
;
705 Size
= StrSize (String
[0]);
706 StringPtr
= AllocatePool (StrSize (String
[1]) + Size
);
707 ASSERT (StringPtr
!= NULL
);
708 StrCpy (StringPtr
, String
[1]);
709 StrCat (StringPtr
, String
[0]);
711 Result
->Type
= EFI_IFR_TYPE_STRING
;
712 Result
->Value
.string
= NewString (StringPtr
, FormSet
->HiiHandle
);
715 if (String
[0] != NULL
) {
716 FreePool (String
[0]);
718 if (String
[1] != NULL
) {
719 FreePool (String
[1]);
721 if (StringPtr
!= NULL
) {
722 FreePool (StringPtr
);
730 Evaluate opcode EFI_IFR_MATCH.
732 @param FormSet Formset which contains this opcode.
733 @param Result Evaluation result for this opcode.
735 @retval EFI_SUCCESS Opcode evaluation success.
736 @retval Other Opcode evaluation failed.
741 IN FORM_BROWSER_FORMSET
*FormSet
,
742 OUT EFI_HII_VALUE
*Result
751 // String[0] - The string to search
752 // String[1] - pattern
756 Status
= EFI_SUCCESS
;
757 for (Index
= 0; Index
< 2; Index
++) {
758 Status
= PopExpression (&Value
);
759 if (EFI_ERROR (Status
)) {
763 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
764 Status
= EFI_UNSUPPORTED
;
768 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
770 Status
= EFI_NOT_FOUND
;
775 Result
->Type
= EFI_IFR_TYPE_BOOLEAN
;
776 Result
->Value
.b
= mUnicodeCollation
->MetaiMatch (mUnicodeCollation
, String
[0], String
[1]);
779 if (String
[0] != NULL
) {
780 FreePool (String
[0]);
782 if (String
[1] != NULL
) {
783 FreePool (String
[1]);
791 Evaluate opcode EFI_IFR_FIND.
793 @param FormSet Formset which contains this opcode.
794 @param Format Case sensitive or insensitive.
795 @param Result Evaluation result for this opcode.
797 @retval EFI_SUCCESS Opcode evaluation success.
798 @retval Other Opcode evaluation failed.
803 IN FORM_BROWSER_FORMSET
*FormSet
,
805 OUT EFI_HII_VALUE
*Result
815 if (Format
> EFI_IFR_FF_CASE_INSENSITIVE
) {
816 return EFI_UNSUPPORTED
;
819 Status
= PopExpression (&Value
);
820 if (EFI_ERROR (Status
)) {
823 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
824 return EFI_UNSUPPORTED
;
826 Base
= (UINTN
) Value
.Value
.u64
;
829 // String[0] - sub-string
830 // String[1] - The string to search
834 for (Index
= 0; Index
< 2; Index
++) {
835 Status
= PopExpression (&Value
);
836 if (EFI_ERROR (Status
)) {
840 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
841 Status
= EFI_UNSUPPORTED
;
845 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
847 Status
= EFI_NOT_FOUND
;
851 if (Format
== EFI_IFR_FF_CASE_INSENSITIVE
) {
853 // Case insensitive, convert both string to upper case
855 IfrStrToUpper (String
[Index
]);
859 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
860 if (Base
>= StrLen (String
[1])) {
861 Result
->Value
.u64
= 0xFFFFFFFFFFFFFFFFULL
;
863 StringPtr
= StrStr (String
[1] + Base
, String
[0]);
864 Result
->Value
.u64
= (StringPtr
== NULL
) ? 0xFFFFFFFFFFFFFFFFULL
: (StringPtr
- String
[1]);
868 if (String
[0] != NULL
) {
869 FreePool (String
[0]);
871 if (String
[1] != NULL
) {
872 FreePool (String
[1]);
880 Evaluate opcode EFI_IFR_MID.
882 @param FormSet Formset which contains this opcode.
883 @param Result Evaluation result for this opcode.
885 @retval EFI_SUCCESS Opcode evaluation success.
886 @retval Other Opcode evaluation failed.
891 IN FORM_BROWSER_FORMSET
*FormSet
,
892 OUT EFI_HII_VALUE
*Result
902 Status
= PopExpression (&Value
);
903 if (EFI_ERROR (Status
)) {
906 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
907 return EFI_UNSUPPORTED
;
909 Length
= (UINTN
) Value
.Value
.u64
;
911 Status
= PopExpression (&Value
);
912 if (EFI_ERROR (Status
)) {
915 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
916 return EFI_UNSUPPORTED
;
918 Base
= (UINTN
) Value
.Value
.u64
;
920 Status
= PopExpression (&Value
);
921 if (EFI_ERROR (Status
)) {
924 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
925 return EFI_UNSUPPORTED
;
927 String
= GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
928 if (String
== NULL
) {
929 return EFI_NOT_FOUND
;
932 if (Length
== 0 || Base
>= StrLen (String
)) {
933 SubString
= gEmptyString
;
935 SubString
= String
+ Base
;
936 if ((Base
+ Length
) < StrLen (String
)) {
937 SubString
[Length
] = L
'\0';
941 Result
->Type
= EFI_IFR_TYPE_STRING
;
942 Result
->Value
.string
= NewString (SubString
, FormSet
->HiiHandle
);
944 gBS
->FreePool (String
);
951 Evaluate opcode EFI_IFR_TOKEN.
953 @param FormSet Formset which contains this opcode.
954 @param Result Evaluation result for this opcode.
956 @retval EFI_SUCCESS Opcode evaluation success.
957 @retval Other Opcode evaluation failed.
962 IN FORM_BROWSER_FORMSET
*FormSet
,
963 OUT EFI_HII_VALUE
*Result
975 Status
= PopExpression (&Value
);
976 if (EFI_ERROR (Status
)) {
979 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
980 return EFI_UNSUPPORTED
;
982 Count
= (UINTN
) Value
.Value
.u64
;
985 // String[0] - Delimiter
986 // String[1] - The string to search
990 for (Index
= 0; Index
< 2; Index
++) {
991 Status
= PopExpression (&Value
);
992 if (EFI_ERROR (Status
)) {
996 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
997 Status
= EFI_UNSUPPORTED
;
1001 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
1002 if (String
== NULL
) {
1003 Status
= EFI_NOT_FOUND
;
1008 Delimiter
= String
[0];
1009 SubString
= String
[1];
1011 SubString
= StrStr (SubString
, Delimiter
);
1012 if (SubString
!= NULL
) {
1014 // Skip over the delimiter
1016 SubString
= SubString
+ StrLen (Delimiter
);
1023 if (SubString
== NULL
) {
1025 // nth delimited sub-string not found, push an empty string
1027 SubString
= gEmptyString
;
1030 // Put a NULL terminator for nth delimited sub-string
1032 StringPtr
= StrStr (SubString
, Delimiter
);
1033 if (StringPtr
!= NULL
) {
1038 Result
->Type
= EFI_IFR_TYPE_STRING
;
1039 Result
->Value
.string
= NewString (SubString
, FormSet
->HiiHandle
);
1042 if (String
[0] != NULL
) {
1043 FreePool (String
[0]);
1045 if (String
[1] != NULL
) {
1046 FreePool (String
[1]);
1054 Evaluate opcode EFI_IFR_SPAN.
1056 @param FormSet Formset which contains this opcode.
1057 @param Flags FIRST_MATCHING or FIRST_NON_MATCHING.
1058 @param Result Evaluation result for this opcode.
1060 @retval EFI_SUCCESS Opcode evaluation success.
1061 @retval Other Opcode evaluation failed.
1066 IN FORM_BROWSER_FORMSET
*FormSet
,
1068 OUT EFI_HII_VALUE
*Result
1072 EFI_HII_VALUE Value
;
1080 Status
= PopExpression (&Value
);
1081 if (EFI_ERROR (Status
)) {
1084 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1085 return EFI_UNSUPPORTED
;
1087 Base
= (UINTN
) Value
.Value
.u64
;
1090 // String[0] - Charset
1091 // String[1] - The string to search
1095 for (Index
= 0; Index
< 2; Index
++) {
1096 Status
= PopExpression (&Value
);
1097 if (EFI_ERROR (Status
)) {
1101 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
1102 Status
= EFI_UNSUPPORTED
;
1106 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
1107 if (String
== NULL
) {
1108 Status
= EFI_NOT_FOUND
;
1113 if (Base
>= StrLen (String
[1])) {
1114 Status
= EFI_UNSUPPORTED
;
1119 StringPtr
= String
[1] + Base
;
1120 Charset
= String
[0];
1121 while (*StringPtr
!= 0 && !Found
) {
1123 while (Charset
[Index
] != 0) {
1124 if (*StringPtr
>= Charset
[Index
] && *StringPtr
<= Charset
[Index
+ 1]) {
1125 if (Flags
== EFI_IFR_FLAGS_FIRST_MATCHING
) {
1130 if (Flags
== EFI_IFR_FLAGS_FIRST_NON_MATCHING
) {
1136 // Skip characters pair representing low-end of a range and high-end of a range
1146 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1147 Result
->Value
.u64
= StringPtr
- String
[1];
1150 if (String
[0] != NULL
) {
1151 FreePool (String
[0]);
1153 if (String
[1] != NULL
) {
1154 FreePool (String
[1]);
1162 Zero extend integer/boolean/date/time to UINT64 for comparing.
1164 @param Value HII Value to be converted.
1169 IN EFI_HII_VALUE
*Value
1175 switch (Value
->Type
) {
1176 case EFI_IFR_TYPE_NUM_SIZE_8
:
1177 Temp
= Value
->Value
.u8
;
1180 case EFI_IFR_TYPE_NUM_SIZE_16
:
1181 Temp
= Value
->Value
.u16
;
1184 case EFI_IFR_TYPE_NUM_SIZE_32
:
1185 Temp
= Value
->Value
.u32
;
1188 case EFI_IFR_TYPE_BOOLEAN
:
1189 Temp
= Value
->Value
.b
;
1192 case EFI_IFR_TYPE_TIME
:
1193 Temp
= Value
->Value
.u32
& 0xffffff;
1196 case EFI_IFR_TYPE_DATE
:
1197 Temp
= Value
->Value
.u32
;
1204 Value
->Value
.u64
= Temp
;
1209 Compare two Hii value.
1211 @param Value1 Expression value to compare on left-hand.
1212 @param Value2 Expression value to compare on right-hand.
1213 @param HiiHandle Only required for string compare.
1215 @retval EFI_INVALID_PARAMETER Could not perform comparation on two values.
1216 @retval 0 Two operators equeal.
1217 @return Positive value if Value1 is greater than Value2.
1218 @retval Negative value if Value1 is less than Value2.
1223 IN EFI_HII_VALUE
*Value1
,
1224 IN EFI_HII_VALUE
*Value2
,
1225 IN EFI_HII_HANDLE HiiHandle OPTIONAL
1233 if (Value1
->Type
>= EFI_IFR_TYPE_OTHER
|| Value2
->Type
>= EFI_IFR_TYPE_OTHER
) {
1234 return EFI_INVALID_PARAMETER
;
1237 if (Value1
->Type
== EFI_IFR_TYPE_STRING
|| Value2
->Type
== EFI_IFR_TYPE_STRING
) {
1238 if (Value1
->Type
!= Value2
->Type
) {
1240 // Both Operator should be type of String
1242 return EFI_INVALID_PARAMETER
;
1245 if (Value1
->Value
.string
== 0 || Value2
->Value
.string
== 0) {
1247 // StringId 0 is reserved
1249 return EFI_INVALID_PARAMETER
;
1252 if (Value1
->Value
.string
== Value2
->Value
.string
) {
1256 Str1
= GetToken (Value1
->Value
.string
, HiiHandle
);
1261 return EFI_INVALID_PARAMETER
;
1264 Str2
= GetToken (Value2
->Value
.string
, HiiHandle
);
1266 gBS
->FreePool (Str1
);
1267 return EFI_INVALID_PARAMETER
;
1270 Result
= StrCmp (Str1
, Str2
);
1272 gBS
->FreePool (Str1
);
1273 gBS
->FreePool (Str2
);
1279 // Take remain types(integer, boolean, date/time) as integer
1281 Temp64
= (INT64
) (Value1
->Value
.u64
- Value2
->Value
.u64
);
1284 } else if (Temp64
< 0) {
1295 Evaluate the result of a HII expression
1297 @param FormSet FormSet associated with this expression.
1298 @param Form Form associated with this expression.
1299 @param Expression Expression to be evaluated.
1301 @retval EFI_SUCCESS The expression evaluated successfuly
1302 @retval EFI_NOT_FOUND The Question which referenced by a QuestionId
1304 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
1306 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
1307 @retval EFI_INVALID_PARAMETER Syntax error with the Expression
1311 EvaluateExpression (
1312 IN FORM_BROWSER_FORMSET
*FormSet
,
1313 IN FORM_BROWSER_FORM
*Form
,
1314 IN OUT FORM_EXPRESSION
*Expression
1319 EXPRESSION_OPCODE
*OpCode
;
1320 FORM_BROWSER_STATEMENT
*Question
;
1321 FORM_BROWSER_STATEMENT
*Question2
;
1323 EFI_HII_VALUE Data1
;
1324 EFI_HII_VALUE Data2
;
1325 EFI_HII_VALUE Data3
;
1326 FORM_EXPRESSION
*RuleExpression
;
1327 EFI_HII_VALUE
*Value
;
1333 // Always reset the stack before evaluating an Expression
1335 ResetExpressionStack ();
1337 Expression
->Result
.Type
= EFI_IFR_TYPE_OTHER
;
1339 Link
= GetFirstNode (&Expression
->OpCodeListHead
);
1340 while (!IsNull (&Expression
->OpCodeListHead
, Link
)) {
1341 OpCode
= EXPRESSION_OPCODE_FROM_LINK (Link
);
1343 Link
= GetNextNode (&Expression
->OpCodeListHead
, Link
);
1345 ZeroMem (&Data1
, sizeof (EFI_HII_VALUE
));
1346 ZeroMem (&Data2
, sizeof (EFI_HII_VALUE
));
1347 ZeroMem (&Data3
, sizeof (EFI_HII_VALUE
));
1350 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
1351 Status
= EFI_SUCCESS
;
1353 switch (OpCode
->Operand
) {
1355 // Built-in functions
1357 case EFI_IFR_EQ_ID_VAL_OP
:
1358 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
1359 if (Question
== NULL
) {
1360 return EFI_NOT_FOUND
;
1363 Result
= CompareHiiValue (&Question
->HiiValue
, &OpCode
->Value
, NULL
);
1364 if (Result
== EFI_INVALID_PARAMETER
) {
1365 return EFI_INVALID_PARAMETER
;
1367 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
1370 case EFI_IFR_EQ_ID_ID_OP
:
1371 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
1372 if (Question
== NULL
) {
1373 return EFI_NOT_FOUND
;
1376 Question2
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId2
);
1377 if (Question2
== NULL
) {
1378 return EFI_NOT_FOUND
;
1381 Result
= CompareHiiValue (&Question
->HiiValue
, &Question2
->HiiValue
, FormSet
->HiiHandle
);
1382 if (Result
== EFI_INVALID_PARAMETER
) {
1383 return EFI_INVALID_PARAMETER
;
1385 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
1388 case EFI_IFR_EQ_ID_LIST_OP
:
1389 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
1390 if (Question
== NULL
) {
1391 return EFI_NOT_FOUND
;
1394 Value
->Value
.b
= FALSE
;
1395 for (Index
=0; Index
< OpCode
->ListLength
; Index
++) {
1396 if (Question
->HiiValue
.Value
.u16
== OpCode
->ValueList
[Index
]) {
1397 Value
->Value
.b
= TRUE
;
1403 case EFI_IFR_DUP_OP
:
1404 Status
= PopExpression (Value
);
1405 if (EFI_ERROR (Status
)) {
1409 Status
= PushExpression (Value
);
1412 case EFI_IFR_QUESTION_REF1_OP
:
1413 case EFI_IFR_THIS_OP
:
1414 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
1415 if (Question
== NULL
) {
1416 return EFI_NOT_FOUND
;
1419 Value
= &Question
->HiiValue
;
1422 case EFI_IFR_QUESTION_REF3_OP
:
1423 if (OpCode
->DevicePath
== 0) {
1425 // EFI_IFR_QUESTION_REF3
1426 // Pop an expression from the expression stack
1428 Status
= PopExpression (Value
);
1429 if (EFI_ERROR (Status
)) {
1434 // Validate the expression value
1436 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
1437 return EFI_NOT_FOUND
;
1440 Question
= IdToQuestion (FormSet
, Form
, Value
->Value
.u16
);
1441 if (Question
== NULL
) {
1442 return EFI_NOT_FOUND
;
1446 // push the questions' value on to the expression stack
1448 Value
= &Question
->HiiValue
;
1451 // BUGBUG: push 0 for EFI_IFR_QUESTION_REF3_2 and EFI_IFR_QUESTION_REF3_3,
1452 // since it is impractical to evaluate the value of a Question in another
1453 // Hii Package list.
1455 ZeroMem (Value
, sizeof (EFI_HII_VALUE
));
1459 case EFI_IFR_RULE_REF_OP
:
1461 // Find expression for this rule
1463 RuleExpression
= RuleIdToExpression (Form
, OpCode
->RuleId
);
1464 if (RuleExpression
== NULL
) {
1465 return EFI_NOT_FOUND
;
1469 // Evaluate this rule expression
1471 Status
= EvaluateExpression (FormSet
, Form
, RuleExpression
);
1472 if (EFI_ERROR (Status
)) {
1476 Value
= &RuleExpression
->Result
;
1479 case EFI_IFR_STRING_REF1_OP
:
1480 Value
->Type
= EFI_IFR_TYPE_STRING
;
1481 Value
->Value
.string
= OpCode
->Value
.Value
.string
;
1487 case EFI_IFR_TRUE_OP
:
1488 case EFI_IFR_FALSE_OP
:
1489 case EFI_IFR_ONE_OP
:
1490 case EFI_IFR_ONES_OP
:
1491 case EFI_IFR_UINT8_OP
:
1492 case EFI_IFR_UINT16_OP
:
1493 case EFI_IFR_UINT32_OP
:
1494 case EFI_IFR_UINT64_OP
:
1495 case EFI_IFR_UNDEFINED_OP
:
1496 case EFI_IFR_VERSION_OP
:
1497 case EFI_IFR_ZERO_OP
:
1498 Value
= &OpCode
->Value
;
1504 case EFI_IFR_LENGTH_OP
:
1505 Status
= PopExpression (Value
);
1506 if (EFI_ERROR (Status
)) {
1509 if (Value
->Type
!= EFI_IFR_TYPE_STRING
) {
1510 return EFI_INVALID_PARAMETER
;
1513 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->HiiHandle
);
1514 if (StrPtr
== NULL
) {
1515 return EFI_INVALID_PARAMETER
;
1518 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1519 Value
->Value
.u64
= StrLen (StrPtr
);
1520 gBS
->FreePool (StrPtr
);
1523 case EFI_IFR_NOT_OP
:
1524 Status
= PopExpression (Value
);
1525 if (EFI_ERROR (Status
)) {
1528 if (Value
->Type
!= EFI_IFR_TYPE_BOOLEAN
) {
1529 return EFI_INVALID_PARAMETER
;
1531 Value
->Value
.b
= (BOOLEAN
) (!Value
->Value
.b
);
1534 case EFI_IFR_QUESTION_REF2_OP
:
1536 // Pop an expression from the expression stack
1538 Status
= PopExpression (Value
);
1539 if (EFI_ERROR (Status
)) {
1544 // Validate the expression value
1546 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
1547 return EFI_NOT_FOUND
;
1550 Question
= IdToQuestion (FormSet
, Form
, Value
->Value
.u16
);
1551 if (Question
== NULL
) {
1552 return EFI_NOT_FOUND
;
1555 Value
= &Question
->HiiValue
;
1558 case EFI_IFR_STRING_REF2_OP
:
1560 // Pop an expression from the expression stack
1562 Status
= PopExpression (Value
);
1563 if (EFI_ERROR (Status
)) {
1568 // Validate the expression value
1570 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
1571 return EFI_NOT_FOUND
;
1574 Value
->Type
= EFI_IFR_TYPE_STRING
;
1575 StrPtr
= GetToken (Value
->Value
.u16
, FormSet
->HiiHandle
);
1576 if (StrPtr
== NULL
) {
1578 // If String not exit, push an empty string
1580 Value
->Value
.string
= NewString (gEmptyString
, FormSet
->HiiHandle
);
1582 Index
= (UINT16
) Value
->Value
.u64
;
1583 Value
->Value
.string
= Index
;
1584 gBS
->FreePool (StrPtr
);
1588 case EFI_IFR_TO_BOOLEAN_OP
:
1590 // Pop an expression from the expression stack
1592 Status
= PopExpression (Value
);
1593 if (EFI_ERROR (Status
)) {
1598 // Convert an expression to a Boolean
1600 if (Value
->Type
<= EFI_IFR_TYPE_DATE
) {
1602 // When converting from an unsigned integer, zero will be converted to
1603 // FALSE and any other value will be converted to TRUE.
1605 Value
->Value
.b
= (BOOLEAN
) ((Value
->Value
.u64
) ? TRUE
: FALSE
);
1607 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
1608 } else if (Value
->Type
== EFI_IFR_TYPE_STRING
) {
1610 // When converting from a string, if case-insensitive compare
1611 // with "true" is True, then push True. If a case-insensitive compare
1612 // with "false" is True, then push False.
1614 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->HiiHandle
);
1615 if (StrPtr
== NULL
) {
1616 return EFI_INVALID_PARAMETER
;
1619 if ((StrCmp (StrPtr
, L
"true") == 0) || (StrCmp (StrPtr
, L
"false") == 0)){
1620 Value
->Value
.b
= TRUE
;
1622 Value
->Value
.b
= FALSE
;
1624 gBS
->FreePool (StrPtr
);
1625 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
1629 case EFI_IFR_TO_STRING_OP
:
1630 Status
= IfrToString (FormSet
, OpCode
->Format
, Value
);
1633 case EFI_IFR_TO_UINT_OP
:
1634 Status
= IfrToUint (FormSet
, Value
);
1637 case EFI_IFR_TO_LOWER_OP
:
1638 case EFI_IFR_TO_UPPER_OP
:
1639 Status
= InitializeUnicodeCollationProtocol ();
1640 if (EFI_ERROR (Status
)) {
1644 Status
= PopExpression (Value
);
1645 if (EFI_ERROR (Status
)) {
1649 if (Value
->Type
!= EFI_IFR_TYPE_STRING
) {
1650 return EFI_UNSUPPORTED
;
1653 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->HiiHandle
);
1654 if (StrPtr
== NULL
) {
1655 return EFI_NOT_FOUND
;
1658 if (OpCode
->Operand
== EFI_IFR_TO_LOWER_OP
) {
1659 mUnicodeCollation
->StrLwr (mUnicodeCollation
, StrPtr
);
1661 mUnicodeCollation
->StrUpr (mUnicodeCollation
, StrPtr
);
1663 Value
->Value
.string
= NewString (StrPtr
, FormSet
->HiiHandle
);
1664 gBS
->FreePool (StrPtr
);
1667 case EFI_IFR_BITWISE_NOT_OP
:
1669 // Pop an expression from the expression stack
1671 Status
= PopExpression (Value
);
1672 if (EFI_ERROR (Status
)) {
1675 if (Value
->Type
> EFI_IFR_TYPE_DATE
) {
1676 return EFI_INVALID_PARAMETER
;
1679 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1680 Value
->Value
.u64
= ~Value
->Value
.u64
;
1686 case EFI_IFR_ADD_OP
:
1687 case EFI_IFR_SUBTRACT_OP
:
1688 case EFI_IFR_MULTIPLY_OP
:
1689 case EFI_IFR_DIVIDE_OP
:
1690 case EFI_IFR_MODULO_OP
:
1691 case EFI_IFR_BITWISE_AND_OP
:
1692 case EFI_IFR_BITWISE_OR_OP
:
1693 case EFI_IFR_SHIFT_LEFT_OP
:
1694 case EFI_IFR_SHIFT_RIGHT_OP
:
1696 // Pop an expression from the expression stack
1698 Status
= PopExpression (&Data2
);
1699 if (EFI_ERROR (Status
)) {
1702 if (Data2
.Type
> EFI_IFR_TYPE_DATE
) {
1703 return EFI_INVALID_PARAMETER
;
1707 // Pop another expression from the expression stack
1709 Status
= PopExpression (&Data1
);
1710 if (EFI_ERROR (Status
)) {
1713 if (Data1
.Type
> EFI_IFR_TYPE_DATE
) {
1714 return EFI_INVALID_PARAMETER
;
1717 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1719 switch (OpCode
->Operand
) {
1720 case EFI_IFR_ADD_OP
:
1721 Value
->Value
.u64
= Data1
.Value
.u64
+ Data2
.Value
.u64
;
1724 case EFI_IFR_SUBTRACT_OP
:
1725 Value
->Value
.u64
= Data1
.Value
.u64
- Data2
.Value
.u64
;
1728 case EFI_IFR_MULTIPLY_OP
:
1729 Value
->Value
.u64
= MultU64x32 (Data1
.Value
.u64
, (UINT32
) Data2
.Value
.u64
);
1732 case EFI_IFR_DIVIDE_OP
:
1733 Value
->Value
.u64
= DivU64x32 (Data1
.Value
.u64
, (UINT32
) Data2
.Value
.u64
);
1736 case EFI_IFR_MODULO_OP
:
1737 DivU64x32Remainder (Data1
.Value
.u64
, (UINT32
) Data2
.Value
.u64
, &TempValue
);
1738 Value
->Value
.u64
= TempValue
;
1741 case EFI_IFR_BITWISE_AND_OP
:
1742 Value
->Value
.u64
= Data1
.Value
.u64
& Data2
.Value
.u64
;
1745 case EFI_IFR_BITWISE_OR_OP
:
1746 Value
->Value
.u64
= Data1
.Value
.u64
| Data2
.Value
.u64
;
1749 case EFI_IFR_SHIFT_LEFT_OP
:
1750 Value
->Value
.u64
= LShiftU64 (Data1
.Value
.u64
, (UINTN
) Data2
.Value
.u64
);
1753 case EFI_IFR_SHIFT_RIGHT_OP
:
1754 Value
->Value
.u64
= RShiftU64 (Data1
.Value
.u64
, (UINTN
) Data2
.Value
.u64
);
1762 case EFI_IFR_AND_OP
:
1765 // Two Boolean operator
1767 Status
= PopExpression (&Data2
);
1768 if (EFI_ERROR (Status
)) {
1771 if (Data2
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
1772 return EFI_INVALID_PARAMETER
;
1776 // Pop another expression from the expression stack
1778 Status
= PopExpression (&Data1
);
1779 if (EFI_ERROR (Status
)) {
1782 if (Data1
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
1783 return EFI_INVALID_PARAMETER
;
1786 if (OpCode
->Operand
== EFI_IFR_AND_OP
) {
1787 Value
->Value
.b
= (BOOLEAN
) (Data1
.Value
.b
&& Data2
.Value
.b
);
1789 Value
->Value
.b
= (BOOLEAN
) (Data1
.Value
.b
|| Data2
.Value
.b
);
1793 case EFI_IFR_EQUAL_OP
:
1794 case EFI_IFR_NOT_EQUAL_OP
:
1795 case EFI_IFR_GREATER_EQUAL_OP
:
1796 case EFI_IFR_GREATER_THAN_OP
:
1797 case EFI_IFR_LESS_EQUAL_OP
:
1798 case EFI_IFR_LESS_THAN_OP
:
1800 // Compare two integer, string, boolean or date/time
1802 Status
= PopExpression (&Data2
);
1803 if (EFI_ERROR (Status
)) {
1806 if (Data2
.Type
> EFI_IFR_TYPE_BOOLEAN
&& Data2
.Type
!= EFI_IFR_TYPE_STRING
) {
1807 return EFI_INVALID_PARAMETER
;
1811 // Pop another expression from the expression stack
1813 Status
= PopExpression (&Data1
);
1814 if (EFI_ERROR (Status
)) {
1818 Result
= CompareHiiValue (&Data1
, &Data2
, FormSet
->HiiHandle
);
1819 if (Result
== EFI_INVALID_PARAMETER
) {
1820 return EFI_INVALID_PARAMETER
;
1823 switch (OpCode
->Operand
) {
1824 case EFI_IFR_EQUAL_OP
:
1825 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
1828 case EFI_IFR_NOT_EQUAL_OP
:
1829 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
1832 case EFI_IFR_GREATER_EQUAL_OP
:
1833 Value
->Value
.b
= (BOOLEAN
) ((Result
>= 0) ? TRUE
: FALSE
);
1836 case EFI_IFR_GREATER_THAN_OP
:
1837 Value
->Value
.b
= (BOOLEAN
) ((Result
> 0) ? TRUE
: FALSE
);
1840 case EFI_IFR_LESS_EQUAL_OP
:
1841 Value
->Value
.b
= (BOOLEAN
) ((Result
<= 0) ? TRUE
: FALSE
);
1844 case EFI_IFR_LESS_THAN_OP
:
1845 Value
->Value
.b
= (BOOLEAN
) ((Result
< 0) ? TRUE
: FALSE
);
1853 case EFI_IFR_MATCH_OP
:
1854 Status
= IfrMatch (FormSet
, Value
);
1857 case EFI_IFR_CATENATE_OP
:
1858 Status
= IfrCatenate (FormSet
, Value
);
1864 case EFI_IFR_CONDITIONAL_OP
:
1866 // Pop third expression from the expression stack
1868 Status
= PopExpression (&Data3
);
1869 if (EFI_ERROR (Status
)) {
1874 // Pop second expression from the expression stack
1876 Status
= PopExpression (&Data2
);
1877 if (EFI_ERROR (Status
)) {
1882 // Pop first expression from the expression stack
1884 Status
= PopExpression (&Data1
);
1885 if (EFI_ERROR (Status
)) {
1888 if (Data1
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
1889 return EFI_INVALID_PARAMETER
;
1892 if (Data1
.Value
.b
) {
1899 case EFI_IFR_FIND_OP
:
1900 Status
= IfrFind (FormSet
, OpCode
->Format
, Value
);
1903 case EFI_IFR_MID_OP
:
1904 Status
= IfrMid (FormSet
, Value
);
1907 case EFI_IFR_TOKEN_OP
:
1908 Status
= IfrToken (FormSet
, Value
);
1911 case EFI_IFR_SPAN_OP
:
1912 Status
= IfrSpan (FormSet
, OpCode
->Flags
, Value
);
1918 if (EFI_ERROR (Status
)) {
1922 Status
= PushExpression (Value
);
1923 if (EFI_ERROR (Status
)) {
1929 // Pop the final result from expression stack
1932 Status
= PopExpression (Value
);
1933 if (EFI_ERROR (Status
)) {
1938 // After evaluating an expression, there should be only one value left on the expression stack
1940 if (PopExpression (Value
) != EFI_ACCESS_DENIED
) {
1941 return EFI_INVALID_PARAMETER
;
1944 CopyMem (&Expression
->Result
, Value
, sizeof (EFI_HII_VALUE
));