2 Utility functions for expression evaluation.
4 Copyright (c) 2007 - 2018, 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
;
37 FORM_EXPRESSION
**mFormExpressionStack
= NULL
;
38 FORM_EXPRESSION
**mFormExpressionEnd
= NULL
;
39 FORM_EXPRESSION
**mFormExpressionPointer
= NULL
;
41 FORM_EXPRESSION
**mStatementExpressionStack
= NULL
;
42 FORM_EXPRESSION
**mStatementExpressionEnd
= NULL
;
43 FORM_EXPRESSION
**mStatementExpressionPointer
= NULL
;
45 FORM_EXPRESSION
**mOptionExpressionStack
= NULL
;
46 FORM_EXPRESSION
**mOptionExpressionEnd
= NULL
;
47 FORM_EXPRESSION
**mOptionExpressionPointer
= NULL
;
51 // Unicode collation protocol interface
53 EFI_UNICODE_COLLATION_PROTOCOL
*mUnicodeCollation
= NULL
;
54 EFI_USER_MANAGER_PROTOCOL
*mUserManager
= NULL
;
57 Grow size of the stack.
59 This is an internal function.
61 @param Stack On input: old stack; On output: new stack
62 @param StackPtr On input: old stack pointer; On output: new stack
64 @param StackEnd On input: old stack end; On output: new stack end
66 @retval EFI_SUCCESS Grow stack success.
67 @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.
72 IN OUT EFI_HII_VALUE
**Stack
,
73 IN OUT EFI_HII_VALUE
**StackPtr
,
74 IN OUT EFI_HII_VALUE
**StackEnd
78 EFI_HII_VALUE
*NewStack
;
80 Size
= EXPRESSION_STACK_SIZE_INCREMENT
;
81 if (*StackPtr
!= NULL
) {
82 Size
= Size
+ (*StackEnd
- *Stack
);
85 NewStack
= AllocatePool (Size
* sizeof (EFI_HII_VALUE
));
86 if (NewStack
== NULL
) {
87 return EFI_OUT_OF_RESOURCES
;
90 if (*StackPtr
!= NULL
) {
92 // Copy from Old Stack to the New Stack
97 (*StackEnd
- *Stack
) * sizeof (EFI_HII_VALUE
)
101 // Free The Old Stack
107 // Make the Stack pointer point to the old data in the new stack
109 *StackPtr
= NewStack
+ (*StackPtr
- *Stack
);
111 *StackEnd
= NewStack
+ Size
;
118 Push an element onto the Boolean Stack.
120 @param Stack On input: old stack; On output: new stack
121 @param StackPtr On input: old stack pointer; On output: new stack
123 @param StackEnd On input: old stack end; On output: new stack end
124 @param Data Data to push.
126 @retval EFI_SUCCESS Push stack success.
131 IN OUT EFI_HII_VALUE
**Stack
,
132 IN OUT EFI_HII_VALUE
**StackPtr
,
133 IN OUT EFI_HII_VALUE
**StackEnd
,
134 IN EFI_HII_VALUE
*Data
140 // Check for a stack overflow condition
142 if (*StackPtr
>= *StackEnd
) {
146 Status
= GrowStack (Stack
, StackPtr
, StackEnd
);
147 if (EFI_ERROR (Status
)) {
153 // Push the item onto the stack
155 CopyMem (*StackPtr
, Data
, sizeof (EFI_HII_VALUE
));
156 if (Data
->Type
== EFI_IFR_TYPE_BUFFER
) {
157 (*StackPtr
)->Buffer
= AllocateCopyPool(Data
->BufferLen
, Data
->Buffer
);
158 ASSERT ((*StackPtr
)->Buffer
!= NULL
);
161 *StackPtr
= *StackPtr
+ 1;
168 Pop an element from the stack.
170 @param Stack On input: old stack
171 @param StackPtr On input: old stack pointer; On output: new stack pointer
172 @param Data Data to pop.
174 @retval EFI_SUCCESS The value was popped onto the stack.
175 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
180 IN EFI_HII_VALUE
*Stack
,
181 IN OUT EFI_HII_VALUE
**StackPtr
,
182 OUT EFI_HII_VALUE
*Data
186 // Check for a stack underflow condition
188 if (*StackPtr
== Stack
) {
189 return EFI_ACCESS_DENIED
;
193 // Pop the item off the stack
195 *StackPtr
= *StackPtr
- 1;
196 CopyMem (Data
, *StackPtr
, sizeof (EFI_HII_VALUE
));
202 Reset stack pointer to begin of the stack.
206 ResetCurrentExpressionStack (
210 mCurrentExpressionPointer
= mCurrentExpressionStack
;
211 mFormExpressionPointer
= mFormExpressionStack
;
212 mStatementExpressionPointer
= mStatementExpressionStack
;
213 mOptionExpressionPointer
= mOptionExpressionStack
;
218 Push current expression onto the Stack
220 @param Pointer Pointer to current expression.
222 @retval EFI_SUCCESS The value was pushed onto the stack.
223 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
227 PushCurrentExpression (
233 Data
.Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
234 Data
.Value
.u64
= (UINT64
) (UINTN
) Pointer
;
237 &mCurrentExpressionStack
,
238 &mCurrentExpressionPointer
,
239 &mCurrentExpressionEnd
,
246 Pop current expression from the Stack
248 @param Pointer Pointer to current expression to be pop.
250 @retval EFI_SUCCESS The value was pushed onto the stack.
251 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
255 PopCurrentExpression (
263 mCurrentExpressionStack
,
264 &mCurrentExpressionPointer
,
268 *Pointer
= (VOID
*) (UINTN
) Data
.Value
.u64
;
274 Reset stack pointer to begin of the stack.
278 ResetMapExpressionListStack (
282 mMapExpressionListPointer
= mMapExpressionListStack
;
287 Grow size of the stack.
289 This is an internal function.
291 @param Stack On input: old stack; On output: new stack
292 @param StackPtr On input: old stack pointer; On output: new stack
294 @param StackEnd On input: old stack end; On output: new stack end
295 @param MemberSize The stack member size.
297 @retval EFI_SUCCESS Grow stack success.
298 @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.
302 GrowConditionalStack (
303 IN OUT FORM_EXPRESSION
***Stack
,
304 IN OUT FORM_EXPRESSION
***StackPtr
,
305 IN OUT FORM_EXPRESSION
***StackEnd
,
310 FORM_EXPRESSION
**NewStack
;
312 Size
= EXPRESSION_STACK_SIZE_INCREMENT
;
313 if (*StackPtr
!= NULL
) {
314 Size
= Size
+ (*StackEnd
- *Stack
);
317 NewStack
= AllocatePool (Size
* MemberSize
);
318 if (NewStack
== NULL
) {
319 return EFI_OUT_OF_RESOURCES
;
322 if (*StackPtr
!= NULL
) {
324 // Copy from Old Stack to the New Stack
329 (*StackEnd
- *Stack
) * MemberSize
333 // Free The Old Stack
339 // Make the Stack pointer point to the old data in the new stack
341 *StackPtr
= NewStack
+ (*StackPtr
- *Stack
);
343 *StackEnd
= NewStack
+ Size
;
349 Push an element onto the Stack.
351 @param Stack On input: old stack; On output: new stack
352 @param StackPtr On input: old stack pointer; On output: new stack
354 @param StackEnd On input: old stack end; On output: new stack end
355 @param Data Data to push.
357 @retval EFI_SUCCESS Push stack success.
361 PushConditionalStack (
362 IN OUT FORM_EXPRESSION
***Stack
,
363 IN OUT FORM_EXPRESSION
***StackPtr
,
364 IN OUT FORM_EXPRESSION
***StackEnd
,
365 IN FORM_EXPRESSION
**Data
371 // Check for a stack overflow condition
373 if (*StackPtr
>= *StackEnd
) {
377 Status
= GrowConditionalStack (Stack
, StackPtr
, StackEnd
, sizeof (FORM_EXPRESSION
*));
378 if (EFI_ERROR (Status
)) {
384 // Push the item onto the stack
386 CopyMem (*StackPtr
, Data
, sizeof (FORM_EXPRESSION
*));
387 *StackPtr
= *StackPtr
+ 1;
394 Pop an element from the stack.
396 @param Stack On input: old stack
397 @param StackPtr On input: old stack pointer; On output: new stack pointer
398 @param Data Data to pop.
400 @retval EFI_SUCCESS The value was popped onto the stack.
401 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
405 PopConditionalStack (
406 IN FORM_EXPRESSION
**Stack
,
407 IN OUT FORM_EXPRESSION
***StackPtr
,
408 OUT FORM_EXPRESSION
**Data
412 // Check for a stack underflow condition
414 if (*StackPtr
== Stack
) {
415 return EFI_ACCESS_DENIED
;
419 // Pop the item off the stack
421 *StackPtr
= *StackPtr
- 1;
422 CopyMem (Data
, *StackPtr
, sizeof (FORM_EXPRESSION
*));
428 Get the expression list count.
430 @param Level Which type this expression belong to. Form,
433 @retval >=0 The expression count
434 @retval -1 Input parameter error.
438 GetConditionalExpressionCount (
439 IN EXPRESS_LEVEL Level
444 return mFormExpressionPointer
- mFormExpressionStack
;
445 case ExpressStatement
:
446 return mStatementExpressionPointer
- mStatementExpressionStack
;
448 return mOptionExpressionPointer
- mOptionExpressionStack
;
456 Get the expression Buffer pointer.
458 @param Level Which type this expression belong to. Form,
461 @retval The start pointer of the expression buffer or NULL.
465 GetConditionalExpressionList (
466 IN EXPRESS_LEVEL Level
471 return mFormExpressionStack
;
472 case ExpressStatement
:
473 return mStatementExpressionStack
;
475 return mOptionExpressionStack
;
484 Push the expression options onto the Stack.
486 @param Pointer Pointer to the current expression.
487 @param Level Which type this expression belong to. Form,
490 @retval EFI_SUCCESS The value was pushed onto the stack.
491 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
495 PushConditionalExpression (
496 IN FORM_EXPRESSION
*Pointer
,
497 IN EXPRESS_LEVEL Level
502 return PushConditionalStack (
503 &mFormExpressionStack
,
504 &mFormExpressionPointer
,
508 case ExpressStatement
:
509 return PushConditionalStack (
510 &mStatementExpressionStack
,
511 &mStatementExpressionPointer
,
512 &mStatementExpressionEnd
,
516 return PushConditionalStack (
517 &mOptionExpressionStack
,
518 &mOptionExpressionPointer
,
519 &mOptionExpressionEnd
,
524 return EFI_INVALID_PARAMETER
;
529 Pop the expression options from the Stack
531 @param Level Which type this expression belong to. Form,
534 @retval EFI_SUCCESS The value was pushed onto the stack.
535 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
539 PopConditionalExpression (
540 IN EXPRESS_LEVEL Level
543 FORM_EXPRESSION
*Pointer
;
547 return PopConditionalStack (
548 mFormExpressionStack
,
549 &mFormExpressionPointer
,
553 case ExpressStatement
:
554 return PopConditionalStack (
555 mStatementExpressionStack
,
556 &mStatementExpressionPointer
,
561 return PopConditionalStack (
562 mOptionExpressionStack
,
563 &mOptionExpressionPointer
,
569 return EFI_INVALID_PARAMETER
;
575 Push the list of map expression onto the Stack
577 @param Pointer Pointer to the list of map expression to be pushed.
579 @retval EFI_SUCCESS The value was pushed onto the stack.
580 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
584 PushMapExpressionList (
590 Data
.Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
591 Data
.Value
.u64
= (UINT64
) (UINTN
) Pointer
;
594 &mMapExpressionListStack
,
595 &mMapExpressionListPointer
,
596 &mMapExpressionListEnd
,
603 Pop the list of map expression from the Stack
605 @param Pointer Pointer to the list of map expression to be pop.
607 @retval EFI_SUCCESS The value was pushed onto the stack.
608 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
612 PopMapExpressionList (
620 mMapExpressionListStack
,
621 &mMapExpressionListPointer
,
625 *Pointer
= (VOID
*) (UINTN
) Data
.Value
.u64
;
631 Reset stack pointer to begin of the stack.
639 mOpCodeScopeStackPointer
= mOpCodeScopeStack
;
644 Push an Operand onto the Stack
646 @param Operand Operand to push.
648 @retval EFI_SUCCESS The value was pushed onto the stack.
649 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
660 Data
.Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
661 Data
.Value
.u8
= Operand
;
665 &mOpCodeScopeStackPointer
,
666 &mOpCodeScopeStackEnd
,
673 Pop an Operand from the Stack
675 @param Operand Operand to pop.
677 @retval EFI_SUCCESS The value was pushed onto the stack.
678 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
692 &mOpCodeScopeStackPointer
,
696 *Operand
= Data
.Value
.u8
;
703 Push an Expression value onto the Stack
705 @param Value Expression value to push.
707 @retval EFI_SUCCESS The value was pushed onto the stack.
708 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
714 IN EFI_HII_VALUE
*Value
718 &mExpressionEvaluationStack
,
719 &mExpressionEvaluationStackPointer
,
720 &mExpressionEvaluationStackEnd
,
727 Pop an Expression value from the stack.
729 @param Value Expression value to pop.
731 @retval EFI_SUCCESS The value was popped onto the stack.
732 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
737 OUT EFI_HII_VALUE
*Value
741 mExpressionEvaluationStack
+ mExpressionEvaluationStackOffset
,
742 &mExpressionEvaluationStackPointer
,
748 Get current stack offset from stack start.
750 @return Stack offset to stack start.
753 SaveExpressionEvaluationStackOffset (
757 UINTN TempStackOffset
;
758 TempStackOffset
= mExpressionEvaluationStackOffset
;
759 mExpressionEvaluationStackOffset
= mExpressionEvaluationStackPointer
- mExpressionEvaluationStack
;
760 return TempStackOffset
;
764 Restore stack offset based on input stack offset
766 @param StackOffset Offset to stack start.
770 RestoreExpressionEvaluationStackOffset (
774 mExpressionEvaluationStackOffset
= StackOffset
;
778 Get Form given its FormId.
780 @param FormSet The formset which contains this form.
781 @param FormId Id of this form.
783 @retval Pointer The form.
784 @retval NULL Specified Form is not found in the formset.
789 IN FORM_BROWSER_FORMSET
*FormSet
,
794 FORM_BROWSER_FORM
*Form
;
796 Link
= GetFirstNode (&FormSet
->FormListHead
);
797 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
798 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
800 if (Form
->FormId
== FormId
) {
804 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
812 Search a Question in Form scope using its QuestionId.
814 @param Form The form which contains this Question.
815 @param QuestionId Id of this Question.
817 @retval Pointer The Question.
818 @retval NULL Specified Question not found in the form.
821 FORM_BROWSER_STATEMENT
*
823 IN FORM_BROWSER_FORM
*Form
,
828 FORM_BROWSER_STATEMENT
*Question
;
830 if (QuestionId
== 0 || Form
== NULL
) {
832 // The value of zero is reserved
837 Link
= GetFirstNode (&Form
->StatementListHead
);
838 while (!IsNull (&Form
->StatementListHead
, Link
)) {
839 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
841 if (Question
->QuestionId
== QuestionId
) {
845 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
853 Search a Question in Formset scope using its QuestionId.
855 @param FormSet The formset which contains this form.
856 @param Form The form which contains this Question.
857 @param QuestionId Id of this Question.
859 @retval Pointer The Question.
860 @retval NULL Specified Question not found in the form.
863 FORM_BROWSER_STATEMENT
*
865 IN FORM_BROWSER_FORMSET
*FormSet
,
866 IN FORM_BROWSER_FORM
*Form
,
871 FORM_BROWSER_STATEMENT
*Question
;
874 // Search in the form scope first
876 Question
= IdToQuestion2 (Form
, QuestionId
);
877 if (Question
!= NULL
) {
882 // Search in the formset scope
884 Link
= GetFirstNode (&FormSet
->FormListHead
);
885 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
886 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
888 Question
= IdToQuestion2 (Form
, QuestionId
);
889 if (Question
!= NULL
) {
891 // EFI variable storage may be updated by Callback() asynchronous,
892 // to keep synchronous, always reload the Question Value.
894 if (Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
895 GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithHiiDriver
);
901 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
909 Get Expression given its RuleId.
911 @param Form The form which contains this Expression.
912 @param RuleId Id of this Expression.
914 @retval Pointer The Expression.
915 @retval NULL Specified Expression not found in the form.
920 IN FORM_BROWSER_FORM
*Form
,
925 FORM_EXPRESSION
*Expression
;
927 Link
= GetFirstNode (&Form
->ExpressionListHead
);
928 while (!IsNull (&Form
->ExpressionListHead
, Link
)) {
929 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
931 if (Expression
->Type
== EFI_HII_EXPRESSION_RULE
&& Expression
->RuleId
== RuleId
) {
935 Link
= GetNextNode (&Form
->ExpressionListHead
, Link
);
943 Locate the Unicode Collation Protocol interface for later use.
945 @retval EFI_SUCCESS Protocol interface initialize success.
946 @retval Other Protocol interface initialize failed.
950 InitializeUnicodeCollationProtocol (
956 if (mUnicodeCollation
!= NULL
) {
961 // BUGBUG: Proper impelmentation is to locate all Unicode Collation Protocol
962 // instances first and then select one which support English language.
963 // Current implementation just pick the first instance.
965 Status
= gBS
->LocateProtocol (
966 &gEfiUnicodeCollation2ProtocolGuid
,
968 (VOID
**) &mUnicodeCollation
974 Convert the input Unicode character to upper.
976 @param String Th Unicode character to be converted.
984 while (*String
!= 0) {
985 if ((*String
>= 'a') && (*String
<= 'z')) {
986 *String
= (UINT16
) ((*String
) & ((UINT16
) ~0x20));
993 Check whether this value type can be transfer to EFI_IFR_TYPE_BUFFER type.
995 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to
996 EFI_IFR_TYPE_BUFFER when do the value compare.
998 @param Value Expression value to compare on.
1000 @retval TRUE This value type can be transter to EFI_IFR_TYPE_BUFFER type.
1001 @retval FALSE This value type can't be transter to EFI_IFR_TYPE_BUFFER type.
1006 IN EFI_HII_VALUE
*Value
1009 switch (Value
->Type
) {
1010 case EFI_IFR_TYPE_BUFFER
:
1011 case EFI_IFR_TYPE_DATE
:
1012 case EFI_IFR_TYPE_TIME
:
1013 case EFI_IFR_TYPE_REF
:
1022 Check whether this value type can be transfer to EFI_IFR_TYPE_UINT64
1024 @param Value Expression value to compare on.
1026 @retval TRUE This value type can be transter to EFI_IFR_TYPE_BUFFER type.
1027 @retval FALSE This value type can't be transter to EFI_IFR_TYPE_BUFFER type.
1032 IN EFI_HII_VALUE
*Value
1035 switch (Value
->Type
) {
1036 case EFI_IFR_TYPE_NUM_SIZE_8
:
1037 case EFI_IFR_TYPE_NUM_SIZE_16
:
1038 case EFI_IFR_TYPE_NUM_SIZE_32
:
1039 case EFI_IFR_TYPE_NUM_SIZE_64
:
1040 case EFI_IFR_TYPE_BOOLEAN
:
1049 Return the buffer length for this value.
1051 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to
1052 EFI_IFR_TYPE_BUFFER when do the value compare.
1054 @param Value Expression value to compare on.
1056 @retval BufLen Return the buffer length.
1061 IN EFI_HII_VALUE
*Value
1064 switch (Value
->Type
) {
1065 case EFI_IFR_TYPE_BUFFER
:
1066 return Value
->BufferLen
;
1068 case EFI_IFR_TYPE_DATE
:
1069 return (UINT16
) sizeof (EFI_HII_DATE
);
1071 case EFI_IFR_TYPE_TIME
:
1072 return (UINT16
) sizeof (EFI_HII_TIME
);
1074 case EFI_IFR_TYPE_REF
:
1075 return (UINT16
) sizeof (EFI_HII_REF
);
1083 Return the buffer pointer for this value.
1085 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to
1086 EFI_IFR_TYPE_BUFFER when do the value compare.
1088 @param Value Expression value to compare on.
1090 @retval Buf Return the buffer pointer.
1095 IN EFI_HII_VALUE
*Value
1098 switch (Value
->Type
) {
1099 case EFI_IFR_TYPE_BUFFER
:
1100 return Value
->Buffer
;
1102 case EFI_IFR_TYPE_DATE
:
1103 return (UINT8
*) (&Value
->Value
.date
);
1105 case EFI_IFR_TYPE_TIME
:
1106 return (UINT8
*) (&Value
->Value
.time
);
1108 case EFI_IFR_TYPE_REF
:
1109 return (UINT8
*) (&Value
->Value
.ref
);
1117 Evaluate opcode EFI_IFR_TO_STRING.
1119 @param FormSet Formset which contains this opcode.
1120 @param Format String format in EFI_IFR_TO_STRING.
1121 @param Result Evaluation result for this opcode.
1123 @retval EFI_SUCCESS Opcode evaluation success.
1124 @retval Other Opcode evaluation failed.
1129 IN FORM_BROWSER_FORMSET
*FormSet
,
1131 OUT EFI_HII_VALUE
*Result
1135 EFI_HII_VALUE Value
;
1137 CHAR16
*PrintFormat
;
1138 CHAR16 Buffer
[MAXIMUM_VALUE_CHARACTERS
];
1144 Status
= PopExpression (&Value
);
1145 if (EFI_ERROR (Status
)) {
1149 switch (Value
.Type
) {
1150 case EFI_IFR_TYPE_NUM_SIZE_8
:
1151 case EFI_IFR_TYPE_NUM_SIZE_16
:
1152 case EFI_IFR_TYPE_NUM_SIZE_32
:
1153 case EFI_IFR_TYPE_NUM_SIZE_64
:
1154 BufferSize
= MAXIMUM_VALUE_CHARACTERS
* sizeof (CHAR16
);
1156 case EFI_IFR_STRING_UNSIGNED_DEC
:
1157 case EFI_IFR_STRING_SIGNED_DEC
:
1158 PrintFormat
= L
"%ld";
1161 case EFI_IFR_STRING_LOWERCASE_HEX
:
1162 PrintFormat
= L
"%lx";
1165 case EFI_IFR_STRING_UPPERCASE_HEX
:
1166 PrintFormat
= L
"%lX";
1170 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1173 UnicodeSPrint (Buffer
, BufferSize
, PrintFormat
, Value
.Value
.u64
);
1177 case EFI_IFR_TYPE_STRING
:
1178 CopyMem (Result
, &Value
, sizeof (EFI_HII_VALUE
));
1181 case EFI_IFR_TYPE_BOOLEAN
:
1182 String
= (Value
.Value
.b
) ? L
"True" : L
"False";
1185 case EFI_IFR_TYPE_BUFFER
:
1186 case EFI_IFR_TYPE_DATE
:
1187 case EFI_IFR_TYPE_TIME
:
1188 case EFI_IFR_TYPE_REF
:
1190 // + 3 is base on the unicode format, the length may be odd number,
1191 // so need 1 byte to align, also need 2 bytes for L'\0'.
1193 if (Value
.Type
== EFI_IFR_TYPE_BUFFER
) {
1194 SrcLen
= Value
.BufferLen
;
1195 SrcBuf
= Value
.Buffer
;
1197 SrcBuf
= GetBufferForValue(&Value
);
1198 SrcLen
= GetLengthForValue(&Value
);
1201 TmpBuf
= AllocateZeroPool (SrcLen
+ 3);
1202 ASSERT (TmpBuf
!= NULL
);
1203 if (Format
== EFI_IFR_STRING_ASCII
) {
1204 CopyMem (TmpBuf
, SrcBuf
, SrcLen
);
1205 PrintFormat
= L
"%a";
1207 // Format == EFI_IFR_STRING_UNICODE
1208 CopyMem (TmpBuf
, SrcBuf
, SrcLen
* sizeof (CHAR16
));
1209 PrintFormat
= L
"%s";
1211 UnicodeSPrint (Buffer
, sizeof (Buffer
), PrintFormat
, TmpBuf
);
1214 if (Value
.Type
== EFI_IFR_TYPE_BUFFER
) {
1215 FreePool (Value
.Buffer
);
1220 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1224 Result
->Type
= EFI_IFR_TYPE_STRING
;
1225 Result
->Value
.string
= NewString (String
, FormSet
->HiiHandle
);
1231 Evaluate opcode EFI_IFR_TO_UINT.
1233 @param FormSet Formset which contains this opcode.
1234 @param Result Evaluation result for this opcode.
1236 @retval EFI_SUCCESS Opcode evaluation success.
1237 @retval Other Opcode evaluation failed.
1242 IN FORM_BROWSER_FORMSET
*FormSet
,
1243 OUT EFI_HII_VALUE
*Result
1247 EFI_HII_VALUE Value
;
1251 Status
= PopExpression (&Value
);
1252 if (EFI_ERROR (Status
)) {
1256 if (Value
.Type
>= EFI_IFR_TYPE_OTHER
&& !IsTypeInBuffer(&Value
)) {
1257 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1261 Status
= EFI_SUCCESS
;
1262 if (Value
.Type
== EFI_IFR_TYPE_STRING
) {
1263 String
= GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
1264 if (String
== NULL
) {
1265 return EFI_NOT_FOUND
;
1268 IfrStrToUpper (String
);
1269 StringPtr
= StrStr (String
, L
"0X");
1270 if (StringPtr
!= NULL
) {
1274 Result
->Value
.u64
= StrHexToUint64 (String
);
1279 Result
->Value
.u64
= StrDecimalToUint64 (String
);
1282 } else if (IsTypeInBuffer(&Value
)) {
1283 if (GetLengthForValue (&Value
) > 8) {
1284 if (Value
.Type
== EFI_IFR_TYPE_BUFFER
) {
1285 FreePool (Value
.Buffer
);
1287 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1290 Result
->Value
.u64
= *(UINT64
*) GetBufferForValue (&Value
);
1291 if (Value
.Type
== EFI_IFR_TYPE_BUFFER
) {
1292 FreePool (Value
.Buffer
);
1295 CopyMem (Result
, &Value
, sizeof (EFI_HII_VALUE
));
1298 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1304 Evaluate opcode EFI_IFR_CATENATE.
1306 @param FormSet Formset which contains this opcode.
1307 @param Result Evaluation result for this opcode.
1309 @retval EFI_SUCCESS Opcode evaluation success.
1310 @retval Other Opcode evaluation failed.
1315 IN FORM_BROWSER_FORMSET
*FormSet
,
1316 OUT EFI_HII_VALUE
*Result
1320 EFI_HII_VALUE Value
[2];
1331 // String[0] - The second string
1332 // String[1] - The first string
1337 Status
= EFI_SUCCESS
;
1338 ZeroMem (Value
, sizeof (Value
));
1340 Status
= PopExpression (&Value
[0]);
1341 if (EFI_ERROR (Status
)) {
1345 Status
= PopExpression (&Value
[1]);
1346 if (EFI_ERROR (Status
)) {
1350 for (Index
= 0; Index
< 2; Index
++) {
1351 if (Value
[Index
].Type
!= EFI_IFR_TYPE_STRING
&& !IsTypeInBuffer(&Value
[Index
])) {
1352 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1353 Status
= EFI_SUCCESS
;
1357 if (Value
[Index
].Type
== EFI_IFR_TYPE_STRING
) {
1358 String
[Index
] = GetToken (Value
[Index
].Value
.string
, FormSet
->HiiHandle
);
1359 if (String
[Index
] == NULL
) {
1360 Status
= EFI_NOT_FOUND
;
1366 if (Value
[0].Type
== EFI_IFR_TYPE_STRING
) {
1367 Size
= StrSize (String
[0]);
1368 MaxLen
= (StrSize (String
[1]) + Size
) / sizeof (CHAR16
);
1369 StringPtr
= AllocatePool (MaxLen
* sizeof (CHAR16
));
1370 ASSERT (StringPtr
!= NULL
);
1371 StrCpyS (StringPtr
, MaxLen
, String
[1]);
1372 StrCatS (StringPtr
, MaxLen
, String
[0]);
1374 Result
->Type
= EFI_IFR_TYPE_STRING
;
1375 Result
->Value
.string
= NewString (StringPtr
, FormSet
->HiiHandle
);
1377 Result
->Type
= EFI_IFR_TYPE_BUFFER
;
1378 Length0
= GetLengthForValue(&Value
[0]);
1379 Length1
= GetLengthForValue(&Value
[1]);
1380 Result
->BufferLen
= (UINT16
) (Length0
+ Length1
);
1382 Result
->Buffer
= AllocateZeroPool (Result
->BufferLen
);
1383 ASSERT (Result
->Buffer
!= NULL
);
1385 TmpBuf
= GetBufferForValue(&Value
[0]);
1386 ASSERT (TmpBuf
!= NULL
);
1387 CopyMem (Result
->Buffer
, TmpBuf
, Length0
);
1388 TmpBuf
= GetBufferForValue(&Value
[1]);
1389 ASSERT (TmpBuf
!= NULL
);
1390 CopyMem (&Result
->Buffer
[Length0
], TmpBuf
, Length1
);
1393 if (Value
[0].Buffer
!= NULL
) {
1394 FreePool (Value
[0].Buffer
);
1396 if (Value
[1].Buffer
!= NULL
) {
1397 FreePool (Value
[1].Buffer
);
1399 if (String
[0] != NULL
) {
1400 FreePool (String
[0]);
1402 if (String
[1] != NULL
) {
1403 FreePool (String
[1]);
1405 if (StringPtr
!= NULL
) {
1406 FreePool (StringPtr
);
1414 Evaluate opcode EFI_IFR_MATCH.
1416 @param FormSet Formset which contains this opcode.
1417 @param Result Evaluation result for this opcode.
1419 @retval EFI_SUCCESS Opcode evaluation success.
1420 @retval Other Opcode evaluation failed.
1425 IN FORM_BROWSER_FORMSET
*FormSet
,
1426 OUT EFI_HII_VALUE
*Result
1430 EFI_HII_VALUE Value
[2];
1435 // String[0] - The string to search
1436 // String[1] - pattern
1440 Status
= EFI_SUCCESS
;
1441 ZeroMem (Value
, sizeof (Value
));
1443 Status
= PopExpression (&Value
[0]);
1444 if (EFI_ERROR (Status
)) {
1448 Status
= PopExpression (&Value
[1]);
1449 if (EFI_ERROR (Status
)) {
1453 for (Index
= 0; Index
< 2; Index
++) {
1454 if (Value
[Index
].Type
!= EFI_IFR_TYPE_STRING
) {
1455 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1456 Status
= EFI_SUCCESS
;
1460 String
[Index
] = GetToken (Value
[Index
].Value
.string
, FormSet
->HiiHandle
);
1461 if (String
[Index
] == NULL
) {
1462 Status
= EFI_NOT_FOUND
;
1467 Result
->Type
= EFI_IFR_TYPE_BOOLEAN
;
1468 Result
->Value
.b
= mUnicodeCollation
->MetaiMatch (mUnicodeCollation
, String
[0], String
[1]);
1471 if (String
[0] != NULL
) {
1472 FreePool (String
[0]);
1474 if (String
[1] != NULL
) {
1475 FreePool (String
[1]);
1482 Evaluate opcode EFI_IFR_MATCH2.
1484 @param FormSet Formset which contains this opcode.
1485 @param SyntaxType Syntax type for match2.
1486 @param Result Evaluation result for this opcode.
1488 @retval EFI_SUCCESS Opcode evaluation success.
1489 @retval Other Opcode evaluation failed.
1494 IN FORM_BROWSER_FORMSET
*FormSet
,
1495 IN EFI_GUID
*SyntaxType
,
1496 OUT EFI_HII_VALUE
*Result
1500 EFI_HII_VALUE Value
[2];
1504 EFI_HANDLE
*HandleBuffer
;
1506 EFI_REGULAR_EXPRESSION_PROTOCOL
*RegularExpressionProtocol
;
1507 UINTN RegExSyntaxTypeListSize
;
1508 EFI_REGEX_SYNTAX_TYPE
*RegExSyntaxTypeList
;
1509 UINTN CapturesCount
;
1512 // String[0] - The string to search
1513 // String[1] - pattern
1517 HandleBuffer
= NULL
;
1518 RegExSyntaxTypeList
= NULL
;
1519 Status
= EFI_SUCCESS
;
1520 ZeroMem (Value
, sizeof (Value
));
1522 Status
= PopExpression (&Value
[0]);
1523 if (EFI_ERROR (Status
)) {
1527 Status
= PopExpression (&Value
[1]);
1528 if (EFI_ERROR (Status
)) {
1532 for (Index
= 0; Index
< 2; Index
++) {
1533 if (Value
[Index
].Type
!= EFI_IFR_TYPE_STRING
) {
1534 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1535 Status
= EFI_SUCCESS
;
1539 String
[Index
] = GetToken (Value
[Index
].Value
.string
, FormSet
->HiiHandle
);
1540 if (String
[Index
] == NULL
) {
1541 Status
= EFI_NOT_FOUND
;
1547 HandleBuffer
= NULL
;
1548 Status
= gBS
->LocateHandle(
1550 &gEfiRegularExpressionProtocolGuid
,
1554 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1555 HandleBuffer
= AllocateZeroPool(BufferSize
);
1556 if (HandleBuffer
== NULL
) {
1557 Status
= EFI_OUT_OF_RESOURCES
;
1560 Status
= gBS
->LocateHandle(
1562 &gEfiRegularExpressionProtocolGuid
,
1569 if (EFI_ERROR (Status
)) {
1570 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1571 Status
= EFI_SUCCESS
;
1575 ASSERT (HandleBuffer
!= NULL
);
1576 for ( Index
= 0; Index
< BufferSize
/ sizeof(EFI_HANDLE
); Index
++) {
1577 Status
= gBS
->HandleProtocol (
1578 HandleBuffer
[Index
],
1579 &gEfiRegularExpressionProtocolGuid
,
1580 (VOID
**)&RegularExpressionProtocol
1582 if (EFI_ERROR (Status
)) {
1586 RegExSyntaxTypeListSize
= 0;
1587 RegExSyntaxTypeList
= NULL
;
1589 Status
= RegularExpressionProtocol
->GetInfo (
1590 RegularExpressionProtocol
,
1591 &RegExSyntaxTypeListSize
,
1594 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1595 RegExSyntaxTypeList
= AllocateZeroPool(RegExSyntaxTypeListSize
);
1596 if (RegExSyntaxTypeList
== NULL
) {
1597 Status
= EFI_OUT_OF_RESOURCES
;
1600 Status
= RegularExpressionProtocol
->GetInfo (
1601 RegularExpressionProtocol
,
1602 &RegExSyntaxTypeListSize
,
1605 } else if (EFI_ERROR (Status
)) {
1609 for (GuidIndex
= 0; GuidIndex
< RegExSyntaxTypeListSize
/ sizeof(EFI_GUID
); GuidIndex
++) {
1610 if (CompareGuid (&RegExSyntaxTypeList
[GuidIndex
], SyntaxType
)) {
1612 // Find the match type, return the value.
1614 Result
->Type
= EFI_IFR_TYPE_BOOLEAN
;
1615 Status
= RegularExpressionProtocol
->MatchString (
1616 RegularExpressionProtocol
,
1628 if (RegExSyntaxTypeList
!= NULL
) {
1629 FreePool (RegExSyntaxTypeList
);
1634 // Type specified by SyntaxType is not supported
1635 // in any of the EFI_REGULAR_EXPRESSION_PROTOCOL instances.
1637 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1638 Status
= EFI_SUCCESS
;
1641 if (String
[0] != NULL
) {
1642 FreePool (String
[0]);
1644 if (String
[1] != NULL
) {
1645 FreePool (String
[1]);
1647 if (RegExSyntaxTypeList
!= NULL
) {
1648 FreePool (RegExSyntaxTypeList
);
1650 if (HandleBuffer
!= NULL
) {
1651 FreePool (HandleBuffer
);
1657 Evaluate opcode EFI_IFR_FIND.
1659 @param FormSet Formset which contains this opcode.
1660 @param Format Case sensitive or insensitive.
1661 @param Result Evaluation result for this opcode.
1663 @retval EFI_SUCCESS Opcode evaluation success.
1664 @retval Other Opcode evaluation failed.
1669 IN FORM_BROWSER_FORMSET
*FormSet
,
1671 OUT EFI_HII_VALUE
*Result
1675 EFI_HII_VALUE Value
[3];
1681 ZeroMem (Value
, sizeof (Value
));
1683 if (Format
> EFI_IFR_FF_CASE_INSENSITIVE
) {
1684 return EFI_INVALID_PARAMETER
;
1687 Status
= PopExpression (&Value
[0]);
1688 if (EFI_ERROR (Status
)) {
1692 Status
= PopExpression (&Value
[1]);
1693 if (EFI_ERROR (Status
)) {
1697 Status
= PopExpression (&Value
[2]);
1698 if (EFI_ERROR (Status
)) {
1702 if (Value
[0].Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1703 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1706 Base
= (UINTN
) Value
[0].Value
.u64
;
1709 // String[0] - sub-string
1710 // String[1] - The string to search
1714 for (Index
= 0; Index
< 2; Index
++) {
1715 if (Value
[Index
+ 1].Type
!= EFI_IFR_TYPE_STRING
) {
1716 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1717 Status
= EFI_SUCCESS
;
1721 String
[Index
] = GetToken (Value
[Index
+ 1].Value
.string
, FormSet
->HiiHandle
);
1722 if (String
[Index
] == NULL
) {
1723 Status
= EFI_NOT_FOUND
;
1727 if (Format
== EFI_IFR_FF_CASE_INSENSITIVE
) {
1729 // Case insensitive, convert both string to upper case
1731 IfrStrToUpper (String
[Index
]);
1735 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1736 if (Base
>= StrLen (String
[1])) {
1737 Result
->Value
.u64
= 0xFFFFFFFFFFFFFFFFULL
;
1739 StringPtr
= StrStr (String
[1] + Base
, String
[0]);
1740 Result
->Value
.u64
= (StringPtr
== NULL
) ? 0xFFFFFFFFFFFFFFFFULL
: (StringPtr
- String
[1]);
1744 if (String
[0] != NULL
) {
1745 FreePool (String
[0]);
1747 if (String
[1] != NULL
) {
1748 FreePool (String
[1]);
1756 Evaluate opcode EFI_IFR_MID.
1758 @param FormSet Formset which contains this opcode.
1759 @param Result Evaluation result for this opcode.
1761 @retval EFI_SUCCESS Opcode evaluation success.
1762 @retval Other Opcode evaluation failed.
1767 IN FORM_BROWSER_FORMSET
*FormSet
,
1768 OUT EFI_HII_VALUE
*Result
1772 EFI_HII_VALUE Value
[3];
1780 ZeroMem (Value
, sizeof (Value
));
1782 Status
= PopExpression (&Value
[0]);
1783 if (EFI_ERROR (Status
)) {
1787 Status
= PopExpression (&Value
[1]);
1788 if (EFI_ERROR (Status
)) {
1792 Status
= PopExpression (&Value
[2]);
1793 if (EFI_ERROR (Status
)) {
1797 if (Value
[0].Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1798 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1801 Length
= (UINTN
) Value
[0].Value
.u64
;
1803 if (Value
[1].Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1804 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1807 Base
= (UINTN
) Value
[1].Value
.u64
;
1809 if (Value
[2].Type
!= EFI_IFR_TYPE_STRING
&& !IsTypeInBuffer(&Value
[2])) {
1810 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1813 if (Value
[2].Type
== EFI_IFR_TYPE_STRING
) {
1814 String
= GetToken (Value
[2].Value
.string
, FormSet
->HiiHandle
);
1815 if (String
== NULL
) {
1816 return EFI_NOT_FOUND
;
1819 if (Length
== 0 || Base
>= StrLen (String
)) {
1820 SubString
= gEmptyString
;
1822 SubString
= String
+ Base
;
1823 if ((Base
+ Length
) < StrLen (String
)) {
1824 SubString
[Length
] = L
'\0';
1828 Result
->Type
= EFI_IFR_TYPE_STRING
;
1829 Result
->Value
.string
= NewString (SubString
, FormSet
->HiiHandle
);
1833 BufferLen
= GetLengthForValue (&Value
[2]);
1834 Buffer
= GetBufferForValue (&Value
[2]);
1836 Result
->Type
= EFI_IFR_TYPE_BUFFER
;
1837 if (Length
== 0 || Base
>= BufferLen
) {
1838 Result
->BufferLen
= 0;
1839 Result
->Buffer
= NULL
;
1841 Result
->BufferLen
= (UINT16
)((BufferLen
- Base
) < Length
? (BufferLen
- Base
) : Length
);
1842 Result
->Buffer
= AllocateZeroPool (Result
->BufferLen
);
1843 ASSERT (Result
->Buffer
!= NULL
);
1844 CopyMem (Result
->Buffer
, &Buffer
[Base
], Result
->BufferLen
);
1847 if (Value
[2].Type
== EFI_IFR_TYPE_BUFFER
) {
1848 FreePool (Value
[2].Buffer
);
1857 Evaluate opcode EFI_IFR_TOKEN.
1859 @param FormSet Formset which contains this opcode.
1860 @param Result Evaluation result for this opcode.
1862 @retval EFI_SUCCESS Opcode evaluation success.
1863 @retval Other Opcode evaluation failed.
1868 IN FORM_BROWSER_FORMSET
*FormSet
,
1869 OUT EFI_HII_VALUE
*Result
1873 EFI_HII_VALUE Value
[3];
1881 ZeroMem (Value
, sizeof (Value
));
1883 Status
= PopExpression (&Value
[0]);
1884 if (EFI_ERROR (Status
)) {
1888 Status
= PopExpression (&Value
[1]);
1889 if (EFI_ERROR (Status
)) {
1893 Status
= PopExpression (&Value
[2]);
1894 if (EFI_ERROR (Status
)) {
1898 if (Value
[0].Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1899 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1902 Count
= (UINTN
) Value
[0].Value
.u64
;
1905 // String[0] - Delimiter
1906 // String[1] - The string to search
1910 for (Index
= 0; Index
< 2; Index
++) {
1911 if (Value
[Index
+ 1].Type
!= EFI_IFR_TYPE_STRING
) {
1912 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1913 Status
= EFI_SUCCESS
;
1917 String
[Index
] = GetToken (Value
[Index
+ 1].Value
.string
, FormSet
->HiiHandle
);
1918 if (String
[Index
] == NULL
) {
1919 Status
= EFI_NOT_FOUND
;
1924 Delimiter
= String
[0];
1925 SubString
= String
[1];
1927 SubString
= StrStr (SubString
, Delimiter
);
1928 if (SubString
!= NULL
) {
1930 // Skip over the delimiter
1932 SubString
= SubString
+ StrLen (Delimiter
);
1939 if (SubString
== NULL
) {
1941 // nth delimited sub-string not found, push an empty string
1943 SubString
= gEmptyString
;
1946 // Put a NULL terminator for nth delimited sub-string
1948 StringPtr
= StrStr (SubString
, Delimiter
);
1949 if (StringPtr
!= NULL
) {
1954 Result
->Type
= EFI_IFR_TYPE_STRING
;
1955 Result
->Value
.string
= NewString (SubString
, FormSet
->HiiHandle
);
1958 if (String
[0] != NULL
) {
1959 FreePool (String
[0]);
1961 if (String
[1] != NULL
) {
1962 FreePool (String
[1]);
1970 Evaluate opcode EFI_IFR_SPAN.
1972 @param FormSet Formset which contains this opcode.
1973 @param Flags FIRST_MATCHING or FIRST_NON_MATCHING.
1974 @param Result Evaluation result for this opcode.
1976 @retval EFI_SUCCESS Opcode evaluation success.
1977 @retval Other Opcode evaluation failed.
1982 IN FORM_BROWSER_FORMSET
*FormSet
,
1984 OUT EFI_HII_VALUE
*Result
1988 EFI_HII_VALUE Value
[3];
1996 ZeroMem (Value
, sizeof (Value
));
1998 Status
= PopExpression (&Value
[0]);
1999 if (EFI_ERROR (Status
)) {
2003 Status
= PopExpression (&Value
[1]);
2004 if (EFI_ERROR (Status
)) {
2008 Status
= PopExpression (&Value
[2]);
2009 if (EFI_ERROR (Status
)) {
2013 if (Value
[0].Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
2014 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2017 Base
= (UINTN
) Value
[0].Value
.u64
;
2020 // String[0] - Charset
2021 // String[1] - The string to search
2025 for (Index
= 0; Index
< 2; Index
++) {
2026 if (Value
[Index
+ 1].Type
!= EFI_IFR_TYPE_STRING
) {
2027 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2028 Status
= EFI_SUCCESS
;
2032 String
[Index
] = GetToken (Value
[Index
+ 1].Value
.string
, FormSet
->HiiHandle
);
2033 if (String
[Index
] == NULL
) {
2034 Status
= EFI_NOT_FOUND
;
2039 if (Base
>= StrLen (String
[1])) {
2040 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2041 Status
= EFI_SUCCESS
;
2046 StringPtr
= String
[1] + Base
;
2047 Charset
= String
[0];
2048 while (*StringPtr
!= 0 && !Found
) {
2050 while (Charset
[Index
] != 0) {
2051 if (*StringPtr
>= Charset
[Index
] && *StringPtr
<= Charset
[Index
+ 1]) {
2052 if (Flags
== EFI_IFR_FLAGS_FIRST_MATCHING
) {
2057 if (Flags
== EFI_IFR_FLAGS_FIRST_NON_MATCHING
) {
2063 // Skip characters pair representing low-end of a range and high-end of a range
2073 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
2074 Result
->Value
.u64
= StringPtr
- String
[1];
2077 if (String
[0] != NULL
) {
2078 FreePool (String
[0]);
2080 if (String
[1] != NULL
) {
2081 FreePool (String
[1]);
2089 Zero extend integer/boolean/date/time to UINT64 for comparing.
2091 @param Value HII Value to be converted.
2096 IN EFI_HII_VALUE
*Value
2102 switch (Value
->Type
) {
2103 case EFI_IFR_TYPE_NUM_SIZE_8
:
2104 Temp
= Value
->Value
.u8
;
2107 case EFI_IFR_TYPE_NUM_SIZE_16
:
2108 Temp
= Value
->Value
.u16
;
2111 case EFI_IFR_TYPE_NUM_SIZE_32
:
2112 Temp
= Value
->Value
.u32
;
2115 case EFI_IFR_TYPE_BOOLEAN
:
2116 Temp
= Value
->Value
.b
;
2119 case EFI_IFR_TYPE_TIME
:
2120 Temp
= Value
->Value
.u32
& 0xffffff;
2123 case EFI_IFR_TYPE_DATE
:
2124 Temp
= Value
->Value
.u32
;
2131 Value
->Value
.u64
= Temp
;
2135 Get UINT64 type value.
2137 @param Value Input Hii value.
2139 @retval UINT64 Return the UINT64 type value.
2144 IN EFI_HII_VALUE
*Value
2151 switch (Value
->Type
) {
2152 case EFI_IFR_TYPE_NUM_SIZE_8
:
2153 RetVal
= Value
->Value
.u8
;
2156 case EFI_IFR_TYPE_NUM_SIZE_16
:
2157 RetVal
= Value
->Value
.u16
;
2160 case EFI_IFR_TYPE_NUM_SIZE_32
:
2161 RetVal
= Value
->Value
.u32
;
2164 case EFI_IFR_TYPE_BOOLEAN
:
2165 RetVal
= Value
->Value
.b
;
2168 case EFI_IFR_TYPE_DATE
:
2169 RetVal
= *(UINT64
*) &Value
->Value
.date
;
2172 case EFI_IFR_TYPE_TIME
:
2173 RetVal
= (*(UINT64
*) &Value
->Value
.time
) & 0xffffff;
2177 RetVal
= Value
->Value
.u64
;
2185 Compare two Hii value.
2187 @param Value1 Expression value to compare on left-hand.
2188 @param Value2 Expression value to compare on right-hand.
2189 @param Result Return value after compare.
2190 retval 0 Two operators equal.
2191 return Positive value if Value1 is greater than Value2.
2192 retval Negative value if Value1 is less than Value2.
2193 @param HiiHandle Only required for string compare.
2195 @retval other Could not perform compare on two values.
2196 @retval EFI_SUCCESS Compare the value success.
2201 IN EFI_HII_VALUE
*Value1
,
2202 IN EFI_HII_VALUE
*Value2
,
2204 IN EFI_HII_HANDLE HiiHandle OPTIONAL
2216 if (Value1
->Type
== EFI_IFR_TYPE_STRING
&& Value2
->Type
== EFI_IFR_TYPE_STRING
) {
2217 if (Value1
->Value
.string
== 0 || Value2
->Value
.string
== 0) {
2219 // StringId 0 is reserved
2221 return EFI_INVALID_PARAMETER
;
2224 if (Value1
->Value
.string
== Value2
->Value
.string
) {
2229 Str1
= GetToken (Value1
->Value
.string
, HiiHandle
);
2234 return EFI_NOT_FOUND
;
2237 Str2
= GetToken (Value2
->Value
.string
, HiiHandle
);
2240 return EFI_NOT_FOUND
;
2243 *Result
= StrCmp (Str1
, Str2
);
2252 // Take types(date, time, ref, buffer) as buffer
2254 if (IsTypeInBuffer(Value1
) && IsTypeInBuffer(Value2
)) {
2255 Buf1
= GetBufferForValue(Value1
);
2256 Buf1Len
= GetLengthForValue(Value1
);
2257 Buf2
= GetBufferForValue(Value2
);
2258 Buf2Len
= GetLengthForValue(Value2
);
2260 Len
= Buf1Len
> Buf2Len
? Buf2Len
: Buf1Len
;
2261 *Result
= CompareMem (Buf1
, Buf2
, Len
);
2262 if ((*Result
== 0) && (Buf1Len
!= Buf2Len
)) {
2264 // In this case, means base on samll number buffer, the data is same
2265 // So which value has more data, which value is bigger.
2267 *Result
= Buf1Len
> Buf2Len
? 1 : -1;
2273 // Take types(integer, boolean) as integer
2275 if (IsTypeInUINT64(Value1
) && IsTypeInUINT64(Value2
)) {
2276 Temp64
= HiiValueToUINT64(Value1
) - HiiValueToUINT64(Value2
);
2279 } else if (Temp64
< 0) {
2288 return EFI_UNSUPPORTED
;
2292 Check if current user has the privilege specified by the permissions GUID.
2294 @param[in] Guid A GUID specifying setup access permissions.
2296 @retval TRUE Current user has the privilege.
2297 @retval FALSE Current user does not have the privilege.
2300 CheckUserPrivilege (
2305 EFI_USER_PROFILE_HANDLE UserProfileHandle
;
2306 EFI_USER_INFO_HANDLE UserInfoHandle
;
2307 EFI_USER_INFO
*UserInfo
;
2308 EFI_GUID
*UserPermissionsGuid
;
2310 UINTN AccessControlDataSize
;
2311 EFI_USER_INFO_ACCESS_CONTROL
*AccessControl
;
2314 if (mUserManager
== NULL
) {
2315 Status
= gBS
->LocateProtocol (
2316 &gEfiUserManagerProtocolGuid
,
2318 (VOID
**) &mUserManager
2320 if (EFI_ERROR (Status
)) {
2322 /// If the system does not support user management, then it is assumed that
2323 /// all users have admin privilege and evaluation of each EFI_IFR_SECURITY
2324 /// op-code is always TRUE.
2330 Status
= mUserManager
->Current (mUserManager
, &UserProfileHandle
);
2331 ASSERT_EFI_ERROR (Status
);
2334 /// Enumerate all user information of the current user profile
2335 /// to look for any EFI_USER_INFO_ACCESS_SETUP record.
2338 for (UserInfoHandle
= NULL
;;) {
2339 Status
= mUserManager
->GetNextInfo (mUserManager
, UserProfileHandle
, &UserInfoHandle
);
2340 if (EFI_ERROR (Status
)) {
2345 Status
= mUserManager
->GetInfo (mUserManager
, UserProfileHandle
, UserInfoHandle
, NULL
, &UserInfoSize
);
2346 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
2350 UserInfo
= (EFI_USER_INFO
*) AllocatePool (UserInfoSize
);
2351 if (UserInfo
== NULL
) {
2355 Status
= mUserManager
->GetInfo (mUserManager
, UserProfileHandle
, UserInfoHandle
, UserInfo
, &UserInfoSize
);
2356 if (EFI_ERROR (Status
) ||
2357 UserInfo
->InfoType
!= EFI_USER_INFO_ACCESS_POLICY_RECORD
||
2358 UserInfo
->InfoSize
<= sizeof (EFI_USER_INFO
)) {
2359 FreePool (UserInfo
);
2363 RemainSize
= UserInfo
->InfoSize
- sizeof (EFI_USER_INFO
);
2364 AccessControl
= (EFI_USER_INFO_ACCESS_CONTROL
*)(UserInfo
+ 1);
2365 while (RemainSize
>= sizeof (EFI_USER_INFO_ACCESS_CONTROL
)) {
2366 if (RemainSize
< AccessControl
->Size
|| AccessControl
->Size
< sizeof (EFI_USER_INFO_ACCESS_CONTROL
)) {
2369 if (AccessControl
->Type
== EFI_USER_INFO_ACCESS_SETUP
) {
2371 /// Check if current user has the privilege specified by the permissions GUID.
2374 UserPermissionsGuid
= (EFI_GUID
*)(AccessControl
+ 1);
2375 AccessControlDataSize
= AccessControl
->Size
- sizeof (EFI_USER_INFO_ACCESS_CONTROL
);
2376 while (AccessControlDataSize
>= sizeof (EFI_GUID
)) {
2377 if (CompareGuid (Guid
, UserPermissionsGuid
)) {
2378 FreePool (UserInfo
);
2381 UserPermissionsGuid
++;
2382 AccessControlDataSize
-= sizeof (EFI_GUID
);
2385 RemainSize
-= AccessControl
->Size
;
2386 AccessControl
= (EFI_USER_INFO_ACCESS_CONTROL
*)((UINT8
*)AccessControl
+ AccessControl
->Size
);
2389 FreePool (UserInfo
);
2395 Get question value from the predefined formset.
2397 @param DevicePath The driver's device path which produece the formset data.
2398 @param InputHiiHandle The hii handle associate with the formset data.
2399 @param FormSetGuid The formset guid which include the question.
2400 @param QuestionId The question id which need to get value from.
2401 @param Value The return data about question's value.
2403 @retval TRUE Get the question value success.
2404 @retval FALSE Get the question value failed.
2407 GetQuestionValueFromForm (
2408 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
2409 IN EFI_HII_HANDLE InputHiiHandle
,
2410 IN EFI_GUID
*FormSetGuid
,
2411 IN EFI_QUESTION_ID QuestionId
,
2412 OUT EFI_HII_VALUE
*Value
2416 EFI_HII_HANDLE HiiHandle
;
2417 FORM_BROWSER_STATEMENT
*Question
;
2418 FORM_BROWSER_FORMSET
*FormSet
;
2419 FORM_BROWSER_FORM
*Form
;
2424 // The input parameter DevicePath or InputHiiHandle must have one valid input.
2426 ASSERT ((DevicePath
!= NULL
&& InputHiiHandle
== NULL
) ||
2427 (DevicePath
== NULL
&& InputHiiHandle
!= NULL
) );
2437 if (DevicePath
!= NULL
) {
2438 HiiHandle
= DevicePathToHiiHandle (DevicePath
, FormSetGuid
);
2439 if (HiiHandle
== NULL
) {
2443 HiiHandle
= InputHiiHandle
;
2445 ASSERT (HiiHandle
!= NULL
);
2448 // Get the formset data include this question.
2450 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
2451 ASSERT (FormSet
!= NULL
);
2452 Status
= InitializeFormSet(HiiHandle
, FormSetGuid
, FormSet
);
2453 if (EFI_ERROR (Status
)) {
2459 // Base on the Question Id to get the question info.
2461 Question
= IdToQuestion(FormSet
, NULL
, QuestionId
);
2462 if (Question
== NULL
) {
2468 // Search form in the formset scope
2470 Link
= GetFirstNode (&FormSet
->FormListHead
);
2471 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2472 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2474 Question
= IdToQuestion2 (Form
, QuestionId
);
2475 if (Question
!= NULL
) {
2479 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2482 ASSERT (Form
!= NULL
);
2485 // Get the question value.
2487 Status
= GetQuestionValue(FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
2488 if (EFI_ERROR (Status
)) {
2493 CopyMem (Value
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
2497 // Clean the formset structure and restore the global parameter.
2499 if (FormSet
!= NULL
) {
2500 DestroyFormSet (FormSet
);
2507 Evaluate the result of a HII expression.
2509 If Expression is NULL, then ASSERT.
2511 @param FormSet FormSet associated with this expression.
2512 @param Form Form associated with this expression.
2513 @param Expression Expression to be evaluated.
2515 @retval EFI_SUCCESS The expression evaluated successfuly
2516 @retval EFI_NOT_FOUND The Question which referenced by a QuestionId
2518 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
2520 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
2521 @retval EFI_INVALID_PARAMETER Syntax error with the Expression
2525 EvaluateExpression (
2526 IN FORM_BROWSER_FORMSET
*FormSet
,
2527 IN FORM_BROWSER_FORM
*Form
,
2528 IN OUT FORM_EXPRESSION
*Expression
2533 EXPRESSION_OPCODE
*OpCode
;
2534 FORM_BROWSER_STATEMENT
*Question
;
2535 FORM_BROWSER_STATEMENT
*Question2
;
2537 EFI_HII_VALUE Data1
;
2538 EFI_HII_VALUE Data2
;
2539 EFI_HII_VALUE Data3
;
2540 FORM_EXPRESSION
*RuleExpression
;
2541 EFI_HII_VALUE
*Value
;
2546 LIST_ENTRY
*SubExpressionLink
;
2547 FORM_EXPRESSION
*SubExpression
;
2554 EFI_HII_VALUE QuestionVal
;
2555 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2560 // Save current stack offset.
2562 StackOffset
= SaveExpressionEvaluationStackOffset ();
2564 ASSERT (Expression
!= NULL
);
2565 Expression
->Result
.Type
= EFI_IFR_TYPE_OTHER
;
2567 Link
= GetFirstNode (&Expression
->OpCodeListHead
);
2568 while (!IsNull (&Expression
->OpCodeListHead
, Link
)) {
2569 OpCode
= EXPRESSION_OPCODE_FROM_LINK (Link
);
2571 Link
= GetNextNode (&Expression
->OpCodeListHead
, Link
);
2573 ZeroMem (&Data1
, sizeof (EFI_HII_VALUE
));
2574 ZeroMem (&Data2
, sizeof (EFI_HII_VALUE
));
2575 ZeroMem (&Data3
, sizeof (EFI_HII_VALUE
));
2578 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
2579 Status
= EFI_SUCCESS
;
2581 switch (OpCode
->Operand
) {
2583 // Built-in functions
2585 case EFI_IFR_EQ_ID_VAL_OP
:
2586 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
2587 if (Question
== NULL
) {
2588 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2592 Status
= CompareHiiValue (&Question
->HiiValue
, &OpCode
->Value
, &Result
, NULL
);
2593 if (Status
== EFI_UNSUPPORTED
) {
2594 Status
= EFI_SUCCESS
;
2595 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2599 if (EFI_ERROR (Status
)) {
2602 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
2605 case EFI_IFR_EQ_ID_ID_OP
:
2606 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
2607 if (Question
== NULL
) {
2608 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2612 Question2
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId2
);
2613 if (Question2
== NULL
) {
2614 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2618 Status
= CompareHiiValue (&Question
->HiiValue
, &Question2
->HiiValue
, &Result
, FormSet
->HiiHandle
);
2619 if (Status
== EFI_UNSUPPORTED
) {
2620 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2621 Status
= EFI_SUCCESS
;
2624 if (EFI_ERROR (Status
)) {
2627 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
2630 case EFI_IFR_EQ_ID_VAL_LIST_OP
:
2631 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
2632 if (Question
== NULL
) {
2633 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2637 Value
->Value
.b
= FALSE
;
2638 for (Index
=0; Index
< OpCode
->ListLength
; Index
++) {
2639 if (Question
->HiiValue
.Value
.u16
== OpCode
->ValueList
[Index
]) {
2640 Value
->Value
.b
= TRUE
;
2646 case EFI_IFR_DUP_OP
:
2647 Status
= PopExpression (Value
);
2648 if (EFI_ERROR (Status
)) {
2652 Status
= PushExpression (Value
);
2655 case EFI_IFR_QUESTION_REF1_OP
:
2656 case EFI_IFR_THIS_OP
:
2657 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
2658 if (Question
== NULL
) {
2659 Status
= EFI_NOT_FOUND
;
2663 Value
= &Question
->HiiValue
;
2666 case EFI_IFR_SECURITY_OP
:
2667 Value
->Value
.b
= CheckUserPrivilege (&OpCode
->Guid
);
2670 case EFI_IFR_GET_OP
:
2672 // Get Value from VarStore buffer, EFI VarStore, Name/Value VarStore.
2674 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2675 Value
->Value
.u8
= 0;
2676 if (OpCode
->VarStorage
!= NULL
) {
2677 switch (OpCode
->VarStorage
->Type
) {
2678 case EFI_HII_VARSTORE_BUFFER
:
2679 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
2681 // Get value from Edit Buffer
2683 Value
->Type
= OpCode
->ValueType
;
2684 CopyMem (&Value
->Value
, OpCode
->VarStorage
->EditBuffer
+ OpCode
->VarStoreInfo
.VarOffset
, OpCode
->ValueWidth
);
2686 case EFI_HII_VARSTORE_NAME_VALUE
:
2687 if (OpCode
->ValueType
!= EFI_IFR_TYPE_STRING
) {
2689 // Get value from string except for STRING value.
2691 Status
= GetValueByName (OpCode
->VarStorage
, OpCode
->ValueName
, &StrPtr
, GetSetValueWithEditBuffer
);
2692 if (!EFI_ERROR (Status
)) {
2693 ASSERT (StrPtr
!= NULL
);
2694 TempLength
= StrLen (StrPtr
);
2695 if (OpCode
->ValueWidth
>= ((TempLength
+ 1) / 2)) {
2696 Value
->Type
= OpCode
->ValueType
;
2697 TempBuffer
= (UINT8
*) &Value
->Value
;
2698 ZeroMem (TempStr
, sizeof (TempStr
));
2699 for (Index
= 0; Index
< TempLength
; Index
++) {
2700 TempStr
[0] = StrPtr
[TempLength
- Index
- 1];
2701 DigitUint8
= (UINT8
) StrHexToUint64 (TempStr
);
2702 if ((Index
& 1) == 0) {
2703 TempBuffer
[Index
/2] = DigitUint8
;
2705 TempBuffer
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + TempBuffer
[Index
/2]);
2712 case EFI_HII_VARSTORE_EFI_VARIABLE
:
2714 // Get value from variable.
2716 TempLength
= OpCode
->ValueWidth
;
2717 Value
->Type
= OpCode
->ValueType
;
2718 Status
= gRT
->GetVariable (
2720 &OpCode
->VarStorage
->Guid
,
2725 if (EFI_ERROR (Status
)) {
2726 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2727 Value
->Value
.u8
= 0;
2732 // Not recognize storage.
2734 Status
= EFI_UNSUPPORTED
;
2739 // For Time/Date Data
2741 if (OpCode
->ValueType
!= EFI_IFR_TYPE_DATE
&& OpCode
->ValueType
!= EFI_IFR_TYPE_TIME
) {
2743 // Only support Data/Time data when storage doesn't exist.
2745 Status
= EFI_UNSUPPORTED
;
2748 Status
= gRT
->GetTime (&EfiTime
, NULL
);
2749 if (!EFI_ERROR (Status
)) {
2750 if (OpCode
->ValueType
== EFI_IFR_TYPE_DATE
) {
2751 switch (OpCode
->VarStoreInfo
.VarOffset
) {
2753 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_16
;
2754 Value
->Value
.u16
= EfiTime
.Year
;
2757 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
2758 Value
->Value
.u8
= EfiTime
.Month
;
2761 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
2762 Value
->Value
.u8
= EfiTime
.Day
;
2766 // Invalid Date field.
2768 Status
= EFI_INVALID_PARAMETER
;
2772 switch (OpCode
->VarStoreInfo
.VarOffset
) {
2774 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
2775 Value
->Value
.u8
= EfiTime
.Hour
;
2778 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
2779 Value
->Value
.u8
= EfiTime
.Minute
;
2782 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
2783 Value
->Value
.u8
= EfiTime
.Second
;
2787 // Invalid Time field.
2789 Status
= EFI_INVALID_PARAMETER
;
2798 case EFI_IFR_QUESTION_REF3_OP
:
2800 // EFI_IFR_QUESTION_REF3
2801 // Pop an expression from the expression stack
2803 Status
= PopExpression (Value
);
2804 if (EFI_ERROR (Status
)) {
2809 // Validate the expression value
2811 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
2812 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2816 if (OpCode
->DevicePath
!= 0) {
2817 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2819 StrPtr
= GetToken (OpCode
->DevicePath
, FormSet
->HiiHandle
);
2820 if (StrPtr
!= NULL
&& mPathFromText
!= NULL
) {
2821 DevicePath
= mPathFromText
->ConvertTextToDevicePath(StrPtr
);
2822 if (DevicePath
!= NULL
&& GetQuestionValueFromForm(DevicePath
, NULL
, &OpCode
->Guid
, Value
->Value
.u16
, &QuestionVal
)) {
2823 Value
= &QuestionVal
;
2825 if (DevicePath
!= NULL
) {
2826 FreePool (DevicePath
);
2830 if (StrPtr
!= NULL
) {
2833 } else if (IsZeroGuid (&OpCode
->Guid
)) {
2834 if (!GetQuestionValueFromForm(NULL
, FormSet
->HiiHandle
, &OpCode
->Guid
, Value
->Value
.u16
, &QuestionVal
)){
2835 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2838 Value
= &QuestionVal
;
2840 Question
= IdToQuestion (FormSet
, Form
, Value
->Value
.u16
);
2841 if (Question
== NULL
) {
2842 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2847 // push the questions' value on to the expression stack
2849 Value
= &Question
->HiiValue
;
2853 case EFI_IFR_RULE_REF_OP
:
2855 // Find expression for this rule
2857 RuleExpression
= RuleIdToExpression (Form
, OpCode
->RuleId
);
2858 if (RuleExpression
== NULL
) {
2859 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2864 // Evaluate this rule expression
2866 Status
= EvaluateExpression (FormSet
, Form
, RuleExpression
);
2867 if (EFI_ERROR (Status
) || RuleExpression
->Result
.Type
== EFI_IFR_TYPE_UNDEFINED
) {
2868 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2872 Value
= &RuleExpression
->Result
;
2875 case EFI_IFR_STRING_REF1_OP
:
2876 Value
->Type
= EFI_IFR_TYPE_STRING
;
2877 Value
->Value
.string
= OpCode
->Value
.Value
.string
;
2883 case EFI_IFR_TRUE_OP
:
2884 case EFI_IFR_FALSE_OP
:
2885 case EFI_IFR_ONE_OP
:
2886 case EFI_IFR_ONES_OP
:
2887 case EFI_IFR_UINT8_OP
:
2888 case EFI_IFR_UINT16_OP
:
2889 case EFI_IFR_UINT32_OP
:
2890 case EFI_IFR_UINT64_OP
:
2891 case EFI_IFR_UNDEFINED_OP
:
2892 case EFI_IFR_VERSION_OP
:
2893 case EFI_IFR_ZERO_OP
:
2894 Value
= &OpCode
->Value
;
2900 case EFI_IFR_LENGTH_OP
:
2901 Status
= PopExpression (Value
);
2902 if (EFI_ERROR (Status
)) {
2905 if (Value
->Type
!= EFI_IFR_TYPE_STRING
&& !IsTypeInBuffer (Value
)) {
2906 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2910 if (Value
->Type
== EFI_IFR_TYPE_STRING
) {
2911 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->HiiHandle
);
2912 if (StrPtr
== NULL
) {
2913 Status
= EFI_INVALID_PARAMETER
;
2917 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
2918 Value
->Value
.u64
= StrLen (StrPtr
);
2921 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
2922 Value
->Value
.u64
= GetLengthForValue(Value
);
2923 FreePool (Value
->Buffer
);
2927 case EFI_IFR_NOT_OP
:
2928 Status
= PopExpression (Value
);
2929 if (EFI_ERROR (Status
)) {
2932 if (Value
->Type
!= EFI_IFR_TYPE_BOOLEAN
) {
2933 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2936 Value
->Value
.b
= (BOOLEAN
) (!Value
->Value
.b
);
2939 case EFI_IFR_QUESTION_REF2_OP
:
2941 // Pop an expression from the expression stack
2943 Status
= PopExpression (Value
);
2944 if (EFI_ERROR (Status
)) {
2949 // Validate the expression value
2951 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
2952 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2956 Question
= IdToQuestion (FormSet
, Form
, Value
->Value
.u16
);
2957 if (Question
== NULL
) {
2958 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2962 Value
= &Question
->HiiValue
;
2965 case EFI_IFR_STRING_REF2_OP
:
2967 // Pop an expression from the expression stack
2969 Status
= PopExpression (Value
);
2970 if (EFI_ERROR (Status
)) {
2975 // Validate the expression value
2977 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
2978 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2982 Value
->Type
= EFI_IFR_TYPE_STRING
;
2983 StrPtr
= GetToken (Value
->Value
.u16
, FormSet
->HiiHandle
);
2984 if (StrPtr
== NULL
) {
2986 // If String not exit, push an empty string
2988 Value
->Value
.string
= NewString (gEmptyString
, FormSet
->HiiHandle
);
2990 Index
= (UINT16
) Value
->Value
.u64
;
2991 Value
->Value
.string
= Index
;
2996 case EFI_IFR_TO_BOOLEAN_OP
:
2998 // Pop an expression from the expression stack
3000 Status
= PopExpression (Value
);
3001 if (EFI_ERROR (Status
)) {
3006 // Convert an expression to a Boolean
3008 if (Value
->Type
<= EFI_IFR_TYPE_DATE
) {
3010 // When converting from an unsigned integer, zero will be converted to
3011 // FALSE and any other value will be converted to TRUE.
3013 Value
->Value
.b
= (BOOLEAN
) (HiiValueToUINT64(Value
) != 0);
3015 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
3016 } else if (Value
->Type
== EFI_IFR_TYPE_STRING
) {
3018 // When converting from a string, if case-insensitive compare
3019 // with "true" is True, then push True. If a case-insensitive compare
3020 // with "false" is True, then push False. Otherwise, push Undefined.
3022 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->HiiHandle
);
3023 if (StrPtr
== NULL
) {
3024 Status
= EFI_INVALID_PARAMETER
;
3028 IfrStrToUpper (StrPtr
);
3029 if (StrCmp (StrPtr
, L
"TRUE") == 0){
3030 Value
->Value
.b
= TRUE
;
3031 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
3032 } else if (StrCmp (StrPtr
, L
"FALSE") == 0) {
3033 Value
->Value
.b
= FALSE
;
3034 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
3036 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3039 } else if (Value
->Type
== EFI_IFR_TYPE_BUFFER
) {
3041 // When converting from a buffer, if the buffer is all zeroes,
3042 // then push False. Otherwise push True.
3044 for (Index
=0; Index
< Value
->BufferLen
; Index
++) {
3045 if (Value
->Buffer
[Index
] != 0) {
3050 if (Index
>= Value
->BufferLen
) {
3051 Value
->Value
.b
= FALSE
;
3053 Value
->Value
.b
= TRUE
;
3055 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
3056 FreePool (Value
->Buffer
);
3060 case EFI_IFR_TO_STRING_OP
:
3061 Status
= IfrToString (FormSet
, OpCode
->Format
, Value
);
3064 case EFI_IFR_TO_UINT_OP
:
3065 Status
= IfrToUint (FormSet
, Value
);
3068 case EFI_IFR_TO_LOWER_OP
:
3069 case EFI_IFR_TO_UPPER_OP
:
3070 Status
= InitializeUnicodeCollationProtocol ();
3071 if (EFI_ERROR (Status
)) {
3075 Status
= PopExpression (Value
);
3076 if (EFI_ERROR (Status
)) {
3080 if (Value
->Type
!= EFI_IFR_TYPE_STRING
) {
3081 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3085 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->HiiHandle
);
3086 if (StrPtr
== NULL
) {
3087 Status
= EFI_NOT_FOUND
;
3091 if (OpCode
->Operand
== EFI_IFR_TO_LOWER_OP
) {
3092 mUnicodeCollation
->StrLwr (mUnicodeCollation
, StrPtr
);
3094 mUnicodeCollation
->StrUpr (mUnicodeCollation
, StrPtr
);
3096 Value
->Value
.string
= NewString (StrPtr
, FormSet
->HiiHandle
);
3100 case EFI_IFR_BITWISE_NOT_OP
:
3102 // Pop an expression from the expression stack
3104 Status
= PopExpression (Value
);
3105 if (EFI_ERROR (Status
)) {
3108 if (Value
->Type
> EFI_IFR_TYPE_DATE
) {
3109 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3113 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
3114 Value
->Value
.u64
= ~ HiiValueToUINT64(Value
);
3117 case EFI_IFR_SET_OP
:
3119 // Pop an expression from the expression stack
3121 Status
= PopExpression (Value
);
3122 if (EFI_ERROR (Status
)) {
3125 Data1
.Type
= EFI_IFR_TYPE_BOOLEAN
;
3126 Data1
.Value
.b
= FALSE
;
3128 // Set value to var storage buffer
3130 if (OpCode
->VarStorage
!= NULL
) {
3131 switch (OpCode
->VarStorage
->Type
) {
3132 case EFI_HII_VARSTORE_BUFFER
:
3133 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
3134 CopyMem (OpCode
->VarStorage
->EditBuffer
+ OpCode
->VarStoreInfo
.VarOffset
, &Value
->Value
, OpCode
->ValueWidth
);
3135 Data1
.Value
.b
= TRUE
;
3137 case EFI_HII_VARSTORE_NAME_VALUE
:
3138 if (OpCode
->ValueType
!= EFI_IFR_TYPE_STRING
) {
3139 NameValue
= AllocateZeroPool ((OpCode
->ValueWidth
* 2 + 1) * sizeof (CHAR16
));
3140 ASSERT (NameValue
!= NULL
);
3142 // Convert Buffer to Hex String
3144 TempBuffer
= (UINT8
*) &Value
->Value
+ OpCode
->ValueWidth
- 1;
3146 for (Index
= 0; Index
< OpCode
->ValueWidth
; Index
++, TempBuffer
--) {
3147 UnicodeValueToStringS (
3149 (OpCode
->ValueWidth
* 2 + 1) * sizeof (CHAR16
) - ((UINTN
)StrPtr
- (UINTN
)NameValue
),
3150 PREFIX_ZERO
| RADIX_HEX
,
3154 StrPtr
+= StrnLenS (StrPtr
, OpCode
->ValueWidth
* 2 + 1 - ((UINTN
)StrPtr
- (UINTN
)NameValue
) / sizeof (CHAR16
));
3156 Status
= SetValueByName (OpCode
->VarStorage
, OpCode
->ValueName
, NameValue
, GetSetValueWithEditBuffer
, NULL
);
3157 FreePool (NameValue
);
3158 if (!EFI_ERROR (Status
)) {
3159 Data1
.Value
.b
= TRUE
;
3163 case EFI_HII_VARSTORE_EFI_VARIABLE
:
3164 Status
= gRT
->SetVariable (
3166 &OpCode
->VarStorage
->Guid
,
3167 OpCode
->VarStorage
->Attributes
,
3171 if (!EFI_ERROR (Status
)) {
3172 Data1
.Value
.b
= TRUE
;
3177 // Not recognize storage.
3179 Status
= EFI_UNSUPPORTED
;
3184 // For Time/Date Data
3186 if (OpCode
->ValueType
!= EFI_IFR_TYPE_DATE
&& OpCode
->ValueType
!= EFI_IFR_TYPE_TIME
) {
3188 // Only support Data/Time data when storage doesn't exist.
3190 Status
= EFI_UNSUPPORTED
;
3193 Status
= gRT
->GetTime (&EfiTime
, NULL
);
3194 if (!EFI_ERROR (Status
)) {
3195 if (OpCode
->ValueType
== EFI_IFR_TYPE_DATE
) {
3196 switch (OpCode
->VarStoreInfo
.VarOffset
) {
3198 EfiTime
.Year
= Value
->Value
.u16
;
3201 EfiTime
.Month
= Value
->Value
.u8
;
3204 EfiTime
.Day
= Value
->Value
.u8
;
3208 // Invalid Date field.
3210 Status
= EFI_INVALID_PARAMETER
;
3214 switch (OpCode
->VarStoreInfo
.VarOffset
) {
3216 EfiTime
.Hour
= Value
->Value
.u8
;
3219 EfiTime
.Minute
= Value
->Value
.u8
;
3222 EfiTime
.Second
= Value
->Value
.u8
;
3226 // Invalid Time field.
3228 Status
= EFI_INVALID_PARAMETER
;
3232 Status
= gRT
->SetTime (&EfiTime
);
3233 if (!EFI_ERROR (Status
)) {
3234 Data1
.Value
.b
= TRUE
;
3244 case EFI_IFR_ADD_OP
:
3245 case EFI_IFR_SUBTRACT_OP
:
3246 case EFI_IFR_MULTIPLY_OP
:
3247 case EFI_IFR_DIVIDE_OP
:
3248 case EFI_IFR_MODULO_OP
:
3249 case EFI_IFR_BITWISE_AND_OP
:
3250 case EFI_IFR_BITWISE_OR_OP
:
3251 case EFI_IFR_SHIFT_LEFT_OP
:
3252 case EFI_IFR_SHIFT_RIGHT_OP
:
3254 // Pop an expression from the expression stack
3256 Status
= PopExpression (&Data2
);
3257 if (EFI_ERROR (Status
)) {
3262 // Pop another expression from the expression stack
3264 Status
= PopExpression (&Data1
);
3265 if (EFI_ERROR (Status
)) {
3269 if (Data2
.Type
> EFI_IFR_TYPE_DATE
) {
3270 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3275 if (Data1
.Type
> EFI_IFR_TYPE_DATE
) {
3276 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3280 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
3282 switch (OpCode
->Operand
) {
3283 case EFI_IFR_ADD_OP
:
3284 Value
->Value
.u64
= HiiValueToUINT64(&Data1
) + HiiValueToUINT64(&Data2
);
3287 case EFI_IFR_SUBTRACT_OP
:
3288 Value
->Value
.u64
= HiiValueToUINT64(&Data1
) - HiiValueToUINT64(&Data2
);
3291 case EFI_IFR_MULTIPLY_OP
:
3292 Value
->Value
.u64
= MultU64x32 (HiiValueToUINT64(&Data1
), (UINT32
) HiiValueToUINT64(&Data2
));
3295 case EFI_IFR_DIVIDE_OP
:
3296 Value
->Value
.u64
= DivU64x32 (HiiValueToUINT64(&Data1
), (UINT32
) HiiValueToUINT64(&Data2
));
3299 case EFI_IFR_MODULO_OP
:
3300 DivU64x32Remainder (HiiValueToUINT64(&Data1
), (UINT32
) HiiValueToUINT64(&Data2
), &TempValue
);
3301 Value
->Value
.u64
= TempValue
;
3304 case EFI_IFR_BITWISE_AND_OP
:
3305 Value
->Value
.u64
= HiiValueToUINT64(&Data1
) & HiiValueToUINT64(&Data2
);
3308 case EFI_IFR_BITWISE_OR_OP
:
3309 Value
->Value
.u64
= HiiValueToUINT64(&Data1
) | HiiValueToUINT64(&Data2
);
3312 case EFI_IFR_SHIFT_LEFT_OP
:
3313 Value
->Value
.u64
= LShiftU64 (HiiValueToUINT64(&Data1
), (UINTN
) HiiValueToUINT64(&Data2
));
3316 case EFI_IFR_SHIFT_RIGHT_OP
:
3317 Value
->Value
.u64
= RShiftU64 (HiiValueToUINT64(&Data1
), (UINTN
) HiiValueToUINT64(&Data2
));
3325 case EFI_IFR_AND_OP
:
3328 // Two Boolean operator
3330 Status
= PopExpression (&Data2
);
3331 if (EFI_ERROR (Status
)) {
3336 // Pop another expression from the expression stack
3338 Status
= PopExpression (&Data1
);
3339 if (EFI_ERROR (Status
)) {
3343 if (Data2
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
3344 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3348 if (Data1
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
3349 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3353 if (OpCode
->Operand
== EFI_IFR_AND_OP
) {
3354 Value
->Value
.b
= (BOOLEAN
) (Data1
.Value
.b
&& Data2
.Value
.b
);
3356 Value
->Value
.b
= (BOOLEAN
) (Data1
.Value
.b
|| Data2
.Value
.b
);
3360 case EFI_IFR_EQUAL_OP
:
3361 case EFI_IFR_NOT_EQUAL_OP
:
3362 case EFI_IFR_GREATER_EQUAL_OP
:
3363 case EFI_IFR_GREATER_THAN_OP
:
3364 case EFI_IFR_LESS_EQUAL_OP
:
3365 case EFI_IFR_LESS_THAN_OP
:
3367 // Compare two integer, string, boolean or date/time
3369 Status
= PopExpression (&Data2
);
3370 if (EFI_ERROR (Status
)) {
3375 // Pop another expression from the expression stack
3377 Status
= PopExpression (&Data1
);
3378 if (EFI_ERROR (Status
)) {
3382 if (Data2
.Type
> EFI_IFR_TYPE_BOOLEAN
&&
3383 Data2
.Type
!= EFI_IFR_TYPE_STRING
&&
3384 !IsTypeInBuffer(&Data2
)) {
3385 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3389 if (Data1
.Type
> EFI_IFR_TYPE_BOOLEAN
&&
3390 Data1
.Type
!= EFI_IFR_TYPE_STRING
&&
3391 !IsTypeInBuffer(&Data1
)) {
3392 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3396 Status
= CompareHiiValue (&Data1
, &Data2
, &Result
, FormSet
->HiiHandle
);
3397 if (Data1
.Type
== EFI_IFR_TYPE_BUFFER
) {
3398 FreePool (Data1
.Buffer
);
3400 if (Data2
.Type
== EFI_IFR_TYPE_BUFFER
) {
3401 FreePool (Data2
.Buffer
);
3404 if (Status
== EFI_UNSUPPORTED
) {
3405 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3406 Status
= EFI_SUCCESS
;
3410 if (EFI_ERROR (Status
)) {
3414 switch (OpCode
->Operand
) {
3415 case EFI_IFR_EQUAL_OP
:
3416 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
3419 case EFI_IFR_NOT_EQUAL_OP
:
3420 Value
->Value
.b
= (BOOLEAN
) ((Result
!= 0) ? TRUE
: FALSE
);
3423 case EFI_IFR_GREATER_EQUAL_OP
:
3424 Value
->Value
.b
= (BOOLEAN
) ((Result
>= 0) ? TRUE
: FALSE
);
3427 case EFI_IFR_GREATER_THAN_OP
:
3428 Value
->Value
.b
= (BOOLEAN
) ((Result
> 0) ? TRUE
: FALSE
);
3431 case EFI_IFR_LESS_EQUAL_OP
:
3432 Value
->Value
.b
= (BOOLEAN
) ((Result
<= 0) ? TRUE
: FALSE
);
3435 case EFI_IFR_LESS_THAN_OP
:
3436 Value
->Value
.b
= (BOOLEAN
) ((Result
< 0) ? TRUE
: FALSE
);
3444 case EFI_IFR_MATCH_OP
:
3445 Status
= InitializeUnicodeCollationProtocol ();
3446 if (EFI_ERROR (Status
)) {
3450 Status
= IfrMatch (FormSet
, Value
);
3453 case EFI_IFR_MATCH2_OP
:
3454 Status
= IfrMatch2 (FormSet
, &OpCode
->Guid
, Value
);
3457 case EFI_IFR_CATENATE_OP
:
3458 Status
= IfrCatenate (FormSet
, Value
);
3464 case EFI_IFR_CONDITIONAL_OP
:
3466 // Pop third expression from the expression stack
3468 Status
= PopExpression (&Data3
);
3469 if (EFI_ERROR (Status
)) {
3474 // Pop second expression from the expression stack
3476 Status
= PopExpression (&Data2
);
3477 if (EFI_ERROR (Status
)) {
3482 // Pop first expression from the expression stack
3484 Status
= PopExpression (&Data1
);
3485 if (EFI_ERROR (Status
)) {
3488 if (Data1
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
3489 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3493 if (Data1
.Value
.b
) {
3500 case EFI_IFR_FIND_OP
:
3501 Status
= IfrFind (FormSet
, OpCode
->Format
, Value
);
3504 case EFI_IFR_MID_OP
:
3505 Status
= IfrMid (FormSet
, Value
);
3508 case EFI_IFR_TOKEN_OP
:
3509 Status
= IfrToken (FormSet
, Value
);
3512 case EFI_IFR_SPAN_OP
:
3513 Status
= IfrSpan (FormSet
, OpCode
->Flags
, Value
);
3516 case EFI_IFR_MAP_OP
:
3518 // Pop the check value
3520 Status
= PopExpression (&Data1
);
3521 if (EFI_ERROR (Status
)) {
3525 // Check MapExpression list is valid.
3527 if (OpCode
->MapExpressionList
.ForwardLink
== NULL
) {
3528 Status
= EFI_INVALID_PARAMETER
;
3532 // Go through map expression list.
3534 SubExpressionLink
= GetFirstNode(&OpCode
->MapExpressionList
);
3535 while (!IsNull (&OpCode
->MapExpressionList
, SubExpressionLink
)) {
3536 SubExpression
= FORM_EXPRESSION_FROM_LINK (SubExpressionLink
);
3538 // Evaluate the first expression in this pair.
3540 Status
= EvaluateExpression (FormSet
, Form
, SubExpression
);
3541 if (EFI_ERROR (Status
)) {
3545 // Compare the expression value with current value
3547 if ((CompareHiiValue (&Data1
, &SubExpression
->Result
, &Result
, NULL
) == EFI_SUCCESS
) && (Result
== 0)) {
3549 // Try get the map value.
3551 SubExpressionLink
= GetNextNode (&OpCode
->MapExpressionList
, SubExpressionLink
);
3552 if (IsNull (&OpCode
->MapExpressionList
, SubExpressionLink
)) {
3553 Status
= EFI_INVALID_PARAMETER
;
3556 SubExpression
= FORM_EXPRESSION_FROM_LINK (SubExpressionLink
);
3557 Status
= EvaluateExpression (FormSet
, Form
, SubExpression
);
3558 if (EFI_ERROR (Status
)) {
3561 Value
= &SubExpression
->Result
;
3565 // Skip the second expression on this pair.
3567 SubExpressionLink
= GetNextNode (&OpCode
->MapExpressionList
, SubExpressionLink
);
3568 if (IsNull (&OpCode
->MapExpressionList
, SubExpressionLink
)) {
3569 Status
= EFI_INVALID_PARAMETER
;
3573 // Goto the first expression on next pair.
3575 SubExpressionLink
= GetNextNode (&OpCode
->MapExpressionList
, SubExpressionLink
);
3579 // No map value is found.
3581 if (IsNull (&OpCode
->MapExpressionList
, SubExpressionLink
)) {
3582 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3583 Value
->Value
.u8
= 0;
3590 if (EFI_ERROR (Status
) || Value
->Type
== EFI_IFR_TYPE_UNDEFINED
) {
3594 Status
= PushExpression (Value
);
3595 if (EFI_ERROR (Status
)) {
3601 // Pop the final result from expression stack
3604 Status
= PopExpression (Value
);
3605 if (EFI_ERROR (Status
)) {
3610 // After evaluating an expression, there should be only one value left on the expression stack
3612 if (PopExpression (Value
) != EFI_ACCESS_DENIED
) {
3613 Status
= EFI_INVALID_PARAMETER
;
3617 RestoreExpressionEvaluationStackOffset (StackOffset
);
3618 if (!EFI_ERROR (Status
)) {
3619 CopyMem (&Expression
->Result
, Value
, sizeof (EFI_HII_VALUE
));
3626 Check whether the result is TRUE or FALSE.
3628 For the EFI_HII_VALUE value type is numeric, return TRUE if the
3631 @param Result Input the result data.
3633 @retval TRUE The result is TRUE.
3634 @retval FALSE The result is FALSE.
3639 IN EFI_HII_VALUE
*Result
3642 switch (Result
->Type
) {
3643 case EFI_IFR_TYPE_BOOLEAN
:
3644 return Result
->Value
.b
;
3646 case EFI_IFR_TYPE_NUM_SIZE_8
:
3647 return (BOOLEAN
)(Result
->Value
.u8
!= 0);
3649 case EFI_IFR_TYPE_NUM_SIZE_16
:
3650 return (BOOLEAN
)(Result
->Value
.u16
!= 0);
3652 case EFI_IFR_TYPE_NUM_SIZE_32
:
3653 return (BOOLEAN
)(Result
->Value
.u32
!= 0);
3655 case EFI_IFR_TYPE_NUM_SIZE_64
:
3656 return (BOOLEAN
)(Result
->Value
.u64
!= 0);
3664 Return the result of the expression list. Check the expression list and
3665 return the highest priority express result.
3666 Priority: DisableIf > SuppressIf > GrayOutIf > FALSE
3668 @param ExpList The input expression list.
3669 @param Evaluate Whether need to evaluate the expression first.
3670 @param FormSet FormSet associated with this expression.
3671 @param Form Form associated with this expression.
3673 @retval EXPRESS_RESULT Return the higher priority express result.
3674 DisableIf > SuppressIf > GrayOutIf > FALSE
3678 EvaluateExpressionList (
3679 IN FORM_EXPRESSION_LIST
*ExpList
,
3680 IN BOOLEAN Evaluate
,
3681 IN FORM_BROWSER_FORMSET
*FormSet
, OPTIONAL
3682 IN FORM_BROWSER_FORM
*Form OPTIONAL
3686 EXPRESS_RESULT ReturnVal
;
3687 EXPRESS_RESULT CompareOne
;
3690 if (ExpList
== NULL
) {
3691 return ExpressFalse
;
3694 ASSERT(ExpList
->Signature
== FORM_EXPRESSION_LIST_SIGNATURE
);
3698 // Check whether need to evaluate the expression first.
3701 while (ExpList
->Count
> Index
) {
3702 Status
= EvaluateExpression (FormSet
, Form
, ExpList
->Expression
[Index
++]);
3703 if (EFI_ERROR (Status
)) {
3704 return ExpressFalse
;
3710 // Run the list of expressions.
3712 ReturnVal
= ExpressFalse
;
3713 for (Index
= 0; Index
< ExpList
->Count
; Index
++) {
3714 if (IsTrue (&ExpList
->Expression
[Index
]->Result
)) {
3715 switch (ExpList
->Expression
[Index
]->Type
) {
3716 case EFI_HII_EXPRESSION_SUPPRESS_IF
:
3717 CompareOne
= ExpressSuppress
;
3720 case EFI_HII_EXPRESSION_GRAY_OUT_IF
:
3721 CompareOne
= ExpressGrayOut
;
3724 case EFI_HII_EXPRESSION_DISABLE_IF
:
3725 CompareOne
= ExpressDisable
;
3729 return ExpressFalse
;
3732 ReturnVal
= ReturnVal
< CompareOne
? CompareOne
: ReturnVal
;