2 Utility functions for expression evaluation.
4 Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>
5 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
;
27 UINTN mExpressionEvaluationStackOffset
= 0;
29 EFI_HII_VALUE
*mCurrentExpressionStack
= NULL
;
30 EFI_HII_VALUE
*mCurrentExpressionEnd
= NULL
;
31 EFI_HII_VALUE
*mCurrentExpressionPointer
= NULL
;
33 EFI_HII_VALUE
*mMapExpressionListStack
= NULL
;
34 EFI_HII_VALUE
*mMapExpressionListEnd
= NULL
;
35 EFI_HII_VALUE
*mMapExpressionListPointer
= NULL
;
38 // Unicode collation protocol interface
40 EFI_UNICODE_COLLATION_PROTOCOL
*mUnicodeCollation
= NULL
;
41 EFI_USER_MANAGER_PROTOCOL
*mUserManager
= NULL
;
44 Grow size of the stack.
46 This is an internal function.
48 @param Stack On input: old stack; On output: new stack
49 @param StackPtr On input: old stack pointer; On output: new stack
51 @param StackEnd On input: old stack end; On output: new stack end
53 @retval EFI_SUCCESS Grow stack success.
54 @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.
59 IN OUT EFI_HII_VALUE
**Stack
,
60 IN OUT EFI_HII_VALUE
**StackPtr
,
61 IN OUT EFI_HII_VALUE
**StackEnd
65 EFI_HII_VALUE
*NewStack
;
67 Size
= EXPRESSION_STACK_SIZE_INCREMENT
;
68 if (*StackPtr
!= NULL
) {
69 Size
= Size
+ (*StackEnd
- *Stack
);
72 NewStack
= AllocatePool (Size
* sizeof (EFI_HII_VALUE
));
73 if (NewStack
== NULL
) {
74 return EFI_OUT_OF_RESOURCES
;
77 if (*StackPtr
!= NULL
) {
79 // Copy from Old Stack to the New Stack
84 (*StackEnd
- *Stack
) * sizeof (EFI_HII_VALUE
)
94 // Make the Stack pointer point to the old data in the new stack
96 *StackPtr
= NewStack
+ (*StackPtr
- *Stack
);
98 *StackEnd
= NewStack
+ Size
;
105 Push an element onto the Boolean Stack.
107 @param Stack On input: old stack; On output: new stack
108 @param StackPtr On input: old stack pointer; On output: new stack
110 @param StackEnd On input: old stack end; On output: new stack end
111 @param Data Data to push.
113 @retval EFI_SUCCESS Push stack success.
118 IN OUT EFI_HII_VALUE
**Stack
,
119 IN OUT EFI_HII_VALUE
**StackPtr
,
120 IN OUT EFI_HII_VALUE
**StackEnd
,
121 IN EFI_HII_VALUE
*Data
127 // Check for a stack overflow condition
129 if (*StackPtr
>= *StackEnd
) {
133 Status
= GrowStack (Stack
, StackPtr
, StackEnd
);
134 if (EFI_ERROR (Status
)) {
140 // Push the item onto the stack
142 CopyMem (*StackPtr
, Data
, sizeof (EFI_HII_VALUE
));
143 if (Data
->Type
== EFI_IFR_TYPE_BUFFER
) {
144 (*StackPtr
)->Buffer
= AllocateCopyPool(Data
->BufferLen
, Data
->Buffer
);
145 ASSERT ((*StackPtr
)->Buffer
!= NULL
);
148 *StackPtr
= *StackPtr
+ 1;
155 Pop an element from the stack.
157 @param Stack On input: old stack
158 @param StackPtr On input: old stack pointer; On output: new stack pointer
159 @param Data Data to pop.
161 @retval EFI_SUCCESS The value was popped onto the stack.
162 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
167 IN EFI_HII_VALUE
*Stack
,
168 IN OUT EFI_HII_VALUE
**StackPtr
,
169 OUT EFI_HII_VALUE
*Data
173 // Check for a stack underflow condition
175 if (*StackPtr
== Stack
) {
176 return EFI_ACCESS_DENIED
;
180 // Pop the item off the stack
182 *StackPtr
= *StackPtr
- 1;
183 CopyMem (Data
, *StackPtr
, sizeof (EFI_HII_VALUE
));
189 Reset stack pointer to begin of the stack.
193 ResetCurrentExpressionStack (
197 mCurrentExpressionPointer
= mCurrentExpressionStack
;
202 Push current expression onto the Stack
204 @param Pointer Pointer to current expression.
206 @retval EFI_SUCCESS The value was pushed onto the stack.
207 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
211 PushCurrentExpression (
217 Data
.Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
218 Data
.Value
.u64
= (UINT64
) (UINTN
) Pointer
;
221 &mCurrentExpressionStack
,
222 &mCurrentExpressionPointer
,
223 &mCurrentExpressionEnd
,
230 Pop current expression from the Stack
232 @param Pointer Pointer to current expression to be pop.
234 @retval EFI_SUCCESS The value was pushed onto the stack.
235 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
239 PopCurrentExpression (
247 mCurrentExpressionStack
,
248 &mCurrentExpressionPointer
,
252 *Pointer
= (VOID
*) (UINTN
) Data
.Value
.u64
;
258 Reset stack pointer to begin of the stack.
262 ResetMapExpressionListStack (
266 mMapExpressionListPointer
= mMapExpressionListStack
;
271 Push the list of map expression onto the Stack
273 @param Pointer Pointer to the list of map expression to be pushed.
275 @retval EFI_SUCCESS The value was pushed onto the stack.
276 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
280 PushMapExpressionList (
286 Data
.Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
287 Data
.Value
.u64
= (UINT64
) (UINTN
) Pointer
;
290 &mMapExpressionListStack
,
291 &mMapExpressionListPointer
,
292 &mMapExpressionListEnd
,
299 Pop the list of map expression from the Stack
301 @param Pointer Pointer to the list of map expression to be pop.
303 @retval EFI_SUCCESS The value was pushed onto the stack.
304 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
308 PopMapExpressionList (
316 mMapExpressionListStack
,
317 &mMapExpressionListPointer
,
321 *Pointer
= (VOID
*) (UINTN
) Data
.Value
.u64
;
327 Reset stack pointer to begin of the stack.
335 mOpCodeScopeStackPointer
= mOpCodeScopeStack
;
340 Push an Operand onto the Stack
342 @param Operand Operand to push.
344 @retval EFI_SUCCESS The value was pushed onto the stack.
345 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
356 Data
.Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
357 Data
.Value
.u8
= Operand
;
361 &mOpCodeScopeStackPointer
,
362 &mOpCodeScopeStackEnd
,
369 Pop an Operand from the Stack
371 @param Operand Operand to pop.
373 @retval EFI_SUCCESS The value was pushed onto the stack.
374 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
388 &mOpCodeScopeStackPointer
,
392 *Operand
= Data
.Value
.u8
;
399 Push an Expression value onto the Stack
401 @param Value Expression value to push.
403 @retval EFI_SUCCESS The value was pushed onto the stack.
404 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
410 IN EFI_HII_VALUE
*Value
414 &mExpressionEvaluationStack
,
415 &mExpressionEvaluationStackPointer
,
416 &mExpressionEvaluationStackEnd
,
423 Pop an Expression value from the stack.
425 @param Value Expression value to pop.
427 @retval EFI_SUCCESS The value was popped onto the stack.
428 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
433 OUT EFI_HII_VALUE
*Value
437 mExpressionEvaluationStack
+ mExpressionEvaluationStackOffset
,
438 &mExpressionEvaluationStackPointer
,
444 Get current stack offset from stack start.
446 @return Stack offset to stack start.
449 SaveExpressionEvaluationStackOffset (
452 UINTN TempStackOffset
;
453 TempStackOffset
= mExpressionEvaluationStackOffset
;
454 mExpressionEvaluationStackOffset
= mExpressionEvaluationStackPointer
- mExpressionEvaluationStack
;
455 return TempStackOffset
;
459 Restore stack offset based on input stack offset
461 @param StackOffset Offset to stack start.
465 RestoreExpressionEvaluationStackOffset (
469 mExpressionEvaluationStackOffset
= StackOffset
;
473 Get Form given its FormId.
475 @param FormSet The formset which contains this form.
476 @param FormId Id of this form.
478 @retval Pointer The form.
479 @retval NULL Specified Form is not found in the formset.
484 IN FORM_BROWSER_FORMSET
*FormSet
,
489 FORM_BROWSER_FORM
*Form
;
491 Link
= GetFirstNode (&FormSet
->FormListHead
);
492 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
493 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
495 if (Form
->FormId
== FormId
) {
499 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
507 Search a Question in Form scope using its QuestionId.
509 @param Form The form which contains this Question.
510 @param QuestionId Id of this Question.
512 @retval Pointer The Question.
513 @retval NULL Specified Question not found in the form.
516 FORM_BROWSER_STATEMENT
*
518 IN FORM_BROWSER_FORM
*Form
,
523 FORM_BROWSER_STATEMENT
*Question
;
525 if (QuestionId
== 0) {
527 // The value of zero is reserved
532 Link
= GetFirstNode (&Form
->StatementListHead
);
533 while (!IsNull (&Form
->StatementListHead
, Link
)) {
534 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
536 if (Question
->QuestionId
== QuestionId
) {
540 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
548 Search a Question in Formset scope using its QuestionId.
550 @param FormSet The formset which contains this form.
551 @param Form The form which contains this Question.
552 @param QuestionId Id of this Question.
554 @retval Pointer The Question.
555 @retval NULL Specified Question not found in the form.
558 FORM_BROWSER_STATEMENT
*
560 IN FORM_BROWSER_FORMSET
*FormSet
,
561 IN FORM_BROWSER_FORM
*Form
,
566 FORM_BROWSER_STATEMENT
*Question
;
569 // Search in the form scope first
571 Question
= IdToQuestion2 (Form
, QuestionId
);
572 if (Question
!= NULL
) {
577 // Search in the formset scope
579 Link
= GetFirstNode (&FormSet
->FormListHead
);
580 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
581 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
583 Question
= IdToQuestion2 (Form
, QuestionId
);
584 if (Question
!= NULL
) {
586 // EFI variable storage may be updated by Callback() asynchronous,
587 // to keep synchronous, always reload the Question Value.
589 if (Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
590 GetQuestionValue (FormSet
, Form
, Question
, FALSE
);
596 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
604 Get Expression given its RuleId.
606 @param Form The form which contains this Expression.
607 @param RuleId Id of this Expression.
609 @retval Pointer The Expression.
610 @retval NULL Specified Expression not found in the form.
615 IN FORM_BROWSER_FORM
*Form
,
620 FORM_EXPRESSION
*Expression
;
622 Link
= GetFirstNode (&Form
->ExpressionListHead
);
623 while (!IsNull (&Form
->ExpressionListHead
, Link
)) {
624 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
626 if (Expression
->Type
== EFI_HII_EXPRESSION_RULE
&& Expression
->RuleId
== RuleId
) {
630 Link
= GetNextNode (&Form
->ExpressionListHead
, Link
);
638 Locate the Unicode Collation Protocol interface for later use.
640 @retval EFI_SUCCESS Protocol interface initialize success.
641 @retval Other Protocol interface initialize failed.
645 InitializeUnicodeCollationProtocol (
651 if (mUnicodeCollation
!= NULL
) {
656 // BUGBUG: Proper impelmentation is to locate all Unicode Collation Protocol
657 // instances first and then select one which support English language.
658 // Current implementation just pick the first instance.
660 Status
= gBS
->LocateProtocol (
661 &gEfiUnicodeCollation2ProtocolGuid
,
663 (VOID
**) &mUnicodeCollation
669 Convert the input Unicode character to upper.
671 @param String Th Unicode character to be converted.
679 while (*String
!= 0) {
680 if ((*String
>= 'a') && (*String
<= 'z')) {
681 *String
= (UINT16
) ((*String
) & ((UINT16
) ~0x20));
689 Evaluate opcode EFI_IFR_TO_STRING.
691 @param FormSet Formset which contains this opcode.
692 @param Format String format in EFI_IFR_TO_STRING.
693 @param Result Evaluation result for this opcode.
695 @retval EFI_SUCCESS Opcode evaluation success.
696 @retval Other Opcode evaluation failed.
701 IN FORM_BROWSER_FORMSET
*FormSet
,
703 OUT EFI_HII_VALUE
*Result
710 CHAR16 Buffer
[MAXIMUM_VALUE_CHARACTERS
];
714 Status
= PopExpression (&Value
);
715 if (EFI_ERROR (Status
)) {
719 switch (Value
.Type
) {
720 case EFI_IFR_TYPE_NUM_SIZE_8
:
721 case EFI_IFR_TYPE_NUM_SIZE_16
:
722 case EFI_IFR_TYPE_NUM_SIZE_32
:
723 case EFI_IFR_TYPE_NUM_SIZE_64
:
724 BufferSize
= MAXIMUM_VALUE_CHARACTERS
* sizeof (CHAR16
);
726 case EFI_IFR_STRING_UNSIGNED_DEC
:
727 case EFI_IFR_STRING_SIGNED_DEC
:
728 PrintFormat
= L
"%ld";
731 case EFI_IFR_STRING_LOWERCASE_HEX
:
732 PrintFormat
= L
"%lx";
735 case EFI_IFR_STRING_UPPERCASE_HEX
:
736 PrintFormat
= L
"%lX";
740 return EFI_UNSUPPORTED
;
742 UnicodeSPrint (Buffer
, BufferSize
, PrintFormat
, Value
.Value
.u64
);
746 case EFI_IFR_TYPE_STRING
:
747 CopyMem (Result
, &Value
, sizeof (EFI_HII_VALUE
));
750 case EFI_IFR_TYPE_BOOLEAN
:
751 String
= (Value
.Value
.b
) ? L
"True" : L
"False";
754 case EFI_IFR_TYPE_BUFFER
:
756 // + 3 is base on the unicode format, the length may be odd number,
757 // so need 1 byte to align, also need 2 bytes for L'\0'.
759 TmpBuf
= AllocateZeroPool (Value
.BufferLen
+ 3);
760 if (Format
== EFI_IFR_STRING_ASCII
) {
761 CopyMem (TmpBuf
, Value
.Buffer
, Value
.BufferLen
);
764 // Format == EFI_IFR_STRING_UNICODE
765 CopyMem (TmpBuf
, Value
.Buffer
, Value
.BufferLen
* sizeof (CHAR16
));
768 UnicodeSPrint (Buffer
, MAXIMUM_VALUE_CHARACTERS
, PrintFormat
, Value
.Buffer
);
771 FreePool (Value
.Buffer
);
775 return EFI_UNSUPPORTED
;
778 Result
->Type
= EFI_IFR_TYPE_STRING
;
779 Result
->Value
.string
= NewString (String
, FormSet
->HiiHandle
);
785 Evaluate opcode EFI_IFR_TO_UINT.
787 @param FormSet Formset which contains this opcode.
788 @param Result Evaluation result for this opcode.
790 @retval EFI_SUCCESS Opcode evaluation success.
791 @retval Other Opcode evaluation failed.
796 IN FORM_BROWSER_FORMSET
*FormSet
,
797 OUT EFI_HII_VALUE
*Result
805 Status
= PopExpression (&Value
);
806 if (EFI_ERROR (Status
)) {
810 if (Value
.Type
>= EFI_IFR_TYPE_OTHER
&& Value
.Type
!= EFI_IFR_TYPE_BUFFER
) {
811 return EFI_UNSUPPORTED
;
814 Status
= EFI_SUCCESS
;
815 if (Value
.Type
== EFI_IFR_TYPE_STRING
) {
816 String
= GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
817 if (String
== NULL
) {
818 return EFI_NOT_FOUND
;
821 IfrStrToUpper (String
);
822 StringPtr
= StrStr (String
, L
"0X");
823 if (StringPtr
!= NULL
) {
827 Result
->Value
.u64
= StrHexToUint64 (String
);
832 Result
->Value
.u64
= StrDecimalToUint64 (String
);
835 } else if (Value
.Type
== EFI_IFR_TYPE_BUFFER
) {
836 if (Value
.BufferLen
> 8) {
837 FreePool (Value
.Buffer
);
838 return EFI_UNSUPPORTED
;
840 Result
->Value
.u64
= *(UINT64
*) Value
.Buffer
;
841 FreePool (Value
.Buffer
);
843 CopyMem (Result
, &Value
, sizeof (EFI_HII_VALUE
));
846 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
852 Evaluate opcode EFI_IFR_CATENATE.
854 @param FormSet Formset which contains this opcode.
855 @param Result Evaluation result for this opcode.
857 @retval EFI_SUCCESS Opcode evaluation success.
858 @retval Other Opcode evaluation failed.
863 IN FORM_BROWSER_FORMSET
*FormSet
,
864 OUT EFI_HII_VALUE
*Result
868 EFI_HII_VALUE Value
[2];
875 // String[0] - The second string
876 // String[1] - The first string
881 Status
= EFI_SUCCESS
;
882 ZeroMem (Value
, sizeof (Value
));
884 for (Index
= 0; Index
< 2; Index
++) {
885 Status
= PopExpression (&Value
[Index
]);
886 if (EFI_ERROR (Status
)) {
890 if (Value
[Index
].Type
!= EFI_IFR_TYPE_STRING
&& Value
[Index
].Type
!= EFI_IFR_TYPE_BUFFER
) {
891 Status
= EFI_UNSUPPORTED
;
895 if (Value
[Index
].Type
== EFI_IFR_TYPE_STRING
) {
896 String
[Index
] = GetToken (Value
[Index
].Value
.string
, FormSet
->HiiHandle
);
897 if (String
[Index
] == NULL
) {
898 Status
= EFI_NOT_FOUND
;
904 if (Value
[0].Type
== EFI_IFR_TYPE_STRING
) {
905 Size
= StrSize (String
[0]);
906 StringPtr
= AllocatePool (StrSize (String
[1]) + Size
);
907 ASSERT (StringPtr
!= NULL
);
908 StrCpy (StringPtr
, String
[1]);
909 StrCat (StringPtr
, String
[0]);
911 Result
->Type
= EFI_IFR_TYPE_STRING
;
912 Result
->Value
.string
= NewString (StringPtr
, FormSet
->HiiHandle
);
914 Result
->Type
= EFI_IFR_TYPE_BUFFER
;
915 Result
->BufferLen
= (UINT16
) (Value
[0].BufferLen
+ Value
[1].BufferLen
);
917 Result
->Buffer
= AllocateZeroPool (Result
->BufferLen
);
918 ASSERT (Result
->Buffer
!= NULL
);
920 CopyMem (Result
->Buffer
, Value
[0].Buffer
, Value
[0].BufferLen
);
921 CopyMem (&Result
->Buffer
[Value
[0].BufferLen
], Value
[1].Buffer
, Value
[1].BufferLen
);
924 if (Value
[0].Buffer
!= NULL
) {
925 FreePool (Value
[0].Buffer
);
927 if (Value
[1].Buffer
!= NULL
) {
928 FreePool (Value
[1].Buffer
);
930 if (String
[0] != NULL
) {
931 FreePool (String
[0]);
933 if (String
[1] != NULL
) {
934 FreePool (String
[1]);
936 if (StringPtr
!= NULL
) {
937 FreePool (StringPtr
);
945 Evaluate opcode EFI_IFR_MATCH.
947 @param FormSet Formset which contains this opcode.
948 @param Result Evaluation result for this opcode.
950 @retval EFI_SUCCESS Opcode evaluation success.
951 @retval Other Opcode evaluation failed.
956 IN FORM_BROWSER_FORMSET
*FormSet
,
957 OUT EFI_HII_VALUE
*Result
966 // String[0] - The string to search
967 // String[1] - pattern
971 Status
= EFI_SUCCESS
;
972 for (Index
= 0; Index
< 2; Index
++) {
973 Status
= PopExpression (&Value
);
974 if (EFI_ERROR (Status
)) {
978 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
979 Status
= EFI_UNSUPPORTED
;
983 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
984 if (String
[Index
] == NULL
) {
985 Status
= EFI_NOT_FOUND
;
990 Result
->Type
= EFI_IFR_TYPE_BOOLEAN
;
991 Result
->Value
.b
= mUnicodeCollation
->MetaiMatch (mUnicodeCollation
, String
[0], String
[1]);
994 if (String
[0] != NULL
) {
995 FreePool (String
[0]);
997 if (String
[1] != NULL
) {
998 FreePool (String
[1]);
1006 Evaluate opcode EFI_IFR_FIND.
1008 @param FormSet Formset which contains this opcode.
1009 @param Format Case sensitive or insensitive.
1010 @param Result Evaluation result for this opcode.
1012 @retval EFI_SUCCESS Opcode evaluation success.
1013 @retval Other Opcode evaluation failed.
1018 IN FORM_BROWSER_FORMSET
*FormSet
,
1020 OUT EFI_HII_VALUE
*Result
1024 EFI_HII_VALUE Value
;
1030 if (Format
> EFI_IFR_FF_CASE_INSENSITIVE
) {
1031 return EFI_UNSUPPORTED
;
1034 Status
= PopExpression (&Value
);
1035 if (EFI_ERROR (Status
)) {
1038 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1039 return EFI_UNSUPPORTED
;
1041 Base
= (UINTN
) Value
.Value
.u64
;
1044 // String[0] - sub-string
1045 // String[1] - The string to search
1049 for (Index
= 0; Index
< 2; Index
++) {
1050 Status
= PopExpression (&Value
);
1051 if (EFI_ERROR (Status
)) {
1055 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
1056 Status
= EFI_UNSUPPORTED
;
1060 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
1061 if (String
[Index
] == NULL
) {
1062 Status
= EFI_NOT_FOUND
;
1066 if (Format
== EFI_IFR_FF_CASE_INSENSITIVE
) {
1068 // Case insensitive, convert both string to upper case
1070 IfrStrToUpper (String
[Index
]);
1074 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1075 if (Base
>= StrLen (String
[1])) {
1076 Result
->Value
.u64
= 0xFFFFFFFFFFFFFFFFULL
;
1078 StringPtr
= StrStr (String
[1] + Base
, String
[0]);
1079 Result
->Value
.u64
= (StringPtr
== NULL
) ? 0xFFFFFFFFFFFFFFFFULL
: (StringPtr
- String
[1]);
1083 if (String
[0] != NULL
) {
1084 FreePool (String
[0]);
1086 if (String
[1] != NULL
) {
1087 FreePool (String
[1]);
1095 Evaluate opcode EFI_IFR_MID.
1097 @param FormSet Formset which contains this opcode.
1098 @param Result Evaluation result for this opcode.
1100 @retval EFI_SUCCESS Opcode evaluation success.
1101 @retval Other Opcode evaluation failed.
1106 IN FORM_BROWSER_FORMSET
*FormSet
,
1107 OUT EFI_HII_VALUE
*Result
1111 EFI_HII_VALUE Value
;
1119 Status
= PopExpression (&Value
);
1120 if (EFI_ERROR (Status
)) {
1123 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1124 return EFI_UNSUPPORTED
;
1126 Length
= (UINTN
) Value
.Value
.u64
;
1128 Status
= PopExpression (&Value
);
1129 if (EFI_ERROR (Status
)) {
1132 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1133 return EFI_UNSUPPORTED
;
1135 Base
= (UINTN
) Value
.Value
.u64
;
1137 Status
= PopExpression (&Value
);
1138 if (EFI_ERROR (Status
)) {
1141 if (Value
.Type
!= EFI_IFR_TYPE_STRING
&& Value
.Type
!= EFI_IFR_TYPE_BUFFER
) {
1142 return EFI_UNSUPPORTED
;
1144 if (Value
.Type
== EFI_IFR_TYPE_STRING
) {
1145 String
= GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
1146 if (String
== NULL
) {
1147 return EFI_NOT_FOUND
;
1150 if (Length
== 0 || Base
>= StrLen (String
)) {
1151 SubString
= gEmptyString
;
1153 SubString
= String
+ Base
;
1154 if ((Base
+ Length
) < StrLen (String
)) {
1155 SubString
[Length
] = L
'\0';
1159 Result
->Type
= EFI_IFR_TYPE_STRING
;
1160 Result
->Value
.string
= NewString (SubString
, FormSet
->HiiHandle
);
1164 Buffer
= Value
.Buffer
;
1165 BufferLen
= Value
.BufferLen
;
1167 Result
->Type
= EFI_IFR_TYPE_BUFFER
;
1168 if (Length
== 0 || Base
>= BufferLen
) {
1169 Result
->BufferLen
= 0;
1170 Result
->Buffer
= NULL
;
1172 Result
->BufferLen
= (UINT16
)((BufferLen
- Base
) < Length
? (BufferLen
- Base
) : Length
);
1173 Result
->Buffer
= AllocateZeroPool (Result
->BufferLen
);
1174 ASSERT (Result
->Buffer
!= NULL
);
1175 CopyMem (Result
->Buffer
, &Value
.Buffer
[Base
], Result
->BufferLen
);
1178 FreePool (Value
.Buffer
);
1186 Evaluate opcode EFI_IFR_TOKEN.
1188 @param FormSet Formset which contains this opcode.
1189 @param Result Evaluation result for this opcode.
1191 @retval EFI_SUCCESS Opcode evaluation success.
1192 @retval Other Opcode evaluation failed.
1197 IN FORM_BROWSER_FORMSET
*FormSet
,
1198 OUT EFI_HII_VALUE
*Result
1202 EFI_HII_VALUE Value
;
1210 Status
= PopExpression (&Value
);
1211 if (EFI_ERROR (Status
)) {
1214 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1215 return EFI_UNSUPPORTED
;
1217 Count
= (UINTN
) Value
.Value
.u64
;
1220 // String[0] - Delimiter
1221 // String[1] - The string to search
1225 for (Index
= 0; Index
< 2; Index
++) {
1226 Status
= PopExpression (&Value
);
1227 if (EFI_ERROR (Status
)) {
1231 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
1232 Status
= EFI_UNSUPPORTED
;
1236 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
1237 if (String
[Index
] == NULL
) {
1238 Status
= EFI_NOT_FOUND
;
1243 Delimiter
= String
[0];
1244 SubString
= String
[1];
1246 SubString
= StrStr (SubString
, Delimiter
);
1247 if (SubString
!= NULL
) {
1249 // Skip over the delimiter
1251 SubString
= SubString
+ StrLen (Delimiter
);
1258 if (SubString
== NULL
) {
1260 // nth delimited sub-string not found, push an empty string
1262 SubString
= gEmptyString
;
1265 // Put a NULL terminator for nth delimited sub-string
1267 StringPtr
= StrStr (SubString
, Delimiter
);
1268 if (StringPtr
!= NULL
) {
1273 Result
->Type
= EFI_IFR_TYPE_STRING
;
1274 Result
->Value
.string
= NewString (SubString
, FormSet
->HiiHandle
);
1277 if (String
[0] != NULL
) {
1278 FreePool (String
[0]);
1280 if (String
[1] != NULL
) {
1281 FreePool (String
[1]);
1289 Evaluate opcode EFI_IFR_SPAN.
1291 @param FormSet Formset which contains this opcode.
1292 @param Flags FIRST_MATCHING or FIRST_NON_MATCHING.
1293 @param Result Evaluation result for this opcode.
1295 @retval EFI_SUCCESS Opcode evaluation success.
1296 @retval Other Opcode evaluation failed.
1301 IN FORM_BROWSER_FORMSET
*FormSet
,
1303 OUT EFI_HII_VALUE
*Result
1307 EFI_HII_VALUE Value
;
1315 Status
= PopExpression (&Value
);
1316 if (EFI_ERROR (Status
)) {
1319 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1320 return EFI_UNSUPPORTED
;
1322 Base
= (UINTN
) Value
.Value
.u64
;
1325 // String[0] - Charset
1326 // String[1] - The string to search
1330 for (Index
= 0; Index
< 2; Index
++) {
1331 Status
= PopExpression (&Value
);
1332 if (EFI_ERROR (Status
)) {
1336 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
1337 Status
= EFI_UNSUPPORTED
;
1341 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
1342 if (String
[Index
] == NULL
) {
1343 Status
= EFI_NOT_FOUND
;
1348 if (Base
>= StrLen (String
[1])) {
1349 Status
= EFI_UNSUPPORTED
;
1354 StringPtr
= String
[1] + Base
;
1355 Charset
= String
[0];
1356 while (*StringPtr
!= 0 && !Found
) {
1358 while (Charset
[Index
] != 0) {
1359 if (*StringPtr
>= Charset
[Index
] && *StringPtr
<= Charset
[Index
+ 1]) {
1360 if (Flags
== EFI_IFR_FLAGS_FIRST_MATCHING
) {
1365 if (Flags
== EFI_IFR_FLAGS_FIRST_NON_MATCHING
) {
1371 // Skip characters pair representing low-end of a range and high-end of a range
1381 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1382 Result
->Value
.u64
= StringPtr
- String
[1];
1385 if (String
[0] != NULL
) {
1386 FreePool (String
[0]);
1388 if (String
[1] != NULL
) {
1389 FreePool (String
[1]);
1397 Zero extend integer/boolean/date/time to UINT64 for comparing.
1399 @param Value HII Value to be converted.
1404 IN EFI_HII_VALUE
*Value
1410 switch (Value
->Type
) {
1411 case EFI_IFR_TYPE_NUM_SIZE_8
:
1412 Temp
= Value
->Value
.u8
;
1415 case EFI_IFR_TYPE_NUM_SIZE_16
:
1416 Temp
= Value
->Value
.u16
;
1419 case EFI_IFR_TYPE_NUM_SIZE_32
:
1420 Temp
= Value
->Value
.u32
;
1423 case EFI_IFR_TYPE_BOOLEAN
:
1424 Temp
= Value
->Value
.b
;
1427 case EFI_IFR_TYPE_TIME
:
1428 Temp
= Value
->Value
.u32
& 0xffffff;
1431 case EFI_IFR_TYPE_DATE
:
1432 Temp
= Value
->Value
.u32
;
1439 Value
->Value
.u64
= Temp
;
1444 Compare two Hii value.
1446 @param Value1 Expression value to compare on left-hand.
1447 @param Value2 Expression value to compare on right-hand.
1448 @param HiiHandle Only required for string compare.
1450 @retval EFI_INVALID_PARAMETER Could not perform compare on two values.
1451 @retval 0 Two operators equal.
1452 @return Positive value if Value1 is greater than Value2.
1453 @retval Negative value if Value1 is less than Value2.
1458 IN EFI_HII_VALUE
*Value1
,
1459 IN EFI_HII_VALUE
*Value2
,
1460 IN EFI_HII_HANDLE HiiHandle OPTIONAL
1469 if (Value1
->Type
>= EFI_IFR_TYPE_OTHER
|| Value2
->Type
>= EFI_IFR_TYPE_OTHER
) {
1470 if (Value1
->Type
!= EFI_IFR_TYPE_BUFFER
&& Value2
->Type
!= EFI_IFR_TYPE_BUFFER
) {
1471 return EFI_INVALID_PARAMETER
;
1475 if (Value1
->Type
== EFI_IFR_TYPE_STRING
|| Value2
->Type
== EFI_IFR_TYPE_STRING
) {
1476 if (Value1
->Type
!= Value2
->Type
) {
1478 // Both Operator should be type of String
1480 return EFI_INVALID_PARAMETER
;
1483 if (Value1
->Value
.string
== 0 || Value2
->Value
.string
== 0) {
1485 // StringId 0 is reserved
1487 return EFI_INVALID_PARAMETER
;
1490 if (Value1
->Value
.string
== Value2
->Value
.string
) {
1494 Str1
= GetToken (Value1
->Value
.string
, HiiHandle
);
1499 return EFI_INVALID_PARAMETER
;
1502 Str2
= GetToken (Value2
->Value
.string
, HiiHandle
);
1505 return EFI_INVALID_PARAMETER
;
1508 Result
= StrCmp (Str1
, Str2
);
1516 if (Value1
->Type
== EFI_IFR_TYPE_BUFFER
|| Value2
->Type
== EFI_IFR_TYPE_BUFFER
) {
1517 if (Value1
->Type
!= Value2
->Type
) {
1519 // Both Operator should be type of Buffer.
1521 return EFI_INVALID_PARAMETER
;
1523 Len
= Value1
->BufferLen
> Value2
->BufferLen
? Value2
->BufferLen
: Value1
->BufferLen
;
1524 Result
= CompareMem (Value1
->Buffer
, Value2
->Buffer
, Len
);
1525 if ((Result
== 0) && (Value1
->BufferLen
!= Value2
->BufferLen
))
1528 // In this case, means base on samll number buffer, the data is same
1529 // So which value has more data, which value is bigger.
1531 Result
= Value1
->BufferLen
> Value2
->BufferLen
? 1 : -1;
1537 // Take remain types(integer, boolean, date/time) as integer
1539 Temp64
= (INT64
) (Value1
->Value
.u64
- Value2
->Value
.u64
);
1542 } else if (Temp64
< 0) {
1552 Check if current user has the privilege specified by the permissions GUID.
1554 @param[in] Guid A GUID specifying setup access permissions.
1556 @retval TRUE Current user has the privilege.
1557 @retval FALSE Current user does not have the privilege.
1560 CheckUserPrivilege (
1565 EFI_USER_PROFILE_HANDLE UserProfileHandle
;
1566 EFI_USER_INFO_HANDLE UserInfoHandle
;
1567 EFI_USER_INFO
*UserInfo
;
1568 EFI_GUID
*UserPermissionsGuid
;
1570 UINTN AccessControlDataSize
;
1571 EFI_USER_INFO_ACCESS_CONTROL
*AccessControl
;
1574 if (mUserManager
== NULL
) {
1575 Status
= gBS
->LocateProtocol (
1576 &gEfiUserManagerProtocolGuid
,
1578 (VOID
**) &mUserManager
1580 if (EFI_ERROR (Status
)) {
1582 /// If the system does not support user management, then it is assumed that
1583 /// all users have admin privilege and evaluation of each EFI_IFR_SECURITY
1584 /// op-code is always TRUE.
1590 Status
= mUserManager
->Current (mUserManager
, &UserProfileHandle
);
1591 ASSERT_EFI_ERROR (Status
);
1594 /// Enumerate all user information of the current user profile
1595 /// to look for any EFI_USER_INFO_ACCESS_SETUP record.
1598 for (UserInfoHandle
= NULL
;;) {
1599 Status
= mUserManager
->GetNextInfo (mUserManager
, UserProfileHandle
, &UserInfoHandle
);
1600 if (EFI_ERROR (Status
)) {
1605 Status
= mUserManager
->GetInfo (mUserManager
, UserProfileHandle
, UserInfoHandle
, NULL
, &UserInfoSize
);
1606 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1610 UserInfo
= (EFI_USER_INFO
*) AllocatePool (UserInfoSize
);
1611 if (UserInfo
== NULL
) {
1615 Status
= mUserManager
->GetInfo (mUserManager
, UserProfileHandle
, UserInfoHandle
, UserInfo
, &UserInfoSize
);
1616 if (EFI_ERROR (Status
) ||
1617 UserInfo
->InfoType
!= EFI_USER_INFO_ACCESS_POLICY_RECORD
||
1618 UserInfo
->InfoSize
<= sizeof (EFI_USER_INFO
)) {
1619 FreePool (UserInfo
);
1623 RemainSize
= UserInfo
->InfoSize
- sizeof (EFI_USER_INFO
);
1624 AccessControl
= (EFI_USER_INFO_ACCESS_CONTROL
*)(UserInfo
+ 1);
1625 while (RemainSize
>= sizeof (EFI_USER_INFO_ACCESS_CONTROL
)) {
1626 if (RemainSize
< AccessControl
->Size
|| AccessControl
->Size
< sizeof (EFI_USER_INFO_ACCESS_CONTROL
)) {
1629 if (AccessControl
->Type
== EFI_USER_INFO_ACCESS_SETUP
) {
1631 /// Check if current user has the privilege specified by the permissions GUID.
1634 UserPermissionsGuid
= (EFI_GUID
*)(AccessControl
+ 1);
1635 AccessControlDataSize
= AccessControl
->Size
- sizeof (EFI_USER_INFO_ACCESS_CONTROL
);
1636 while (AccessControlDataSize
>= sizeof (EFI_GUID
)) {
1637 if (CompareGuid (Guid
, UserPermissionsGuid
)) {
1638 FreePool (UserInfo
);
1641 UserPermissionsGuid
++;
1642 AccessControlDataSize
-= sizeof (EFI_GUID
);
1645 RemainSize
-= AccessControl
->Size
;
1646 AccessControl
= (EFI_USER_INFO_ACCESS_CONTROL
*)((UINT8
*)AccessControl
+ AccessControl
->Size
);
1649 FreePool (UserInfo
);
1655 Evaluate the result of a HII expression.
1657 If Expression is NULL, then ASSERT.
1659 @param FormSet FormSet associated with this expression.
1660 @param Form Form associated with this expression.
1661 @param Expression Expression to be evaluated.
1663 @retval EFI_SUCCESS The expression evaluated successfuly
1664 @retval EFI_NOT_FOUND The Question which referenced by a QuestionId
1666 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
1668 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
1669 @retval EFI_INVALID_PARAMETER Syntax error with the Expression
1673 EvaluateExpression (
1674 IN FORM_BROWSER_FORMSET
*FormSet
,
1675 IN FORM_BROWSER_FORM
*Form
,
1676 IN OUT FORM_EXPRESSION
*Expression
1681 EXPRESSION_OPCODE
*OpCode
;
1682 FORM_BROWSER_STATEMENT
*Question
;
1683 FORM_BROWSER_STATEMENT
*Question2
;
1685 EFI_HII_VALUE Data1
;
1686 EFI_HII_VALUE Data2
;
1687 EFI_HII_VALUE Data3
;
1688 FORM_EXPRESSION
*RuleExpression
;
1689 EFI_HII_VALUE
*Value
;
1694 LIST_ENTRY
*SubExpressionLink
;
1695 FORM_EXPRESSION
*SubExpression
;
1704 // Save current stack offset.
1706 StackOffset
= SaveExpressionEvaluationStackOffset ();
1708 ASSERT (Expression
!= NULL
);
1709 Expression
->Result
.Type
= EFI_IFR_TYPE_OTHER
;
1711 Link
= GetFirstNode (&Expression
->OpCodeListHead
);
1712 while (!IsNull (&Expression
->OpCodeListHead
, Link
)) {
1713 OpCode
= EXPRESSION_OPCODE_FROM_LINK (Link
);
1715 Link
= GetNextNode (&Expression
->OpCodeListHead
, Link
);
1717 ZeroMem (&Data1
, sizeof (EFI_HII_VALUE
));
1718 ZeroMem (&Data2
, sizeof (EFI_HII_VALUE
));
1719 ZeroMem (&Data3
, sizeof (EFI_HII_VALUE
));
1722 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
1723 Status
= EFI_SUCCESS
;
1725 switch (OpCode
->Operand
) {
1727 // Built-in functions
1729 case EFI_IFR_EQ_ID_VAL_OP
:
1730 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
1731 if (Question
== NULL
) {
1732 Status
= EFI_NOT_FOUND
;
1736 Result
= CompareHiiValue (&Question
->HiiValue
, &OpCode
->Value
, NULL
);
1737 if (Result
== EFI_INVALID_PARAMETER
) {
1738 Status
= EFI_INVALID_PARAMETER
;
1741 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
1744 case EFI_IFR_EQ_ID_ID_OP
:
1745 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
1746 if (Question
== NULL
) {
1747 Status
= EFI_NOT_FOUND
;
1751 Question2
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId2
);
1752 if (Question2
== NULL
) {
1753 Status
= EFI_NOT_FOUND
;
1757 Result
= CompareHiiValue (&Question
->HiiValue
, &Question2
->HiiValue
, FormSet
->HiiHandle
);
1758 if (Result
== EFI_INVALID_PARAMETER
) {
1759 Status
= EFI_INVALID_PARAMETER
;
1762 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
1765 case EFI_IFR_EQ_ID_LIST_OP
:
1766 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
1767 if (Question
== NULL
) {
1768 Status
= EFI_NOT_FOUND
;
1772 Value
->Value
.b
= FALSE
;
1773 for (Index
=0; Index
< OpCode
->ListLength
; Index
++) {
1774 if (Question
->HiiValue
.Value
.u16
== OpCode
->ValueList
[Index
]) {
1775 Value
->Value
.b
= TRUE
;
1781 case EFI_IFR_DUP_OP
:
1782 Status
= PopExpression (Value
);
1783 if (EFI_ERROR (Status
)) {
1787 Status
= PushExpression (Value
);
1790 case EFI_IFR_QUESTION_REF1_OP
:
1791 case EFI_IFR_THIS_OP
:
1792 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
1793 if (Question
== NULL
) {
1794 Status
= EFI_NOT_FOUND
;
1798 Value
= &Question
->HiiValue
;
1801 case EFI_IFR_SECURITY_OP
:
1802 Value
->Value
.b
= CheckUserPrivilege (&OpCode
->Guid
);
1805 case EFI_IFR_GET_OP
:
1807 // Get Value from VarStore buffer, EFI VarStore, Name/Value VarStore.
1809 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1810 Value
->Value
.u8
= 0;
1811 if (OpCode
->VarStorage
!= NULL
) {
1812 switch (OpCode
->VarStorage
->Type
) {
1813 case EFI_HII_VARSTORE_BUFFER
:
1814 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1816 // Get value from Edit Buffer
1818 Value
->Type
= OpCode
->ValueType
;
1819 CopyMem (&Value
->Value
, OpCode
->VarStorage
->EditBuffer
+ OpCode
->VarStoreInfo
.VarOffset
, OpCode
->ValueWidth
);
1821 case EFI_HII_VARSTORE_NAME_VALUE
:
1822 if (OpCode
->ValueType
!= EFI_IFR_TYPE_STRING
) {
1824 // Get value from string except for STRING value.
1826 Status
= GetValueByName (OpCode
->VarStorage
, OpCode
->ValueName
, &StrPtr
);
1827 if (!EFI_ERROR (Status
)) {
1828 ASSERT (StrPtr
!= NULL
);
1829 TempLength
= StrLen (StrPtr
);
1830 if (OpCode
->ValueWidth
>= ((TempLength
+ 1) / 2)) {
1831 Value
->Type
= OpCode
->ValueType
;
1832 TempBuffer
= (UINT8
*) &Value
->Value
;
1833 ZeroMem (TempStr
, sizeof (TempStr
));
1834 for (Index
= 0; Index
< TempLength
; Index
++) {
1835 TempStr
[0] = StrPtr
[TempLength
- Index
- 1];
1836 DigitUint8
= (UINT8
) StrHexToUint64 (TempStr
);
1837 if ((Index
& 1) == 0) {
1838 TempBuffer
[Index
/2] = DigitUint8
;
1840 TempBuffer
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + TempBuffer
[Index
/2]);
1847 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1849 // Get value from variable.
1851 TempLength
= OpCode
->ValueWidth
;
1852 Value
->Type
= OpCode
->ValueType
;
1853 Status
= gRT
->GetVariable (
1855 &OpCode
->VarStorage
->Guid
,
1860 if (EFI_ERROR (Status
)) {
1861 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1862 Value
->Value
.u8
= 0;
1867 // Not recognize storage.
1869 Status
= EFI_UNSUPPORTED
;
1874 // For Time/Date Data
1876 if (OpCode
->ValueType
!= EFI_IFR_TYPE_DATE
&& OpCode
->ValueType
!= EFI_IFR_TYPE_TIME
) {
1878 // Only support Data/Time data when storage doesn't exist.
1880 Status
= EFI_UNSUPPORTED
;
1883 Status
= gRT
->GetTime (&EfiTime
, NULL
);
1884 if (!EFI_ERROR (Status
)) {
1885 if (OpCode
->ValueType
== EFI_IFR_TYPE_DATE
) {
1886 switch (OpCode
->VarStoreInfo
.VarOffset
) {
1888 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_16
;
1889 Value
->Value
.u16
= EfiTime
.Year
;
1892 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
1893 Value
->Value
.u8
= EfiTime
.Month
;
1896 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
1897 Value
->Value
.u8
= EfiTime
.Day
;
1901 // Invalid Date field.
1903 Status
= EFI_INVALID_PARAMETER
;
1907 switch (OpCode
->VarStoreInfo
.VarOffset
) {
1909 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
1910 Value
->Value
.u8
= EfiTime
.Hour
;
1913 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
1914 Value
->Value
.u8
= EfiTime
.Minute
;
1917 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
1918 Value
->Value
.u8
= EfiTime
.Second
;
1922 // Invalid Time field.
1924 Status
= EFI_INVALID_PARAMETER
;
1933 case EFI_IFR_QUESTION_REF3_OP
:
1934 if (OpCode
->DevicePath
== 0) {
1936 // EFI_IFR_QUESTION_REF3
1937 // Pop an expression from the expression stack
1939 Status
= PopExpression (Value
);
1940 if (EFI_ERROR (Status
)) {
1945 // Validate the expression value
1947 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
1948 Status
= EFI_NOT_FOUND
;
1952 Question
= IdToQuestion (FormSet
, Form
, Value
->Value
.u16
);
1953 if (Question
== NULL
) {
1954 Status
= EFI_NOT_FOUND
;
1959 // push the questions' value on to the expression stack
1961 Value
= &Question
->HiiValue
;
1964 // BUGBUG: push 0 for EFI_IFR_QUESTION_REF3_2 and EFI_IFR_QUESTION_REF3_3,
1965 // since it is impractical to evaluate the value of a Question in another
1966 // Hii Package list.
1968 ZeroMem (Value
, sizeof (EFI_HII_VALUE
));
1972 case EFI_IFR_RULE_REF_OP
:
1974 // Find expression for this rule
1976 RuleExpression
= RuleIdToExpression (Form
, OpCode
->RuleId
);
1977 if (RuleExpression
== NULL
) {
1978 Status
= EFI_NOT_FOUND
;
1983 // Evaluate this rule expression
1985 Status
= EvaluateExpression (FormSet
, Form
, RuleExpression
);
1986 if (EFI_ERROR (Status
)) {
1990 Value
= &RuleExpression
->Result
;
1993 case EFI_IFR_STRING_REF1_OP
:
1994 Value
->Type
= EFI_IFR_TYPE_STRING
;
1995 Value
->Value
.string
= OpCode
->Value
.Value
.string
;
2001 case EFI_IFR_TRUE_OP
:
2002 case EFI_IFR_FALSE_OP
:
2003 case EFI_IFR_ONE_OP
:
2004 case EFI_IFR_ONES_OP
:
2005 case EFI_IFR_UINT8_OP
:
2006 case EFI_IFR_UINT16_OP
:
2007 case EFI_IFR_UINT32_OP
:
2008 case EFI_IFR_UINT64_OP
:
2009 case EFI_IFR_UNDEFINED_OP
:
2010 case EFI_IFR_VERSION_OP
:
2011 case EFI_IFR_ZERO_OP
:
2012 Value
= &OpCode
->Value
;
2018 case EFI_IFR_LENGTH_OP
:
2019 Status
= PopExpression (Value
);
2020 if (EFI_ERROR (Status
)) {
2023 if (Value
->Type
!= EFI_IFR_TYPE_STRING
&& Value
->Type
!= EFI_IFR_TYPE_BUFFER
) {
2024 Status
= EFI_INVALID_PARAMETER
;
2028 if (Value
->Type
== EFI_IFR_TYPE_STRING
) {
2029 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->HiiHandle
);
2030 if (StrPtr
== NULL
) {
2031 Status
= EFI_INVALID_PARAMETER
;
2035 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
2036 Value
->Value
.u64
= StrLen (StrPtr
);
2039 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
2040 Value
->Value
.u64
= Value
->BufferLen
;
2041 FreePool (Value
->Buffer
);
2045 case EFI_IFR_NOT_OP
:
2046 Status
= PopExpression (Value
);
2047 if (EFI_ERROR (Status
)) {
2050 if (Value
->Type
!= EFI_IFR_TYPE_BOOLEAN
) {
2051 Status
= EFI_INVALID_PARAMETER
;
2054 Value
->Value
.b
= (BOOLEAN
) (!Value
->Value
.b
);
2057 case EFI_IFR_QUESTION_REF2_OP
:
2059 // Pop an expression from the expression stack
2061 Status
= PopExpression (Value
);
2062 if (EFI_ERROR (Status
)) {
2067 // Validate the expression value
2069 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
2070 Status
= EFI_NOT_FOUND
;
2074 Question
= IdToQuestion (FormSet
, Form
, Value
->Value
.u16
);
2075 if (Question
== NULL
) {
2076 Status
= EFI_NOT_FOUND
;
2080 Value
= &Question
->HiiValue
;
2083 case EFI_IFR_STRING_REF2_OP
:
2085 // Pop an expression from the expression stack
2087 Status
= PopExpression (Value
);
2088 if (EFI_ERROR (Status
)) {
2093 // Validate the expression value
2095 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
2096 Status
= EFI_NOT_FOUND
;
2100 Value
->Type
= EFI_IFR_TYPE_STRING
;
2101 StrPtr
= GetToken (Value
->Value
.u16
, FormSet
->HiiHandle
);
2102 if (StrPtr
== NULL
) {
2104 // If String not exit, push an empty string
2106 Value
->Value
.string
= NewString (gEmptyString
, FormSet
->HiiHandle
);
2108 Index
= (UINT16
) Value
->Value
.u64
;
2109 Value
->Value
.string
= Index
;
2114 case EFI_IFR_TO_BOOLEAN_OP
:
2116 // Pop an expression from the expression stack
2118 Status
= PopExpression (Value
);
2119 if (EFI_ERROR (Status
)) {
2124 // Convert an expression to a Boolean
2126 if (Value
->Type
<= EFI_IFR_TYPE_DATE
) {
2128 // When converting from an unsigned integer, zero will be converted to
2129 // FALSE and any other value will be converted to TRUE.
2131 Value
->Value
.b
= (BOOLEAN
) (Value
->Value
.u64
!= 0);
2133 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
2134 } else if (Value
->Type
== EFI_IFR_TYPE_STRING
) {
2136 // When converting from a string, if case-insensitive compare
2137 // with "true" is True, then push True. If a case-insensitive compare
2138 // with "false" is True, then push False. Otherwise, push Undefined.
2140 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->HiiHandle
);
2141 if (StrPtr
== NULL
) {
2142 Status
= EFI_INVALID_PARAMETER
;
2146 IfrStrToUpper (StrPtr
);
2147 if (StrCmp (StrPtr
, L
"TRUE") == 0){
2148 Value
->Value
.b
= TRUE
;
2149 } else if (StrCmp (StrPtr
, L
"FALSE") == 0) {
2150 Value
->Value
.b
= FALSE
;
2152 Status
= EFI_INVALID_PARAMETER
;
2157 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
2158 } else if (Value
->Type
== EFI_IFR_TYPE_BUFFER
) {
2160 // When converting from a buffer, if the buffer is all zeroes,
2161 // then push False. Otherwise push True.
2163 for (Index
=0; Index
< Value
->BufferLen
; Index
++) {
2164 if (Value
->Buffer
[Index
] != 0) {
2169 if (Index
>= Value
->BufferLen
) {
2170 Value
->Value
.b
= FALSE
;
2172 Value
->Value
.b
= TRUE
;
2174 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
2175 FreePool (Value
->Buffer
);
2179 case EFI_IFR_TO_STRING_OP
:
2180 Status
= IfrToString (FormSet
, OpCode
->Format
, Value
);
2183 case EFI_IFR_TO_UINT_OP
:
2184 Status
= IfrToUint (FormSet
, Value
);
2187 case EFI_IFR_TO_LOWER_OP
:
2188 case EFI_IFR_TO_UPPER_OP
:
2189 Status
= InitializeUnicodeCollationProtocol ();
2190 if (EFI_ERROR (Status
)) {
2194 Status
= PopExpression (Value
);
2195 if (EFI_ERROR (Status
)) {
2199 if (Value
->Type
!= EFI_IFR_TYPE_STRING
) {
2200 Status
= EFI_UNSUPPORTED
;
2204 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->HiiHandle
);
2205 if (StrPtr
== NULL
) {
2206 Status
= EFI_NOT_FOUND
;
2210 if (OpCode
->Operand
== EFI_IFR_TO_LOWER_OP
) {
2211 mUnicodeCollation
->StrLwr (mUnicodeCollation
, StrPtr
);
2213 mUnicodeCollation
->StrUpr (mUnicodeCollation
, StrPtr
);
2215 Value
->Value
.string
= NewString (StrPtr
, FormSet
->HiiHandle
);
2219 case EFI_IFR_BITWISE_NOT_OP
:
2221 // Pop an expression from the expression stack
2223 Status
= PopExpression (Value
);
2224 if (EFI_ERROR (Status
)) {
2227 if (Value
->Type
> EFI_IFR_TYPE_DATE
) {
2228 Status
= EFI_INVALID_PARAMETER
;
2232 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
2233 Value
->Value
.u64
= ~Value
->Value
.u64
;
2236 case EFI_IFR_SET_OP
:
2238 // Pop an expression from the expression stack
2240 Status
= PopExpression (Value
);
2241 if (EFI_ERROR (Status
)) {
2244 Data1
.Type
= EFI_IFR_TYPE_BOOLEAN
;
2245 Data1
.Value
.b
= FALSE
;
2247 // Set value to var storage buffer
2249 if (OpCode
->VarStorage
!= NULL
) {
2250 switch (OpCode
->VarStorage
->Type
) {
2251 case EFI_HII_VARSTORE_BUFFER
:
2252 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
2253 CopyMem (OpCode
->VarStorage
->EditBuffer
+ OpCode
->VarStoreInfo
.VarOffset
, &Value
->Value
, OpCode
->ValueWidth
);
2254 Data1
.Value
.b
= TRUE
;
2256 case EFI_HII_VARSTORE_NAME_VALUE
:
2257 if (OpCode
->ValueType
!= EFI_IFR_TYPE_STRING
) {
2258 NameValue
= AllocateZeroPool ((OpCode
->ValueWidth
* 2 + 1) * sizeof (CHAR16
));
2259 ASSERT (Value
!= NULL
);
2261 // Convert Buffer to Hex String
2263 TempBuffer
= (UINT8
*) &Value
->Value
+ OpCode
->ValueWidth
- 1;
2265 for (Index
= 0; Index
< OpCode
->ValueWidth
; Index
++, TempBuffer
--) {
2266 StrPtr
+= UnicodeValueToString (StrPtr
, PREFIX_ZERO
| RADIX_HEX
, *TempBuffer
, 2);
2268 Status
= SetValueByName (OpCode
->VarStorage
, OpCode
->ValueName
, NameValue
, TRUE
);
2269 FreePool (NameValue
);
2270 if (!EFI_ERROR (Status
)) {
2271 Data1
.Value
.b
= TRUE
;
2275 case EFI_HII_VARSTORE_EFI_VARIABLE
:
2276 Status
= gRT
->SetVariable (
2278 &OpCode
->VarStorage
->Guid
,
2279 OpCode
->VarStorage
->Attributes
,
2283 if (!EFI_ERROR (Status
)) {
2284 Data1
.Value
.b
= TRUE
;
2289 // Not recognize storage.
2291 Status
= EFI_UNSUPPORTED
;
2297 // For Time/Date Data
2299 if (OpCode
->ValueType
!= EFI_IFR_TYPE_DATE
&& OpCode
->ValueType
!= EFI_IFR_TYPE_TIME
) {
2301 // Only support Data/Time data when storage doesn't exist.
2303 Status
= EFI_UNSUPPORTED
;
2306 Status
= gRT
->GetTime (&EfiTime
, NULL
);
2307 if (!EFI_ERROR (Status
)) {
2308 if (OpCode
->ValueType
== EFI_IFR_TYPE_DATE
) {
2309 switch (OpCode
->VarStoreInfo
.VarOffset
) {
2311 EfiTime
.Year
= Value
->Value
.u16
;
2314 EfiTime
.Month
= Value
->Value
.u8
;
2317 EfiTime
.Day
= Value
->Value
.u8
;
2321 // Invalid Date field.
2323 Status
= EFI_INVALID_PARAMETER
;
2327 switch (OpCode
->VarStoreInfo
.VarOffset
) {
2329 EfiTime
.Hour
= Value
->Value
.u8
;
2332 EfiTime
.Minute
= Value
->Value
.u8
;
2335 EfiTime
.Second
= Value
->Value
.u8
;
2339 // Invalid Time field.
2341 Status
= EFI_INVALID_PARAMETER
;
2345 Status
= gRT
->SetTime (&EfiTime
);
2346 if (!EFI_ERROR (Status
)) {
2347 Data1
.Value
.b
= TRUE
;
2357 case EFI_IFR_ADD_OP
:
2358 case EFI_IFR_SUBTRACT_OP
:
2359 case EFI_IFR_MULTIPLY_OP
:
2360 case EFI_IFR_DIVIDE_OP
:
2361 case EFI_IFR_MODULO_OP
:
2362 case EFI_IFR_BITWISE_AND_OP
:
2363 case EFI_IFR_BITWISE_OR_OP
:
2364 case EFI_IFR_SHIFT_LEFT_OP
:
2365 case EFI_IFR_SHIFT_RIGHT_OP
:
2367 // Pop an expression from the expression stack
2369 Status
= PopExpression (&Data2
);
2370 if (EFI_ERROR (Status
)) {
2373 if (Data2
.Type
> EFI_IFR_TYPE_DATE
) {
2374 Status
= EFI_INVALID_PARAMETER
;
2379 // Pop another expression from the expression stack
2381 Status
= PopExpression (&Data1
);
2382 if (EFI_ERROR (Status
)) {
2385 if (Data1
.Type
> EFI_IFR_TYPE_DATE
) {
2386 Status
= EFI_INVALID_PARAMETER
;
2390 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
2392 switch (OpCode
->Operand
) {
2393 case EFI_IFR_ADD_OP
:
2394 Value
->Value
.u64
= Data1
.Value
.u64
+ Data2
.Value
.u64
;
2397 case EFI_IFR_SUBTRACT_OP
:
2398 Value
->Value
.u64
= Data1
.Value
.u64
- Data2
.Value
.u64
;
2401 case EFI_IFR_MULTIPLY_OP
:
2402 Value
->Value
.u64
= MultU64x32 (Data1
.Value
.u64
, (UINT32
) Data2
.Value
.u64
);
2405 case EFI_IFR_DIVIDE_OP
:
2406 Value
->Value
.u64
= DivU64x32 (Data1
.Value
.u64
, (UINT32
) Data2
.Value
.u64
);
2409 case EFI_IFR_MODULO_OP
:
2410 DivU64x32Remainder (Data1
.Value
.u64
, (UINT32
) Data2
.Value
.u64
, &TempValue
);
2411 Value
->Value
.u64
= TempValue
;
2414 case EFI_IFR_BITWISE_AND_OP
:
2415 Value
->Value
.u64
= Data1
.Value
.u64
& Data2
.Value
.u64
;
2418 case EFI_IFR_BITWISE_OR_OP
:
2419 Value
->Value
.u64
= Data1
.Value
.u64
| Data2
.Value
.u64
;
2422 case EFI_IFR_SHIFT_LEFT_OP
:
2423 Value
->Value
.u64
= LShiftU64 (Data1
.Value
.u64
, (UINTN
) Data2
.Value
.u64
);
2426 case EFI_IFR_SHIFT_RIGHT_OP
:
2427 Value
->Value
.u64
= RShiftU64 (Data1
.Value
.u64
, (UINTN
) Data2
.Value
.u64
);
2435 case EFI_IFR_AND_OP
:
2438 // Two Boolean operator
2440 Status
= PopExpression (&Data2
);
2441 if (EFI_ERROR (Status
)) {
2444 if (Data2
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
2445 Status
= EFI_INVALID_PARAMETER
;
2450 // Pop another expression from the expression stack
2452 Status
= PopExpression (&Data1
);
2453 if (EFI_ERROR (Status
)) {
2456 if (Data1
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
2457 Status
= EFI_INVALID_PARAMETER
;
2461 if (OpCode
->Operand
== EFI_IFR_AND_OP
) {
2462 Value
->Value
.b
= (BOOLEAN
) (Data1
.Value
.b
&& Data2
.Value
.b
);
2464 Value
->Value
.b
= (BOOLEAN
) (Data1
.Value
.b
|| Data2
.Value
.b
);
2468 case EFI_IFR_EQUAL_OP
:
2469 case EFI_IFR_NOT_EQUAL_OP
:
2470 case EFI_IFR_GREATER_EQUAL_OP
:
2471 case EFI_IFR_GREATER_THAN_OP
:
2472 case EFI_IFR_LESS_EQUAL_OP
:
2473 case EFI_IFR_LESS_THAN_OP
:
2475 // Compare two integer, string, boolean or date/time
2477 Status
= PopExpression (&Data2
);
2478 if (EFI_ERROR (Status
)) {
2481 if (Data2
.Type
> EFI_IFR_TYPE_BOOLEAN
&&
2482 Data2
.Type
!= EFI_IFR_TYPE_STRING
&&
2483 Data2
.Type
!= EFI_IFR_TYPE_BUFFER
) {
2484 Status
= EFI_INVALID_PARAMETER
;
2489 // Pop another expression from the expression stack
2491 Status
= PopExpression (&Data1
);
2492 if (EFI_ERROR (Status
)) {
2496 Result
= CompareHiiValue (&Data1
, &Data2
, FormSet
->HiiHandle
);
2497 if (Data1
.Type
== EFI_IFR_TYPE_BUFFER
) {
2498 FreePool (Data1
.Buffer
);
2499 FreePool (Data2
.Buffer
);
2502 if (Result
== EFI_INVALID_PARAMETER
) {
2503 Status
= EFI_INVALID_PARAMETER
;
2507 switch (OpCode
->Operand
) {
2508 case EFI_IFR_EQUAL_OP
:
2509 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
2512 case EFI_IFR_NOT_EQUAL_OP
:
2513 Value
->Value
.b
= (BOOLEAN
) ((Result
!= 0) ? TRUE
: FALSE
);
2516 case EFI_IFR_GREATER_EQUAL_OP
:
2517 Value
->Value
.b
= (BOOLEAN
) ((Result
>= 0) ? TRUE
: FALSE
);
2520 case EFI_IFR_GREATER_THAN_OP
:
2521 Value
->Value
.b
= (BOOLEAN
) ((Result
> 0) ? TRUE
: FALSE
);
2524 case EFI_IFR_LESS_EQUAL_OP
:
2525 Value
->Value
.b
= (BOOLEAN
) ((Result
<= 0) ? TRUE
: FALSE
);
2528 case EFI_IFR_LESS_THAN_OP
:
2529 Value
->Value
.b
= (BOOLEAN
) ((Result
< 0) ? TRUE
: FALSE
);
2537 case EFI_IFR_MATCH_OP
:
2538 Status
= InitializeUnicodeCollationProtocol ();
2539 if (EFI_ERROR (Status
)) {
2543 Status
= IfrMatch (FormSet
, Value
);
2546 case EFI_IFR_CATENATE_OP
:
2547 Status
= IfrCatenate (FormSet
, Value
);
2553 case EFI_IFR_CONDITIONAL_OP
:
2555 // Pop third expression from the expression stack
2557 Status
= PopExpression (&Data3
);
2558 if (EFI_ERROR (Status
)) {
2563 // Pop second expression from the expression stack
2565 Status
= PopExpression (&Data2
);
2566 if (EFI_ERROR (Status
)) {
2571 // Pop first expression from the expression stack
2573 Status
= PopExpression (&Data1
);
2574 if (EFI_ERROR (Status
)) {
2577 if (Data1
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
2578 Status
= EFI_INVALID_PARAMETER
;
2582 if (Data1
.Value
.b
) {
2589 case EFI_IFR_FIND_OP
:
2590 Status
= IfrFind (FormSet
, OpCode
->Format
, Value
);
2593 case EFI_IFR_MID_OP
:
2594 Status
= IfrMid (FormSet
, Value
);
2597 case EFI_IFR_TOKEN_OP
:
2598 Status
= IfrToken (FormSet
, Value
);
2601 case EFI_IFR_SPAN_OP
:
2602 Status
= IfrSpan (FormSet
, OpCode
->Flags
, Value
);
2605 case EFI_IFR_MAP_OP
:
2607 // Pop the check value
2609 Status
= PopExpression (&Data1
);
2610 if (EFI_ERROR (Status
)) {
2614 // Check MapExpression list is valid.
2616 if (OpCode
->MapExpressionList
.ForwardLink
== NULL
) {
2617 Status
= EFI_INVALID_PARAMETER
;
2621 // Go through map expression list.
2623 SubExpressionLink
= GetFirstNode(&OpCode
->MapExpressionList
);
2624 while (!IsNull (&OpCode
->MapExpressionList
, SubExpressionLink
)) {
2625 SubExpression
= FORM_EXPRESSION_FROM_LINK (SubExpressionLink
);
2627 // Evaluate the first expression in this pair.
2629 Status
= EvaluateExpression (FormSet
, Form
, SubExpression
);
2630 if (EFI_ERROR (Status
)) {
2634 // Compare the expression value with current value
2636 if (CompareHiiValue (&Data1
, &SubExpression
->Result
, NULL
) == 0) {
2638 // Try get the map value.
2640 SubExpressionLink
= GetNextNode (&OpCode
->MapExpressionList
, SubExpressionLink
);
2641 if (IsNull (&OpCode
->MapExpressionList
, SubExpressionLink
)) {
2642 Status
= EFI_INVALID_PARAMETER
;
2645 SubExpression
= FORM_EXPRESSION_FROM_LINK (SubExpressionLink
);
2646 Status
= EvaluateExpression (FormSet
, Form
, SubExpression
);
2647 if (EFI_ERROR (Status
)) {
2650 Value
= &SubExpression
->Result
;
2654 // Skip the second expression on this pair.
2656 SubExpressionLink
= GetNextNode (&OpCode
->MapExpressionList
, SubExpressionLink
);
2657 if (IsNull (&OpCode
->MapExpressionList
, SubExpressionLink
)) {
2658 Status
= EFI_INVALID_PARAMETER
;
2662 // Goto the first expression on next pair.
2664 SubExpressionLink
= GetNextNode (&OpCode
->MapExpressionList
, SubExpressionLink
);
2668 // No map value is found.
2670 if (IsNull (&OpCode
->MapExpressionList
, SubExpressionLink
)) {
2671 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2672 Value
->Value
.u8
= 0;
2679 if (EFI_ERROR (Status
)) {
2683 Status
= PushExpression (Value
);
2684 if (EFI_ERROR (Status
)) {
2690 // Pop the final result from expression stack
2693 Status
= PopExpression (Value
);
2694 if (EFI_ERROR (Status
)) {
2699 // After evaluating an expression, there should be only one value left on the expression stack
2701 if (PopExpression (Value
) != EFI_ACCESS_DENIED
) {
2702 Status
= EFI_INVALID_PARAMETER
;
2706 RestoreExpressionEvaluationStackOffset (StackOffset
);
2707 if (!EFI_ERROR (Status
)) {
2708 CopyMem (&Expression
->Result
, Value
, sizeof (EFI_HII_VALUE
));