2 Utility functions for expression evaluation.
4 Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
12 // Global stack used to evaluate boolean expresions
14 EFI_HII_VALUE
*mOpCodeScopeStack
= NULL
;
15 EFI_HII_VALUE
*mOpCodeScopeStackEnd
= NULL
;
16 EFI_HII_VALUE
*mOpCodeScopeStackPointer
= NULL
;
18 EFI_HII_VALUE
*mExpressionEvaluationStack
= NULL
;
19 EFI_HII_VALUE
*mExpressionEvaluationStackEnd
= NULL
;
20 EFI_HII_VALUE
*mExpressionEvaluationStackPointer
= NULL
;
21 UINTN mExpressionEvaluationStackOffset
= 0;
23 EFI_HII_VALUE
*mCurrentExpressionStack
= NULL
;
24 EFI_HII_VALUE
*mCurrentExpressionEnd
= NULL
;
25 EFI_HII_VALUE
*mCurrentExpressionPointer
= NULL
;
27 EFI_HII_VALUE
*mMapExpressionListStack
= NULL
;
28 EFI_HII_VALUE
*mMapExpressionListEnd
= NULL
;
29 EFI_HII_VALUE
*mMapExpressionListPointer
= NULL
;
31 FORM_EXPRESSION
**mFormExpressionStack
= NULL
;
32 FORM_EXPRESSION
**mFormExpressionEnd
= NULL
;
33 FORM_EXPRESSION
**mFormExpressionPointer
= NULL
;
35 FORM_EXPRESSION
**mStatementExpressionStack
= NULL
;
36 FORM_EXPRESSION
**mStatementExpressionEnd
= NULL
;
37 FORM_EXPRESSION
**mStatementExpressionPointer
= NULL
;
39 FORM_EXPRESSION
**mOptionExpressionStack
= NULL
;
40 FORM_EXPRESSION
**mOptionExpressionEnd
= NULL
;
41 FORM_EXPRESSION
**mOptionExpressionPointer
= NULL
;
44 // Unicode collation protocol interface
46 EFI_UNICODE_COLLATION_PROTOCOL
*mUnicodeCollation
= NULL
;
47 EFI_USER_MANAGER_PROTOCOL
*mUserManager
= NULL
;
50 Grow size of the stack.
52 This is an internal function.
54 @param Stack On input: old stack; On output: new stack
55 @param StackPtr On input: old stack pointer; On output: new stack
57 @param StackEnd On input: old stack end; On output: new stack end
59 @retval EFI_SUCCESS Grow stack success.
60 @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.
65 IN OUT EFI_HII_VALUE
**Stack
,
66 IN OUT EFI_HII_VALUE
**StackPtr
,
67 IN OUT EFI_HII_VALUE
**StackEnd
71 EFI_HII_VALUE
*NewStack
;
73 Size
= EXPRESSION_STACK_SIZE_INCREMENT
;
74 if (*StackPtr
!= NULL
) {
75 Size
= Size
+ (*StackEnd
- *Stack
);
78 NewStack
= AllocatePool (Size
* sizeof (EFI_HII_VALUE
));
79 if (NewStack
== NULL
) {
80 return EFI_OUT_OF_RESOURCES
;
83 if (*StackPtr
!= NULL
) {
85 // Copy from Old Stack to the New Stack
90 (*StackEnd
- *Stack
) * sizeof (EFI_HII_VALUE
)
100 // Make the Stack pointer point to the old data in the new stack
102 *StackPtr
= NewStack
+ (*StackPtr
- *Stack
);
104 *StackEnd
= NewStack
+ Size
;
110 Push an element onto the Boolean Stack.
112 @param Stack On input: old stack; On output: new stack
113 @param StackPtr On input: old stack pointer; On output: new stack
115 @param StackEnd On input: old stack end; On output: new stack end
116 @param Data Data to push.
118 @retval EFI_SUCCESS Push stack success.
123 IN OUT EFI_HII_VALUE
**Stack
,
124 IN OUT EFI_HII_VALUE
**StackPtr
,
125 IN OUT EFI_HII_VALUE
**StackEnd
,
126 IN EFI_HII_VALUE
*Data
132 // Check for a stack overflow condition
134 if (*StackPtr
>= *StackEnd
) {
138 Status
= GrowStack (Stack
, StackPtr
, StackEnd
);
139 if (EFI_ERROR (Status
)) {
145 // Push the item onto the stack
147 CopyMem (*StackPtr
, Data
, sizeof (EFI_HII_VALUE
));
148 if (Data
->Type
== EFI_IFR_TYPE_BUFFER
) {
149 (*StackPtr
)->Buffer
= AllocateCopyPool (Data
->BufferLen
, Data
->Buffer
);
150 ASSERT ((*StackPtr
)->Buffer
!= NULL
);
153 *StackPtr
= *StackPtr
+ 1;
159 Pop an element from the stack.
161 @param Stack On input: old stack
162 @param StackPtr On input: old stack pointer; On output: new stack pointer
163 @param Data Data to pop.
165 @retval EFI_SUCCESS The value was popped onto the stack.
166 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
171 IN EFI_HII_VALUE
*Stack
,
172 IN OUT EFI_HII_VALUE
**StackPtr
,
173 OUT EFI_HII_VALUE
*Data
177 // Check for a stack underflow condition
179 if (*StackPtr
== Stack
) {
180 return EFI_ACCESS_DENIED
;
184 // Pop the item off the stack
186 *StackPtr
= *StackPtr
- 1;
187 CopyMem (Data
, *StackPtr
, sizeof (EFI_HII_VALUE
));
192 Reset stack pointer to begin of the stack.
196 ResetCurrentExpressionStack (
200 mCurrentExpressionPointer
= mCurrentExpressionStack
;
201 mFormExpressionPointer
= mFormExpressionStack
;
202 mStatementExpressionPointer
= mStatementExpressionStack
;
203 mOptionExpressionPointer
= mOptionExpressionStack
;
207 Push current expression onto the Stack
209 @param Pointer Pointer to current expression.
211 @retval EFI_SUCCESS The value was pushed onto the stack.
212 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
216 PushCurrentExpression (
222 Data
.Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
223 Data
.Value
.u64
= (UINT64
)(UINTN
)Pointer
;
226 &mCurrentExpressionStack
,
227 &mCurrentExpressionPointer
,
228 &mCurrentExpressionEnd
,
234 Pop current expression from the Stack
236 @param Pointer Pointer to current expression to be pop.
238 @retval EFI_SUCCESS The value was pushed onto the stack.
239 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
243 PopCurrentExpression (
251 mCurrentExpressionStack
,
252 &mCurrentExpressionPointer
,
256 *Pointer
= (VOID
*)(UINTN
)Data
.Value
.u64
;
262 Reset stack pointer to begin of the stack.
266 ResetMapExpressionListStack (
270 mMapExpressionListPointer
= mMapExpressionListStack
;
274 Grow size of the stack.
276 This is an internal function.
278 @param Stack On input: old stack; On output: new stack
279 @param StackPtr On input: old stack pointer; On output: new stack
281 @param StackEnd On input: old stack end; On output: new stack end
282 @param MemberSize The stack member size.
284 @retval EFI_SUCCESS Grow stack success.
285 @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.
289 GrowConditionalStack (
290 IN OUT FORM_EXPRESSION
***Stack
,
291 IN OUT FORM_EXPRESSION
***StackPtr
,
292 IN OUT FORM_EXPRESSION
***StackEnd
,
297 FORM_EXPRESSION
**NewStack
;
299 Size
= EXPRESSION_STACK_SIZE_INCREMENT
;
300 if (*StackPtr
!= NULL
) {
301 Size
= Size
+ (*StackEnd
- *Stack
);
304 NewStack
= AllocatePool (Size
* MemberSize
);
305 if (NewStack
== NULL
) {
306 return EFI_OUT_OF_RESOURCES
;
309 if (*StackPtr
!= NULL
) {
311 // Copy from Old Stack to the New Stack
316 (*StackEnd
- *Stack
) * MemberSize
320 // Free The Old Stack
326 // Make the Stack pointer point to the old data in the new stack
328 *StackPtr
= NewStack
+ (*StackPtr
- *Stack
);
330 *StackEnd
= NewStack
+ Size
;
336 Push an element onto the Stack.
338 @param Stack On input: old stack; On output: new stack
339 @param StackPtr On input: old stack pointer; On output: new stack
341 @param StackEnd On input: old stack end; On output: new stack end
342 @param Data Data to push.
344 @retval EFI_SUCCESS Push stack success.
348 PushConditionalStack (
349 IN OUT FORM_EXPRESSION
***Stack
,
350 IN OUT FORM_EXPRESSION
***StackPtr
,
351 IN OUT FORM_EXPRESSION
***StackEnd
,
352 IN FORM_EXPRESSION
**Data
358 // Check for a stack overflow condition
360 if (*StackPtr
>= *StackEnd
) {
364 Status
= GrowConditionalStack (Stack
, StackPtr
, StackEnd
, sizeof (FORM_EXPRESSION
*));
365 if (EFI_ERROR (Status
)) {
371 // Push the item onto the stack
373 CopyMem (*StackPtr
, Data
, sizeof (FORM_EXPRESSION
*));
374 *StackPtr
= *StackPtr
+ 1;
380 Pop an element from the stack.
382 @param Stack On input: old stack
383 @param StackPtr On input: old stack pointer; On output: new stack pointer
384 @param Data Data to pop.
386 @retval EFI_SUCCESS The value was popped onto the stack.
387 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
391 PopConditionalStack (
392 IN FORM_EXPRESSION
**Stack
,
393 IN OUT FORM_EXPRESSION
***StackPtr
,
394 OUT FORM_EXPRESSION
**Data
398 // Check for a stack underflow condition
400 if (*StackPtr
== Stack
) {
401 return EFI_ACCESS_DENIED
;
405 // Pop the item off the stack
407 *StackPtr
= *StackPtr
- 1;
408 CopyMem (Data
, *StackPtr
, sizeof (FORM_EXPRESSION
*));
413 Get the expression list count.
415 @param Level Which type this expression belong to. Form,
418 @retval >=0 The expression count
419 @retval -1 Input parameter error.
423 GetConditionalExpressionCount (
424 IN EXPRESS_LEVEL Level
429 return mFormExpressionPointer
- mFormExpressionStack
;
430 case ExpressStatement
:
431 return mStatementExpressionPointer
- mStatementExpressionStack
;
433 return mOptionExpressionPointer
- mOptionExpressionStack
;
441 Get the expression Buffer pointer.
443 @param Level Which type this expression belong to. Form,
446 @retval The start pointer of the expression buffer or NULL.
450 GetConditionalExpressionList (
451 IN EXPRESS_LEVEL Level
456 return mFormExpressionStack
;
457 case ExpressStatement
:
458 return mStatementExpressionStack
;
460 return mOptionExpressionStack
;
468 Push the expression options onto the Stack.
470 @param Pointer Pointer to the current expression.
471 @param Level Which type this expression belong to. Form,
474 @retval EFI_SUCCESS The value was pushed onto the stack.
475 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
479 PushConditionalExpression (
480 IN FORM_EXPRESSION
*Pointer
,
481 IN EXPRESS_LEVEL Level
486 return PushConditionalStack (
487 &mFormExpressionStack
,
488 &mFormExpressionPointer
,
492 case ExpressStatement
:
493 return PushConditionalStack (
494 &mStatementExpressionStack
,
495 &mStatementExpressionPointer
,
496 &mStatementExpressionEnd
,
500 return PushConditionalStack (
501 &mOptionExpressionStack
,
502 &mOptionExpressionPointer
,
503 &mOptionExpressionEnd
,
508 return EFI_INVALID_PARAMETER
;
513 Pop the expression options from the Stack
515 @param Level Which type this expression belong to. Form,
518 @retval EFI_SUCCESS The value was pushed onto the stack.
519 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
523 PopConditionalExpression (
524 IN EXPRESS_LEVEL Level
527 FORM_EXPRESSION
*Pointer
;
531 return PopConditionalStack (
532 mFormExpressionStack
,
533 &mFormExpressionPointer
,
537 case ExpressStatement
:
538 return PopConditionalStack (
539 mStatementExpressionStack
,
540 &mStatementExpressionPointer
,
545 return PopConditionalStack (
546 mOptionExpressionStack
,
547 &mOptionExpressionPointer
,
553 return EFI_INVALID_PARAMETER
;
558 Push the list of map expression onto the Stack
560 @param Pointer Pointer to the list of map expression to be pushed.
562 @retval EFI_SUCCESS The value was pushed onto the stack.
563 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
567 PushMapExpressionList (
573 Data
.Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
574 Data
.Value
.u64
= (UINT64
)(UINTN
)Pointer
;
577 &mMapExpressionListStack
,
578 &mMapExpressionListPointer
,
579 &mMapExpressionListEnd
,
585 Pop the list of map expression from the Stack
587 @param Pointer Pointer to the list of map expression to be pop.
589 @retval EFI_SUCCESS The value was pushed onto the stack.
590 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
594 PopMapExpressionList (
602 mMapExpressionListStack
,
603 &mMapExpressionListPointer
,
607 *Pointer
= (VOID
*)(UINTN
)Data
.Value
.u64
;
613 Reset stack pointer to begin of the stack.
621 mOpCodeScopeStackPointer
= mOpCodeScopeStack
;
625 Push an Operand onto the Stack
627 @param Operand Operand to push.
629 @retval EFI_SUCCESS The value was pushed onto the stack.
630 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
641 Data
.Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
642 Data
.Value
.u8
= Operand
;
646 &mOpCodeScopeStackPointer
,
647 &mOpCodeScopeStackEnd
,
653 Pop an Operand from the Stack
655 @param Operand Operand to pop.
657 @retval EFI_SUCCESS The value was pushed onto the stack.
658 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
672 &mOpCodeScopeStackPointer
,
676 *Operand
= Data
.Value
.u8
;
682 Push an Expression value onto the Stack
684 @param Value Expression value to push.
686 @retval EFI_SUCCESS The value was pushed onto the stack.
687 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
693 IN EFI_HII_VALUE
*Value
697 &mExpressionEvaluationStack
,
698 &mExpressionEvaluationStackPointer
,
699 &mExpressionEvaluationStackEnd
,
705 Pop an Expression value from the stack.
707 @param Value Expression value to pop.
709 @retval EFI_SUCCESS The value was popped onto the stack.
710 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
715 OUT EFI_HII_VALUE
*Value
719 mExpressionEvaluationStack
+ mExpressionEvaluationStackOffset
,
720 &mExpressionEvaluationStackPointer
,
726 Get current stack offset from stack start.
728 @return Stack offset to stack start.
731 SaveExpressionEvaluationStackOffset (
735 UINTN TempStackOffset
;
737 TempStackOffset
= mExpressionEvaluationStackOffset
;
738 mExpressionEvaluationStackOffset
= mExpressionEvaluationStackPointer
- mExpressionEvaluationStack
;
739 return TempStackOffset
;
743 Restore stack offset based on input stack offset
745 @param StackOffset Offset to stack start.
749 RestoreExpressionEvaluationStackOffset (
753 mExpressionEvaluationStackOffset
= StackOffset
;
757 Get Form given its FormId.
759 @param FormSet The formset which contains this form.
760 @param FormId Id of this form.
762 @retval Pointer The form.
763 @retval NULL Specified Form is not found in the formset.
768 IN FORM_BROWSER_FORMSET
*FormSet
,
773 FORM_BROWSER_FORM
*Form
;
775 Link
= GetFirstNode (&FormSet
->FormListHead
);
776 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
777 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
779 if (Form
->FormId
== FormId
) {
783 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
790 Search a Question in Form scope using its QuestionId.
792 @param Form The form which contains this Question.
793 @param QuestionId Id of this Question.
795 @retval Pointer The Question.
796 @retval NULL Specified Question not found in the form.
799 FORM_BROWSER_STATEMENT
*
801 IN FORM_BROWSER_FORM
*Form
,
806 FORM_BROWSER_STATEMENT
*Question
;
808 if ((QuestionId
== 0) || (Form
== NULL
)) {
810 // The value of zero is reserved
815 Link
= GetFirstNode (&Form
->StatementListHead
);
816 while (!IsNull (&Form
->StatementListHead
, Link
)) {
817 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
819 if (Question
->QuestionId
== QuestionId
) {
823 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
830 Search a Question in Formset scope using its QuestionId.
832 @param FormSet The formset which contains this form.
833 @param Form The form which contains this Question.
834 @param QuestionId Id of this Question.
836 @retval Pointer The Question.
837 @retval NULL Specified Question not found in the form.
840 FORM_BROWSER_STATEMENT
*
842 IN FORM_BROWSER_FORMSET
*FormSet
,
843 IN FORM_BROWSER_FORM
*Form
,
848 FORM_BROWSER_STATEMENT
*Question
;
851 // Search in the form scope first
853 Question
= IdToQuestion2 (Form
, QuestionId
);
854 if (Question
!= NULL
) {
859 // Search in the formset scope
861 Link
= GetFirstNode (&FormSet
->FormListHead
);
862 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
863 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
865 Question
= IdToQuestion2 (Form
, QuestionId
);
866 if (Question
!= NULL
) {
868 // EFI variable storage may be updated by Callback() asynchronous,
869 // to keep synchronous, always reload the Question Value.
871 if (Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
872 GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithHiiDriver
);
878 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
885 Get Expression given its RuleId.
887 @param Form The form which contains this Expression.
888 @param RuleId Id of this Expression.
890 @retval Pointer The Expression.
891 @retval NULL Specified Expression not found in the form.
896 IN FORM_BROWSER_FORM
*Form
,
901 FORM_EXPRESSION
*Expression
;
903 Link
= GetFirstNode (&Form
->ExpressionListHead
);
904 while (!IsNull (&Form
->ExpressionListHead
, Link
)) {
905 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
907 if ((Expression
->Type
== EFI_HII_EXPRESSION_RULE
) && (Expression
->RuleId
== RuleId
)) {
911 Link
= GetNextNode (&Form
->ExpressionListHead
, Link
);
918 Locate the Unicode Collation Protocol interface for later use.
920 @retval EFI_SUCCESS Protocol interface initialize success.
921 @retval Other Protocol interface initialize failed.
925 InitializeUnicodeCollationProtocol (
931 if (mUnicodeCollation
!= NULL
) {
936 // BUGBUG: Proper impelmentation is to locate all Unicode Collation Protocol
937 // instances first and then select one which support English language.
938 // Current implementation just pick the first instance.
940 Status
= gBS
->LocateProtocol (
941 &gEfiUnicodeCollation2ProtocolGuid
,
943 (VOID
**)&mUnicodeCollation
949 Convert the input Unicode character to upper.
951 @param String Th Unicode character to be converted.
959 while (*String
!= 0) {
960 if ((*String
>= 'a') && (*String
<= 'z')) {
961 *String
= (UINT16
)((*String
) & ((UINT16
) ~0x20));
969 Check whether this value type can be transfer to EFI_IFR_TYPE_BUFFER type.
971 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to
972 EFI_IFR_TYPE_BUFFER when do the value compare.
974 @param Value Expression value to compare on.
976 @retval TRUE This value type can be transter to EFI_IFR_TYPE_BUFFER type.
977 @retval FALSE This value type can't be transter to EFI_IFR_TYPE_BUFFER type.
982 IN EFI_HII_VALUE
*Value
985 switch (Value
->Type
) {
986 case EFI_IFR_TYPE_BUFFER
:
987 case EFI_IFR_TYPE_DATE
:
988 case EFI_IFR_TYPE_TIME
:
989 case EFI_IFR_TYPE_REF
:
998 Check whether this value type can be transfer to EFI_IFR_TYPE_UINT64
1000 @param Value Expression value to compare on.
1002 @retval TRUE This value type can be transter to EFI_IFR_TYPE_BUFFER type.
1003 @retval FALSE This value type can't be transter to EFI_IFR_TYPE_BUFFER type.
1008 IN EFI_HII_VALUE
*Value
1011 switch (Value
->Type
) {
1012 case EFI_IFR_TYPE_NUM_SIZE_8
:
1013 case EFI_IFR_TYPE_NUM_SIZE_16
:
1014 case EFI_IFR_TYPE_NUM_SIZE_32
:
1015 case EFI_IFR_TYPE_NUM_SIZE_64
:
1016 case EFI_IFR_TYPE_BOOLEAN
:
1025 Return the buffer length for this value.
1027 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to
1028 EFI_IFR_TYPE_BUFFER when do the value compare.
1030 @param Value Expression value to compare on.
1032 @retval BufLen Return the buffer length.
1037 IN EFI_HII_VALUE
*Value
1040 switch (Value
->Type
) {
1041 case EFI_IFR_TYPE_BUFFER
:
1042 return Value
->BufferLen
;
1044 case EFI_IFR_TYPE_DATE
:
1045 return (UINT16
)sizeof (EFI_HII_DATE
);
1047 case EFI_IFR_TYPE_TIME
:
1048 return (UINT16
)sizeof (EFI_HII_TIME
);
1050 case EFI_IFR_TYPE_REF
:
1051 return (UINT16
)sizeof (EFI_HII_REF
);
1059 Return the buffer pointer for this value.
1061 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to
1062 EFI_IFR_TYPE_BUFFER when do the value compare.
1064 @param Value Expression value to compare on.
1066 @retval Buf Return the buffer pointer.
1071 IN EFI_HII_VALUE
*Value
1074 switch (Value
->Type
) {
1075 case EFI_IFR_TYPE_BUFFER
:
1076 return Value
->Buffer
;
1078 case EFI_IFR_TYPE_DATE
:
1079 return (UINT8
*)(&Value
->Value
.date
);
1081 case EFI_IFR_TYPE_TIME
:
1082 return (UINT8
*)(&Value
->Value
.time
);
1084 case EFI_IFR_TYPE_REF
:
1085 return (UINT8
*)(&Value
->Value
.ref
);
1093 Evaluate opcode EFI_IFR_TO_STRING.
1095 @param FormSet Formset which contains this opcode.
1096 @param Format String format in EFI_IFR_TO_STRING.
1097 @param Result Evaluation result for this opcode.
1099 @retval EFI_SUCCESS Opcode evaluation success.
1100 @retval Other Opcode evaluation failed.
1105 IN FORM_BROWSER_FORMSET
*FormSet
,
1107 OUT EFI_HII_VALUE
*Result
1111 EFI_HII_VALUE Value
;
1113 CHAR16
*PrintFormat
;
1114 CHAR16 Buffer
[MAXIMUM_VALUE_CHARACTERS
];
1120 Status
= PopExpression (&Value
);
1121 if (EFI_ERROR (Status
)) {
1125 switch (Value
.Type
) {
1126 case EFI_IFR_TYPE_NUM_SIZE_8
:
1127 case EFI_IFR_TYPE_NUM_SIZE_16
:
1128 case EFI_IFR_TYPE_NUM_SIZE_32
:
1129 case EFI_IFR_TYPE_NUM_SIZE_64
:
1130 BufferSize
= MAXIMUM_VALUE_CHARACTERS
* sizeof (CHAR16
);
1132 case EFI_IFR_STRING_UNSIGNED_DEC
:
1133 case EFI_IFR_STRING_SIGNED_DEC
:
1134 PrintFormat
= L
"%ld";
1137 case EFI_IFR_STRING_LOWERCASE_HEX
:
1138 PrintFormat
= L
"%lx";
1141 case EFI_IFR_STRING_UPPERCASE_HEX
:
1142 PrintFormat
= L
"%lX";
1146 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1150 UnicodeSPrint (Buffer
, BufferSize
, PrintFormat
, Value
.Value
.u64
);
1154 case EFI_IFR_TYPE_STRING
:
1155 CopyMem (Result
, &Value
, sizeof (EFI_HII_VALUE
));
1158 case EFI_IFR_TYPE_BOOLEAN
:
1159 String
= (Value
.Value
.b
) ? L
"True" : L
"False";
1162 case EFI_IFR_TYPE_BUFFER
:
1163 case EFI_IFR_TYPE_DATE
:
1164 case EFI_IFR_TYPE_TIME
:
1165 case EFI_IFR_TYPE_REF
:
1167 // + 3 is base on the unicode format, the length may be odd number,
1168 // so need 1 byte to align, also need 2 bytes for L'\0'.
1170 if (Value
.Type
== EFI_IFR_TYPE_BUFFER
) {
1171 SrcLen
= Value
.BufferLen
;
1172 SrcBuf
= Value
.Buffer
;
1174 SrcBuf
= GetBufferForValue (&Value
);
1175 SrcLen
= GetLengthForValue (&Value
);
1178 TmpBuf
= AllocateZeroPool (SrcLen
+ 3);
1179 ASSERT (TmpBuf
!= NULL
);
1180 if (Format
== EFI_IFR_STRING_ASCII
) {
1181 CopyMem (TmpBuf
, SrcBuf
, SrcLen
);
1182 PrintFormat
= L
"%a";
1184 // Format == EFI_IFR_STRING_UNICODE
1185 CopyMem (TmpBuf
, SrcBuf
, SrcLen
* sizeof (CHAR16
));
1186 PrintFormat
= L
"%s";
1189 UnicodeSPrint (Buffer
, sizeof (Buffer
), PrintFormat
, TmpBuf
);
1192 if (Value
.Type
== EFI_IFR_TYPE_BUFFER
) {
1193 FreePool (Value
.Buffer
);
1199 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1203 Result
->Type
= EFI_IFR_TYPE_STRING
;
1204 Result
->Value
.string
= NewString (String
, FormSet
->HiiHandle
);
1209 Evaluate opcode EFI_IFR_TO_UINT.
1211 @param FormSet Formset which contains this opcode.
1212 @param Result Evaluation result for this opcode.
1214 @retval EFI_SUCCESS Opcode evaluation success.
1215 @retval Other Opcode evaluation failed.
1220 IN FORM_BROWSER_FORMSET
*FormSet
,
1221 OUT EFI_HII_VALUE
*Result
1225 EFI_HII_VALUE Value
;
1229 Status
= PopExpression (&Value
);
1230 if (EFI_ERROR (Status
)) {
1234 if ((Value
.Type
>= EFI_IFR_TYPE_OTHER
) && !IsTypeInBuffer (&Value
)) {
1235 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1239 Status
= EFI_SUCCESS
;
1240 if (Value
.Type
== EFI_IFR_TYPE_STRING
) {
1241 String
= GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
1242 if (String
== NULL
) {
1243 return EFI_NOT_FOUND
;
1246 IfrStrToUpper (String
);
1247 StringPtr
= StrStr (String
, L
"0X");
1248 if (StringPtr
!= NULL
) {
1252 Result
->Value
.u64
= StrHexToUint64 (String
);
1257 Result
->Value
.u64
= StrDecimalToUint64 (String
);
1261 } else if (IsTypeInBuffer (&Value
)) {
1262 if (GetLengthForValue (&Value
) > 8) {
1263 if (Value
.Type
== EFI_IFR_TYPE_BUFFER
) {
1264 FreePool (Value
.Buffer
);
1267 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1271 ASSERT (GetBufferForValue (&Value
) != NULL
);
1272 Result
->Value
.u64
= *(UINT64
*)GetBufferForValue (&Value
);
1274 if (Value
.Type
== EFI_IFR_TYPE_BUFFER
) {
1275 FreePool (Value
.Buffer
);
1278 CopyMem (Result
, &Value
, sizeof (EFI_HII_VALUE
));
1281 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1286 Evaluate opcode EFI_IFR_CATENATE.
1288 @param FormSet Formset which contains this opcode.
1289 @param Result Evaluation result for this opcode.
1291 @retval EFI_SUCCESS Opcode evaluation success.
1292 @retval Other Opcode evaluation failed.
1297 IN FORM_BROWSER_FORMSET
*FormSet
,
1298 OUT EFI_HII_VALUE
*Result
1302 EFI_HII_VALUE Value
[2];
1313 // String[0] - The second string
1314 // String[1] - The first string
1319 Status
= EFI_SUCCESS
;
1320 ZeroMem (Value
, sizeof (Value
));
1322 Status
= PopExpression (&Value
[0]);
1323 if (EFI_ERROR (Status
)) {
1327 Status
= PopExpression (&Value
[1]);
1328 if (EFI_ERROR (Status
)) {
1332 for (Index
= 0; Index
< 2; Index
++) {
1333 if ((Value
[Index
].Type
!= EFI_IFR_TYPE_STRING
) && !IsTypeInBuffer (&Value
[Index
])) {
1334 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1335 Status
= EFI_SUCCESS
;
1339 if (Value
[Index
].Type
== EFI_IFR_TYPE_STRING
) {
1340 String
[Index
] = GetToken (Value
[Index
].Value
.string
, FormSet
->HiiHandle
);
1341 if (String
[Index
] == NULL
) {
1342 Status
= EFI_NOT_FOUND
;
1348 if (Value
[0].Type
== EFI_IFR_TYPE_STRING
) {
1349 Size
= StrSize (String
[0]);
1350 MaxLen
= (StrSize (String
[1]) + Size
) / sizeof (CHAR16
);
1351 StringPtr
= AllocatePool (MaxLen
* sizeof (CHAR16
));
1352 ASSERT (StringPtr
!= NULL
);
1353 StrCpyS (StringPtr
, MaxLen
, String
[1]);
1354 StrCatS (StringPtr
, MaxLen
, String
[0]);
1356 Result
->Type
= EFI_IFR_TYPE_STRING
;
1357 Result
->Value
.string
= NewString (StringPtr
, FormSet
->HiiHandle
);
1359 Result
->Type
= EFI_IFR_TYPE_BUFFER
;
1360 Length0
= GetLengthForValue (&Value
[0]);
1361 Length1
= GetLengthForValue (&Value
[1]);
1362 Result
->BufferLen
= (UINT16
)(Length0
+ Length1
);
1364 Result
->Buffer
= AllocateZeroPool (Result
->BufferLen
);
1365 ASSERT (Result
->Buffer
!= NULL
);
1367 TmpBuf
= GetBufferForValue (&Value
[0]);
1368 ASSERT (TmpBuf
!= NULL
);
1369 CopyMem (Result
->Buffer
, TmpBuf
, Length0
);
1370 TmpBuf
= GetBufferForValue (&Value
[1]);
1371 ASSERT (TmpBuf
!= NULL
);
1372 CopyMem (&Result
->Buffer
[Length0
], TmpBuf
, Length1
);
1376 if (Value
[0].Buffer
!= NULL
) {
1377 FreePool (Value
[0].Buffer
);
1380 if (Value
[1].Buffer
!= NULL
) {
1381 FreePool (Value
[1].Buffer
);
1384 if (String
[0] != NULL
) {
1385 FreePool (String
[0]);
1388 if (String
[1] != NULL
) {
1389 FreePool (String
[1]);
1392 if (StringPtr
!= NULL
) {
1393 FreePool (StringPtr
);
1400 Evaluate opcode EFI_IFR_MATCH.
1402 @param FormSet Formset which contains this opcode.
1403 @param Result Evaluation result for this opcode.
1405 @retval EFI_SUCCESS Opcode evaluation success.
1406 @retval Other Opcode evaluation failed.
1411 IN FORM_BROWSER_FORMSET
*FormSet
,
1412 OUT EFI_HII_VALUE
*Result
1416 EFI_HII_VALUE Value
[2];
1421 // String[0] - The string to search
1422 // String[1] - pattern
1426 Status
= EFI_SUCCESS
;
1427 ZeroMem (Value
, sizeof (Value
));
1429 Status
= PopExpression (&Value
[0]);
1430 if (EFI_ERROR (Status
)) {
1434 Status
= PopExpression (&Value
[1]);
1435 if (EFI_ERROR (Status
)) {
1439 for (Index
= 0; Index
< 2; Index
++) {
1440 if (Value
[Index
].Type
!= EFI_IFR_TYPE_STRING
) {
1441 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1442 Status
= EFI_SUCCESS
;
1446 String
[Index
] = GetToken (Value
[Index
].Value
.string
, FormSet
->HiiHandle
);
1447 if (String
[Index
] == NULL
) {
1448 Status
= EFI_NOT_FOUND
;
1453 Result
->Type
= EFI_IFR_TYPE_BOOLEAN
;
1454 Result
->Value
.b
= mUnicodeCollation
->MetaiMatch (mUnicodeCollation
, String
[0], String
[1]);
1457 if (String
[0] != NULL
) {
1458 FreePool (String
[0]);
1461 if (String
[1] != NULL
) {
1462 FreePool (String
[1]);
1469 Evaluate opcode EFI_IFR_MATCH2.
1471 @param FormSet Formset which contains this opcode.
1472 @param SyntaxType Syntax type for match2.
1473 @param Result Evaluation result for this opcode.
1475 @retval EFI_SUCCESS Opcode evaluation success.
1476 @retval Other Opcode evaluation failed.
1481 IN FORM_BROWSER_FORMSET
*FormSet
,
1482 IN EFI_GUID
*SyntaxType
,
1483 OUT EFI_HII_VALUE
*Result
1487 EFI_HII_VALUE Value
[2];
1491 EFI_HANDLE
*HandleBuffer
;
1493 EFI_REGULAR_EXPRESSION_PROTOCOL
*RegularExpressionProtocol
;
1494 UINTN RegExSyntaxTypeListSize
;
1495 EFI_REGEX_SYNTAX_TYPE
*RegExSyntaxTypeList
;
1496 UINTN CapturesCount
;
1499 // String[0] - The string to search
1500 // String[1] - pattern
1504 HandleBuffer
= NULL
;
1505 RegExSyntaxTypeList
= NULL
;
1506 Status
= EFI_SUCCESS
;
1507 ZeroMem (Value
, sizeof (Value
));
1509 Status
= PopExpression (&Value
[0]);
1510 if (EFI_ERROR (Status
)) {
1514 Status
= PopExpression (&Value
[1]);
1515 if (EFI_ERROR (Status
)) {
1519 for (Index
= 0; Index
< 2; Index
++) {
1520 if (Value
[Index
].Type
!= EFI_IFR_TYPE_STRING
) {
1521 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1522 Status
= EFI_SUCCESS
;
1526 String
[Index
] = GetToken (Value
[Index
].Value
.string
, FormSet
->HiiHandle
);
1527 if (String
[Index
] == NULL
) {
1528 Status
= EFI_NOT_FOUND
;
1534 HandleBuffer
= NULL
;
1535 Status
= gBS
->LocateHandle (
1537 &gEfiRegularExpressionProtocolGuid
,
1542 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1543 HandleBuffer
= AllocateZeroPool (BufferSize
);
1544 if (HandleBuffer
== NULL
) {
1545 Status
= EFI_OUT_OF_RESOURCES
;
1549 Status
= gBS
->LocateHandle (
1551 &gEfiRegularExpressionProtocolGuid
,
1558 if (EFI_ERROR (Status
)) {
1559 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1560 Status
= EFI_SUCCESS
;
1564 ASSERT (HandleBuffer
!= NULL
);
1565 for ( Index
= 0; Index
< BufferSize
/ sizeof (EFI_HANDLE
); Index
++) {
1566 Status
= gBS
->HandleProtocol (
1567 HandleBuffer
[Index
],
1568 &gEfiRegularExpressionProtocolGuid
,
1569 (VOID
**)&RegularExpressionProtocol
1571 if (EFI_ERROR (Status
)) {
1575 RegExSyntaxTypeListSize
= 0;
1576 RegExSyntaxTypeList
= NULL
;
1578 Status
= RegularExpressionProtocol
->GetInfo (
1579 RegularExpressionProtocol
,
1580 &RegExSyntaxTypeListSize
,
1583 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1584 RegExSyntaxTypeList
= AllocateZeroPool (RegExSyntaxTypeListSize
);
1585 if (RegExSyntaxTypeList
== NULL
) {
1586 Status
= EFI_OUT_OF_RESOURCES
;
1590 Status
= RegularExpressionProtocol
->GetInfo (
1591 RegularExpressionProtocol
,
1592 &RegExSyntaxTypeListSize
,
1595 } else if (EFI_ERROR (Status
)) {
1599 for (GuidIndex
= 0; GuidIndex
< RegExSyntaxTypeListSize
/ sizeof (EFI_GUID
); GuidIndex
++) {
1600 if (CompareGuid (&RegExSyntaxTypeList
[GuidIndex
], SyntaxType
)) {
1602 // Find the match type, return the value.
1604 Result
->Type
= EFI_IFR_TYPE_BOOLEAN
;
1605 Status
= RegularExpressionProtocol
->MatchString (
1606 RegularExpressionProtocol
,
1618 if (RegExSyntaxTypeList
!= NULL
) {
1619 FreePool (RegExSyntaxTypeList
);
1624 // Type specified by SyntaxType is not supported
1625 // in any of the EFI_REGULAR_EXPRESSION_PROTOCOL instances.
1627 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1628 Status
= EFI_SUCCESS
;
1631 if (String
[0] != NULL
) {
1632 FreePool (String
[0]);
1635 if (String
[1] != NULL
) {
1636 FreePool (String
[1]);
1639 if (RegExSyntaxTypeList
!= NULL
) {
1640 FreePool (RegExSyntaxTypeList
);
1643 if (HandleBuffer
!= NULL
) {
1644 FreePool (HandleBuffer
);
1651 Evaluate opcode EFI_IFR_FIND.
1653 @param FormSet Formset which contains this opcode.
1654 @param Format Case sensitive or insensitive.
1655 @param Result Evaluation result for this opcode.
1657 @retval EFI_SUCCESS Opcode evaluation success.
1658 @retval Other Opcode evaluation failed.
1663 IN FORM_BROWSER_FORMSET
*FormSet
,
1665 OUT EFI_HII_VALUE
*Result
1669 EFI_HII_VALUE Value
[3];
1675 ZeroMem (Value
, sizeof (Value
));
1677 if (Format
> EFI_IFR_FF_CASE_INSENSITIVE
) {
1678 return EFI_INVALID_PARAMETER
;
1681 Status
= PopExpression (&Value
[0]);
1682 if (EFI_ERROR (Status
)) {
1686 Status
= PopExpression (&Value
[1]);
1687 if (EFI_ERROR (Status
)) {
1691 Status
= PopExpression (&Value
[2]);
1692 if (EFI_ERROR (Status
)) {
1696 if (Value
[0].Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1697 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1701 Base
= (UINTN
)Value
[0].Value
.u64
;
1704 // String[0] - sub-string
1705 // String[1] - The string to search
1709 for (Index
= 0; Index
< 2; Index
++) {
1710 if (Value
[Index
+ 1].Type
!= EFI_IFR_TYPE_STRING
) {
1711 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1712 Status
= EFI_SUCCESS
;
1716 String
[Index
] = GetToken (Value
[Index
+ 1].Value
.string
, FormSet
->HiiHandle
);
1717 if (String
[Index
] == NULL
) {
1718 Status
= EFI_NOT_FOUND
;
1722 if (Format
== EFI_IFR_FF_CASE_INSENSITIVE
) {
1724 // Case insensitive, convert both string to upper case
1726 IfrStrToUpper (String
[Index
]);
1730 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1731 if (Base
>= StrLen (String
[1])) {
1732 Result
->Value
.u64
= 0xFFFFFFFFFFFFFFFFULL
;
1734 StringPtr
= StrStr (String
[1] + Base
, String
[0]);
1735 Result
->Value
.u64
= (StringPtr
== NULL
) ? 0xFFFFFFFFFFFFFFFFULL
: (StringPtr
- String
[1]);
1739 if (String
[0] != NULL
) {
1740 FreePool (String
[0]);
1743 if (String
[1] != NULL
) {
1744 FreePool (String
[1]);
1751 Evaluate opcode EFI_IFR_MID.
1753 @param FormSet Formset which contains this opcode.
1754 @param Result Evaluation result for this opcode.
1756 @retval EFI_SUCCESS Opcode evaluation success.
1757 @retval Other Opcode evaluation failed.
1762 IN FORM_BROWSER_FORMSET
*FormSet
,
1763 OUT EFI_HII_VALUE
*Result
1767 EFI_HII_VALUE Value
[3];
1775 ZeroMem (Value
, sizeof (Value
));
1777 Status
= PopExpression (&Value
[0]);
1778 if (EFI_ERROR (Status
)) {
1782 Status
= PopExpression (&Value
[1]);
1783 if (EFI_ERROR (Status
)) {
1787 Status
= PopExpression (&Value
[2]);
1788 if (EFI_ERROR (Status
)) {
1792 if (Value
[0].Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1793 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1797 Length
= (UINTN
)Value
[0].Value
.u64
;
1799 if (Value
[1].Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1800 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1804 Base
= (UINTN
)Value
[1].Value
.u64
;
1806 if ((Value
[2].Type
!= EFI_IFR_TYPE_STRING
) && !IsTypeInBuffer (&Value
[2])) {
1807 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1811 if (Value
[2].Type
== EFI_IFR_TYPE_STRING
) {
1812 String
= GetToken (Value
[2].Value
.string
, FormSet
->HiiHandle
);
1813 if (String
== NULL
) {
1814 return EFI_NOT_FOUND
;
1817 if ((Length
== 0) || (Base
>= StrLen (String
))) {
1818 SubString
= gEmptyString
;
1820 SubString
= String
+ Base
;
1821 if ((Base
+ Length
) < StrLen (String
)) {
1822 SubString
[Length
] = L
'\0';
1826 Result
->Type
= EFI_IFR_TYPE_STRING
;
1827 Result
->Value
.string
= NewString (SubString
, FormSet
->HiiHandle
);
1831 BufferLen
= GetLengthForValue (&Value
[2]);
1832 Buffer
= GetBufferForValue (&Value
[2]);
1834 Result
->Type
= EFI_IFR_TYPE_BUFFER
;
1835 if ((Length
== 0) || (Base
>= BufferLen
)) {
1836 Result
->BufferLen
= 0;
1837 Result
->Buffer
= NULL
;
1839 Result
->BufferLen
= (UINT16
)((BufferLen
- Base
) < Length
? (BufferLen
- Base
) : Length
);
1840 Result
->Buffer
= AllocateZeroPool (Result
->BufferLen
);
1841 ASSERT (Result
->Buffer
!= NULL
);
1842 CopyMem (Result
->Buffer
, &Buffer
[Base
], Result
->BufferLen
);
1845 if (Value
[2].Type
== EFI_IFR_TYPE_BUFFER
) {
1846 FreePool (Value
[2].Buffer
);
1854 Evaluate opcode EFI_IFR_TOKEN.
1856 @param FormSet Formset which contains this opcode.
1857 @param Result Evaluation result for this opcode.
1859 @retval EFI_SUCCESS Opcode evaluation success.
1860 @retval Other Opcode evaluation failed.
1865 IN FORM_BROWSER_FORMSET
*FormSet
,
1866 OUT EFI_HII_VALUE
*Result
1870 EFI_HII_VALUE Value
[3];
1878 ZeroMem (Value
, sizeof (Value
));
1880 Status
= PopExpression (&Value
[0]);
1881 if (EFI_ERROR (Status
)) {
1885 Status
= PopExpression (&Value
[1]);
1886 if (EFI_ERROR (Status
)) {
1890 Status
= PopExpression (&Value
[2]);
1891 if (EFI_ERROR (Status
)) {
1895 if (Value
[0].Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1896 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1900 Count
= (UINTN
)Value
[0].Value
.u64
;
1903 // String[0] - Delimiter
1904 // String[1] - The string to search
1908 for (Index
= 0; Index
< 2; Index
++) {
1909 if (Value
[Index
+ 1].Type
!= EFI_IFR_TYPE_STRING
) {
1910 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1911 Status
= EFI_SUCCESS
;
1915 String
[Index
] = GetToken (Value
[Index
+ 1].Value
.string
, FormSet
->HiiHandle
);
1916 if (String
[Index
] == NULL
) {
1917 Status
= EFI_NOT_FOUND
;
1922 Delimiter
= String
[0];
1923 SubString
= String
[1];
1925 SubString
= StrStr (SubString
, Delimiter
);
1926 if (SubString
!= NULL
) {
1928 // Skip over the delimiter
1930 SubString
= SubString
+ StrLen (Delimiter
);
1938 if (SubString
== NULL
) {
1940 // nth delimited sub-string not found, push an empty string
1942 SubString
= gEmptyString
;
1945 // Put a NULL terminator for nth delimited sub-string
1947 StringPtr
= StrStr (SubString
, Delimiter
);
1948 if (StringPtr
!= NULL
) {
1953 Result
->Type
= EFI_IFR_TYPE_STRING
;
1954 Result
->Value
.string
= NewString (SubString
, FormSet
->HiiHandle
);
1957 if (String
[0] != NULL
) {
1958 FreePool (String
[0]);
1961 if (String
[1] != NULL
) {
1962 FreePool (String
[1]);
1969 Evaluate opcode EFI_IFR_SPAN.
1971 @param FormSet Formset which contains this opcode.
1972 @param Flags FIRST_MATCHING or FIRST_NON_MATCHING.
1973 @param Result Evaluation result for this opcode.
1975 @retval EFI_SUCCESS Opcode evaluation success.
1976 @retval Other Opcode evaluation failed.
1981 IN FORM_BROWSER_FORMSET
*FormSet
,
1983 OUT EFI_HII_VALUE
*Result
1987 EFI_HII_VALUE Value
[3];
1995 ZeroMem (Value
, sizeof (Value
));
1997 Status
= PopExpression (&Value
[0]);
1998 if (EFI_ERROR (Status
)) {
2002 Status
= PopExpression (&Value
[1]);
2003 if (EFI_ERROR (Status
)) {
2007 Status
= PopExpression (&Value
[2]);
2008 if (EFI_ERROR (Status
)) {
2012 if (Value
[0].Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
2013 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
) {
2064 // Skip characters pair representing low-end of a range and high-end of a range
2074 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
2075 Result
->Value
.u64
= StringPtr
- String
[1];
2078 if (String
[0] != NULL
) {
2079 FreePool (String
[0]);
2082 if (String
[1] != NULL
) {
2083 FreePool (String
[1]);
2090 Zero extend integer/boolean/date/time to UINT64 for comparing.
2092 @param Value HII Value to be converted.
2097 IN EFI_HII_VALUE
*Value
2103 switch (Value
->Type
) {
2104 case EFI_IFR_TYPE_NUM_SIZE_8
:
2105 Temp
= Value
->Value
.u8
;
2108 case EFI_IFR_TYPE_NUM_SIZE_16
:
2109 Temp
= Value
->Value
.u16
;
2112 case EFI_IFR_TYPE_NUM_SIZE_32
:
2113 Temp
= Value
->Value
.u32
;
2116 case EFI_IFR_TYPE_BOOLEAN
:
2117 Temp
= Value
->Value
.b
;
2120 case EFI_IFR_TYPE_TIME
:
2121 Temp
= Value
->Value
.u32
& 0xffffff;
2124 case EFI_IFR_TYPE_DATE
:
2125 Temp
= Value
->Value
.u32
;
2132 Value
->Value
.u64
= Temp
;
2136 Get UINT64 type value.
2138 @param Value Input Hii value.
2140 @retval UINT64 Return the UINT64 type value.
2145 IN EFI_HII_VALUE
*Value
2152 switch (Value
->Type
) {
2153 case EFI_IFR_TYPE_NUM_SIZE_8
:
2154 RetVal
= Value
->Value
.u8
;
2157 case EFI_IFR_TYPE_NUM_SIZE_16
:
2158 RetVal
= Value
->Value
.u16
;
2161 case EFI_IFR_TYPE_NUM_SIZE_32
:
2162 RetVal
= Value
->Value
.u32
;
2165 case EFI_IFR_TYPE_BOOLEAN
:
2166 RetVal
= Value
->Value
.b
;
2169 case EFI_IFR_TYPE_DATE
:
2170 RetVal
= *(UINT64
*)&Value
->Value
.date
;
2173 case EFI_IFR_TYPE_TIME
:
2174 RetVal
= (*(UINT64
*)&Value
->Value
.time
) & 0xffffff;
2178 RetVal
= Value
->Value
.u64
;
2186 Compare two Hii value.
2188 @param Value1 Expression value to compare on left-hand.
2189 @param Value2 Expression value to compare on right-hand.
2190 @param Result Return value after compare.
2191 retval 0 Two operators equal.
2192 return Positive value if Value1 is greater than Value2.
2193 retval Negative value if Value1 is less than Value2.
2194 @param HiiHandle Only required for string compare.
2196 @retval other Could not perform compare on two values.
2197 @retval EFI_SUCCESS Compare the value success.
2202 IN EFI_HII_VALUE
*Value1
,
2203 IN EFI_HII_VALUE
*Value2
,
2205 IN EFI_HII_HANDLE HiiHandle OPTIONAL
2217 if ((Value1
->Type
== EFI_IFR_TYPE_STRING
) && (Value2
->Type
== EFI_IFR_TYPE_STRING
)) {
2218 if ((Value1
->Value
.string
== 0) || (Value2
->Value
.string
== 0)) {
2220 // StringId 0 is reserved
2222 return EFI_INVALID_PARAMETER
;
2225 if (Value1
->Value
.string
== Value2
->Value
.string
) {
2230 Str1
= GetToken (Value1
->Value
.string
, HiiHandle
);
2235 return EFI_NOT_FOUND
;
2238 Str2
= GetToken (Value2
->Value
.string
, HiiHandle
);
2241 return EFI_NOT_FOUND
;
2244 *Result
= StrCmp (Str1
, Str2
);
2253 // Take types(date, time, ref, buffer) as buffer
2255 if (IsTypeInBuffer (Value1
) && IsTypeInBuffer (Value2
)) {
2256 Buf1
= GetBufferForValue (Value1
);
2257 Buf1Len
= GetLengthForValue (Value1
);
2258 Buf2
= GetBufferForValue (Value2
);
2259 Buf2Len
= GetLengthForValue (Value2
);
2261 Len
= Buf1Len
> Buf2Len
? Buf2Len
: Buf1Len
;
2262 *Result
= CompareMem (Buf1
, Buf2
, Len
);
2263 if ((*Result
== 0) && (Buf1Len
!= Buf2Len
)) {
2265 // In this case, means base on samll number buffer, the data is same
2266 // So which value has more data, which value is bigger.
2268 *Result
= Buf1Len
> Buf2Len
? 1 : -1;
2275 // Take types(integer, boolean) as integer
2277 if (IsTypeInUINT64 (Value1
) && IsTypeInUINT64 (Value2
)) {
2278 Temp64
= HiiValueToUINT64 (Value1
) - HiiValueToUINT64 (Value2
);
2281 } else if (Temp64
< 0) {
2290 return EFI_UNSUPPORTED
;
2294 Check if current user has the privilege specified by the permissions GUID.
2296 @param[in] Guid A GUID specifying setup access permissions.
2298 @retval TRUE Current user has the privilege.
2299 @retval FALSE Current user does not have the privilege.
2302 CheckUserPrivilege (
2307 EFI_USER_PROFILE_HANDLE UserProfileHandle
;
2308 EFI_USER_INFO_HANDLE UserInfoHandle
;
2309 EFI_USER_INFO
*UserInfo
;
2310 EFI_GUID
*UserPermissionsGuid
;
2312 UINTN AccessControlDataSize
;
2313 EFI_USER_INFO_ACCESS_CONTROL
*AccessControl
;
2316 if (mUserManager
== NULL
) {
2317 Status
= gBS
->LocateProtocol (
2318 &gEfiUserManagerProtocolGuid
,
2320 (VOID
**)&mUserManager
2322 if (EFI_ERROR (Status
)) {
2324 /// If the system does not support user management, then it is assumed that
2325 /// all users have admin privilege and evaluation of each EFI_IFR_SECURITY
2326 /// op-code is always TRUE.
2332 Status
= mUserManager
->Current (mUserManager
, &UserProfileHandle
);
2333 ASSERT_EFI_ERROR (Status
);
2336 /// Enumerate all user information of the current user profile
2337 /// to look for any EFI_USER_INFO_ACCESS_SETUP record.
2340 for (UserInfoHandle
= NULL
; ;) {
2341 Status
= mUserManager
->GetNextInfo (mUserManager
, UserProfileHandle
, &UserInfoHandle
);
2342 if (EFI_ERROR (Status
)) {
2347 Status
= mUserManager
->GetInfo (mUserManager
, UserProfileHandle
, UserInfoHandle
, NULL
, &UserInfoSize
);
2348 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
2352 UserInfo
= (EFI_USER_INFO
*)AllocatePool (UserInfoSize
);
2353 if (UserInfo
== NULL
) {
2357 Status
= mUserManager
->GetInfo (mUserManager
, UserProfileHandle
, UserInfoHandle
, UserInfo
, &UserInfoSize
);
2358 if (EFI_ERROR (Status
) ||
2359 (UserInfo
->InfoType
!= EFI_USER_INFO_ACCESS_POLICY_RECORD
) ||
2360 (UserInfo
->InfoSize
<= sizeof (EFI_USER_INFO
)))
2362 FreePool (UserInfo
);
2366 RemainSize
= UserInfo
->InfoSize
- sizeof (EFI_USER_INFO
);
2367 AccessControl
= (EFI_USER_INFO_ACCESS_CONTROL
*)(UserInfo
+ 1);
2368 while (RemainSize
>= sizeof (EFI_USER_INFO_ACCESS_CONTROL
)) {
2369 if ((RemainSize
< AccessControl
->Size
) || (AccessControl
->Size
< sizeof (EFI_USER_INFO_ACCESS_CONTROL
))) {
2373 if (AccessControl
->Type
== EFI_USER_INFO_ACCESS_SETUP
) {
2375 /// Check if current user has the privilege specified by the permissions GUID.
2378 UserPermissionsGuid
= (EFI_GUID
*)(AccessControl
+ 1);
2379 AccessControlDataSize
= AccessControl
->Size
- sizeof (EFI_USER_INFO_ACCESS_CONTROL
);
2380 while (AccessControlDataSize
>= sizeof (EFI_GUID
)) {
2381 if (CompareGuid (Guid
, UserPermissionsGuid
)) {
2382 FreePool (UserInfo
);
2386 UserPermissionsGuid
++;
2387 AccessControlDataSize
-= sizeof (EFI_GUID
);
2391 RemainSize
-= AccessControl
->Size
;
2392 AccessControl
= (EFI_USER_INFO_ACCESS_CONTROL
*)((UINT8
*)AccessControl
+ AccessControl
->Size
);
2395 FreePool (UserInfo
);
2402 Get question value from the predefined formset.
2404 @param DevicePath The driver's device path which produece the formset data.
2405 @param InputHiiHandle The hii handle associate with the formset data.
2406 @param FormSetGuid The formset guid which include the question.
2407 @param QuestionId The question id which need to get value from.
2408 @param Value The return data about question's value.
2410 @retval TRUE Get the question value success.
2411 @retval FALSE Get the question value failed.
2414 GetQuestionValueFromForm (
2415 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
2416 IN EFI_HII_HANDLE InputHiiHandle
,
2417 IN EFI_GUID
*FormSetGuid
,
2418 IN EFI_QUESTION_ID QuestionId
,
2419 OUT EFI_HII_VALUE
*Value
2423 EFI_HII_HANDLE HiiHandle
;
2424 FORM_BROWSER_STATEMENT
*Question
;
2425 FORM_BROWSER_FORMSET
*FormSet
;
2426 FORM_BROWSER_FORM
*Form
;
2431 // The input parameter DevicePath or InputHiiHandle must have one valid input.
2434 (DevicePath
!= NULL
&& InputHiiHandle
== NULL
) ||
2435 (DevicePath
== NULL
&& InputHiiHandle
!= NULL
)
2446 if (DevicePath
!= NULL
) {
2447 HiiHandle
= DevicePathToHiiHandle (DevicePath
, FormSetGuid
);
2448 if (HiiHandle
== NULL
) {
2452 HiiHandle
= InputHiiHandle
;
2455 ASSERT (HiiHandle
!= NULL
);
2458 // Get the formset data include this question.
2460 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
2461 ASSERT (FormSet
!= NULL
);
2462 Status
= InitializeFormSet (HiiHandle
, FormSetGuid
, FormSet
);
2463 if (EFI_ERROR (Status
)) {
2469 // Base on the Question Id to get the question info.
2471 Question
= IdToQuestion (FormSet
, NULL
, QuestionId
);
2472 if (Question
== NULL
) {
2478 // Search form in the formset scope
2480 Link
= GetFirstNode (&FormSet
->FormListHead
);
2481 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2482 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2484 Question
= IdToQuestion2 (Form
, QuestionId
);
2485 if (Question
!= NULL
) {
2489 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2493 ASSERT (Form
!= NULL
);
2496 // Get the question value.
2498 Status
= GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
2499 if (EFI_ERROR (Status
)) {
2504 CopyMem (Value
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
2508 // Clean the formset structure and restore the global parameter.
2510 if (FormSet
!= NULL
) {
2511 DestroyFormSet (FormSet
);
2518 Evaluate the result of a HII expression.
2520 If Expression is NULL, then ASSERT.
2522 @param FormSet FormSet associated with this expression.
2523 @param Form Form associated with this expression.
2524 @param Expression Expression to be evaluated.
2526 @retval EFI_SUCCESS The expression evaluated successfuly
2527 @retval EFI_NOT_FOUND The Question which referenced by a QuestionId
2529 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
2531 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
2532 @retval EFI_INVALID_PARAMETER Syntax error with the Expression
2536 EvaluateExpression (
2537 IN FORM_BROWSER_FORMSET
*FormSet
,
2538 IN FORM_BROWSER_FORM
*Form
,
2539 IN OUT FORM_EXPRESSION
*Expression
2544 EXPRESSION_OPCODE
*OpCode
;
2545 FORM_BROWSER_STATEMENT
*Question
;
2546 FORM_BROWSER_STATEMENT
*Question2
;
2548 EFI_HII_VALUE Data1
;
2549 EFI_HII_VALUE Data2
;
2550 EFI_HII_VALUE Data3
;
2551 FORM_EXPRESSION
*RuleExpression
;
2552 EFI_HII_VALUE
*Value
;
2557 LIST_ENTRY
*SubExpressionLink
;
2558 FORM_EXPRESSION
*SubExpression
;
2565 EFI_HII_VALUE QuestionVal
;
2566 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2571 // Save current stack offset.
2573 StackOffset
= SaveExpressionEvaluationStackOffset ();
2575 ASSERT (Expression
!= NULL
);
2576 Expression
->Result
.Type
= EFI_IFR_TYPE_OTHER
;
2578 Link
= GetFirstNode (&Expression
->OpCodeListHead
);
2579 while (!IsNull (&Expression
->OpCodeListHead
, Link
)) {
2580 OpCode
= EXPRESSION_OPCODE_FROM_LINK (Link
);
2582 Link
= GetNextNode (&Expression
->OpCodeListHead
, Link
);
2584 ZeroMem (&Data1
, sizeof (EFI_HII_VALUE
));
2585 ZeroMem (&Data2
, sizeof (EFI_HII_VALUE
));
2586 ZeroMem (&Data3
, sizeof (EFI_HII_VALUE
));
2589 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
2590 Status
= EFI_SUCCESS
;
2592 switch (OpCode
->Operand
) {
2594 // Built-in functions
2596 case EFI_IFR_EQ_ID_VAL_OP
:
2597 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
2598 if (Question
== NULL
) {
2599 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2603 Status
= CompareHiiValue (&Question
->HiiValue
, &OpCode
->Value
, &Result
, NULL
);
2604 if (Status
== EFI_UNSUPPORTED
) {
2605 Status
= EFI_SUCCESS
;
2606 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2610 if (EFI_ERROR (Status
)) {
2614 Value
->Value
.b
= (BOOLEAN
)((Result
== 0) ? TRUE
: FALSE
);
2617 case EFI_IFR_EQ_ID_ID_OP
:
2618 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
2619 if (Question
== NULL
) {
2620 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2624 Question2
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId2
);
2625 if (Question2
== NULL
) {
2626 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2630 Status
= CompareHiiValue (&Question
->HiiValue
, &Question2
->HiiValue
, &Result
, FormSet
->HiiHandle
);
2631 if (Status
== EFI_UNSUPPORTED
) {
2632 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2633 Status
= EFI_SUCCESS
;
2637 if (EFI_ERROR (Status
)) {
2641 Value
->Value
.b
= (BOOLEAN
)((Result
== 0) ? TRUE
: FALSE
);
2644 case EFI_IFR_EQ_ID_VAL_LIST_OP
:
2645 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
2646 if (Question
== NULL
) {
2647 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2651 Value
->Value
.b
= FALSE
;
2652 for (Index
= 0; Index
< OpCode
->ListLength
; Index
++) {
2653 if (Question
->HiiValue
.Value
.u16
== OpCode
->ValueList
[Index
]) {
2654 Value
->Value
.b
= TRUE
;
2661 case EFI_IFR_DUP_OP
:
2662 Status
= PopExpression (Value
);
2663 if (EFI_ERROR (Status
)) {
2667 Status
= PushExpression (Value
);
2670 case EFI_IFR_QUESTION_REF1_OP
:
2671 case EFI_IFR_THIS_OP
:
2672 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
2673 if (Question
== NULL
) {
2674 Status
= EFI_NOT_FOUND
;
2678 Value
= &Question
->HiiValue
;
2681 case EFI_IFR_SECURITY_OP
:
2682 Value
->Value
.b
= CheckUserPrivilege (&OpCode
->Guid
);
2685 case EFI_IFR_GET_OP
:
2687 // Get Value from VarStore buffer, EFI VarStore, Name/Value VarStore.
2689 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2690 Value
->Value
.u8
= 0;
2691 if (OpCode
->VarStorage
!= NULL
) {
2692 switch (OpCode
->VarStorage
->Type
) {
2693 case EFI_HII_VARSTORE_BUFFER
:
2694 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
2696 // Get value from Edit Buffer
2698 Value
->Type
= OpCode
->ValueType
;
2699 CopyMem (&Value
->Value
, OpCode
->VarStorage
->EditBuffer
+ OpCode
->VarStoreInfo
.VarOffset
, OpCode
->ValueWidth
);
2701 case EFI_HII_VARSTORE_NAME_VALUE
:
2702 if (OpCode
->ValueType
!= EFI_IFR_TYPE_STRING
) {
2704 // Get value from string except for STRING value.
2706 Status
= GetValueByName (OpCode
->VarStorage
, OpCode
->ValueName
, &StrPtr
, GetSetValueWithEditBuffer
);
2707 if (!EFI_ERROR (Status
)) {
2708 ASSERT (StrPtr
!= NULL
);
2709 TempLength
= StrLen (StrPtr
);
2710 if (OpCode
->ValueWidth
>= ((TempLength
+ 1) / 2)) {
2711 Value
->Type
= OpCode
->ValueType
;
2712 TempBuffer
= (UINT8
*)&Value
->Value
;
2713 ZeroMem (TempStr
, sizeof (TempStr
));
2714 for (Index
= 0; Index
< TempLength
; Index
++) {
2715 TempStr
[0] = StrPtr
[TempLength
- Index
- 1];
2716 DigitUint8
= (UINT8
)StrHexToUint64 (TempStr
);
2717 if ((Index
& 1) == 0) {
2718 TempBuffer
[Index
/2] = DigitUint8
;
2720 TempBuffer
[Index
/2] = (UINT8
)((DigitUint8
<< 4) + TempBuffer
[Index
/2]);
2728 case EFI_HII_VARSTORE_EFI_VARIABLE
:
2730 // Get value from variable.
2732 TempLength
= OpCode
->ValueWidth
;
2733 Value
->Type
= OpCode
->ValueType
;
2734 Status
= gRT
->GetVariable (
2736 &OpCode
->VarStorage
->Guid
,
2741 if (EFI_ERROR (Status
)) {
2742 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2743 Value
->Value
.u8
= 0;
2749 // Not recognize storage.
2751 Status
= EFI_UNSUPPORTED
;
2756 // For Time/Date Data
2758 if ((OpCode
->ValueType
!= EFI_IFR_TYPE_DATE
) && (OpCode
->ValueType
!= EFI_IFR_TYPE_TIME
)) {
2760 // Only support Data/Time data when storage doesn't exist.
2762 Status
= EFI_UNSUPPORTED
;
2766 Status
= gRT
->GetTime (&EfiTime
, NULL
);
2767 if (!EFI_ERROR (Status
)) {
2768 if (OpCode
->ValueType
== EFI_IFR_TYPE_DATE
) {
2769 switch (OpCode
->VarStoreInfo
.VarOffset
) {
2771 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_16
;
2772 Value
->Value
.u16
= EfiTime
.Year
;
2775 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
2776 Value
->Value
.u8
= EfiTime
.Month
;
2779 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
2780 Value
->Value
.u8
= EfiTime
.Day
;
2784 // Invalid Date field.
2786 Status
= EFI_INVALID_PARAMETER
;
2790 switch (OpCode
->VarStoreInfo
.VarOffset
) {
2792 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
2793 Value
->Value
.u8
= EfiTime
.Hour
;
2796 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
2797 Value
->Value
.u8
= EfiTime
.Minute
;
2800 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
2801 Value
->Value
.u8
= EfiTime
.Second
;
2805 // Invalid Time field.
2807 Status
= EFI_INVALID_PARAMETER
;
2816 case EFI_IFR_QUESTION_REF3_OP
:
2818 // EFI_IFR_QUESTION_REF3
2819 // Pop an expression from the expression stack
2821 Status
= PopExpression (Value
);
2822 if (EFI_ERROR (Status
)) {
2827 // Validate the expression value
2829 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
2830 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2834 if (OpCode
->DevicePath
!= 0) {
2835 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2837 StrPtr
= GetToken (OpCode
->DevicePath
, FormSet
->HiiHandle
);
2838 if ((StrPtr
!= NULL
) && (mPathFromText
!= NULL
)) {
2839 DevicePath
= mPathFromText
->ConvertTextToDevicePath (StrPtr
);
2840 if ((DevicePath
!= NULL
) && GetQuestionValueFromForm (DevicePath
, NULL
, &OpCode
->Guid
, Value
->Value
.u16
, &QuestionVal
)) {
2841 Value
= &QuestionVal
;
2844 if (DevicePath
!= NULL
) {
2845 FreePool (DevicePath
);
2849 if (StrPtr
!= NULL
) {
2852 } else if (IsZeroGuid (&OpCode
->Guid
)) {
2853 if (!GetQuestionValueFromForm (NULL
, FormSet
->HiiHandle
, &OpCode
->Guid
, Value
->Value
.u16
, &QuestionVal
)) {
2854 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2858 Value
= &QuestionVal
;
2860 Question
= IdToQuestion (FormSet
, Form
, Value
->Value
.u16
);
2861 if (Question
== NULL
) {
2862 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2867 // push the questions' value on to the expression stack
2869 Value
= &Question
->HiiValue
;
2874 case EFI_IFR_RULE_REF_OP
:
2876 // Find expression for this rule
2878 RuleExpression
= RuleIdToExpression (Form
, OpCode
->RuleId
);
2879 if (RuleExpression
== NULL
) {
2880 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2885 // Evaluate this rule expression
2887 Status
= EvaluateExpression (FormSet
, Form
, RuleExpression
);
2888 if (EFI_ERROR (Status
) || (RuleExpression
->Result
.Type
== EFI_IFR_TYPE_UNDEFINED
)) {
2889 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2893 Value
= &RuleExpression
->Result
;
2896 case EFI_IFR_STRING_REF1_OP
:
2897 Value
->Type
= EFI_IFR_TYPE_STRING
;
2898 Value
->Value
.string
= OpCode
->Value
.Value
.string
;
2904 case EFI_IFR_TRUE_OP
:
2905 case EFI_IFR_FALSE_OP
:
2906 case EFI_IFR_ONE_OP
:
2907 case EFI_IFR_ONES_OP
:
2908 case EFI_IFR_UINT8_OP
:
2909 case EFI_IFR_UINT16_OP
:
2910 case EFI_IFR_UINT32_OP
:
2911 case EFI_IFR_UINT64_OP
:
2912 case EFI_IFR_UNDEFINED_OP
:
2913 case EFI_IFR_VERSION_OP
:
2914 case EFI_IFR_ZERO_OP
:
2915 Value
= &OpCode
->Value
;
2921 case EFI_IFR_LENGTH_OP
:
2922 Status
= PopExpression (Value
);
2923 if (EFI_ERROR (Status
)) {
2927 if ((Value
->Type
!= EFI_IFR_TYPE_STRING
) && !IsTypeInBuffer (Value
)) {
2928 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2932 if (Value
->Type
== EFI_IFR_TYPE_STRING
) {
2933 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->HiiHandle
);
2934 if (StrPtr
== NULL
) {
2935 Status
= EFI_INVALID_PARAMETER
;
2939 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
2940 Value
->Value
.u64
= StrLen (StrPtr
);
2943 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
2944 Value
->Value
.u64
= GetLengthForValue (Value
);
2945 FreePool (Value
->Buffer
);
2950 case EFI_IFR_NOT_OP
:
2951 Status
= PopExpression (Value
);
2952 if (EFI_ERROR (Status
)) {
2956 if (Value
->Type
!= EFI_IFR_TYPE_BOOLEAN
) {
2957 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2961 Value
->Value
.b
= (BOOLEAN
)(!Value
->Value
.b
);
2964 case EFI_IFR_QUESTION_REF2_OP
:
2966 // Pop an expression from the expression stack
2968 Status
= PopExpression (Value
);
2969 if (EFI_ERROR (Status
)) {
2974 // Validate the expression value
2976 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
2977 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2981 Question
= IdToQuestion (FormSet
, Form
, Value
->Value
.u16
);
2982 if (Question
== NULL
) {
2983 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2987 Value
= &Question
->HiiValue
;
2990 case EFI_IFR_STRING_REF2_OP
:
2992 // Pop an expression from the expression stack
2994 Status
= PopExpression (Value
);
2995 if (EFI_ERROR (Status
)) {
3000 // Validate the expression value
3002 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
3003 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3007 Value
->Type
= EFI_IFR_TYPE_STRING
;
3008 StrPtr
= GetToken (Value
->Value
.u16
, FormSet
->HiiHandle
);
3009 if (StrPtr
== NULL
) {
3011 // If String not exit, push an empty string
3013 Value
->Value
.string
= NewString (gEmptyString
, FormSet
->HiiHandle
);
3015 Index
= (UINT16
)Value
->Value
.u64
;
3016 Value
->Value
.string
= Index
;
3022 case EFI_IFR_TO_BOOLEAN_OP
:
3024 // Pop an expression from the expression stack
3026 Status
= PopExpression (Value
);
3027 if (EFI_ERROR (Status
)) {
3032 // Convert an expression to a Boolean
3034 if (Value
->Type
<= EFI_IFR_TYPE_DATE
) {
3036 // When converting from an unsigned integer, zero will be converted to
3037 // FALSE and any other value will be converted to TRUE.
3039 Value
->Value
.b
= (BOOLEAN
)(HiiValueToUINT64 (Value
) != 0);
3041 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
3042 } else if (Value
->Type
== EFI_IFR_TYPE_STRING
) {
3044 // When converting from a string, if case-insensitive compare
3045 // with "true" is True, then push True. If a case-insensitive compare
3046 // with "false" is True, then push False. Otherwise, push Undefined.
3048 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->HiiHandle
);
3049 if (StrPtr
== NULL
) {
3050 Status
= EFI_INVALID_PARAMETER
;
3054 IfrStrToUpper (StrPtr
);
3055 if (StrCmp (StrPtr
, L
"TRUE") == 0) {
3056 Value
->Value
.b
= TRUE
;
3057 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
3058 } else if (StrCmp (StrPtr
, L
"FALSE") == 0) {
3059 Value
->Value
.b
= FALSE
;
3060 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
3062 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3066 } else if (Value
->Type
== EFI_IFR_TYPE_BUFFER
) {
3068 // When converting from a buffer, if the buffer is all zeroes,
3069 // then push False. Otherwise push True.
3071 for (Index
= 0; Index
< Value
->BufferLen
; Index
++) {
3072 if (Value
->Buffer
[Index
] != 0) {
3077 if (Index
>= Value
->BufferLen
) {
3078 Value
->Value
.b
= FALSE
;
3080 Value
->Value
.b
= TRUE
;
3083 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
3084 FreePool (Value
->Buffer
);
3089 case EFI_IFR_TO_STRING_OP
:
3090 Status
= IfrToString (FormSet
, OpCode
->Format
, Value
);
3093 case EFI_IFR_TO_UINT_OP
:
3094 Status
= IfrToUint (FormSet
, Value
);
3097 case EFI_IFR_TO_LOWER_OP
:
3098 case EFI_IFR_TO_UPPER_OP
:
3099 Status
= InitializeUnicodeCollationProtocol ();
3100 if (EFI_ERROR (Status
)) {
3104 Status
= PopExpression (Value
);
3105 if (EFI_ERROR (Status
)) {
3109 if (Value
->Type
!= EFI_IFR_TYPE_STRING
) {
3110 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3114 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->HiiHandle
);
3115 if (StrPtr
== NULL
) {
3116 Status
= EFI_NOT_FOUND
;
3120 if (OpCode
->Operand
== EFI_IFR_TO_LOWER_OP
) {
3121 mUnicodeCollation
->StrLwr (mUnicodeCollation
, StrPtr
);
3123 mUnicodeCollation
->StrUpr (mUnicodeCollation
, StrPtr
);
3126 Value
->Value
.string
= NewString (StrPtr
, FormSet
->HiiHandle
);
3130 case EFI_IFR_BITWISE_NOT_OP
:
3132 // Pop an expression from the expression stack
3134 Status
= PopExpression (Value
);
3135 if (EFI_ERROR (Status
)) {
3139 if (Value
->Type
> EFI_IFR_TYPE_DATE
) {
3140 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3144 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
3145 Value
->Value
.u64
= ~HiiValueToUINT64(Value
);
3148 case EFI_IFR_SET_OP
:
3150 // Pop an expression from the expression stack
3152 Status
= PopExpression (Value
);
3153 if (EFI_ERROR (Status
)) {
3157 Data1
.Type
= EFI_IFR_TYPE_BOOLEAN
;
3158 Data1
.Value
.b
= FALSE
;
3160 // Set value to var storage buffer
3162 if (OpCode
->VarStorage
!= NULL
) {
3163 switch (OpCode
->VarStorage
->Type
) {
3164 case EFI_HII_VARSTORE_BUFFER
:
3165 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
3166 CopyMem (OpCode
->VarStorage
->EditBuffer
+ OpCode
->VarStoreInfo
.VarOffset
, &Value
->Value
, OpCode
->ValueWidth
);
3167 Data1
.Value
.b
= TRUE
;
3169 case EFI_HII_VARSTORE_NAME_VALUE
:
3170 if (OpCode
->ValueType
!= EFI_IFR_TYPE_STRING
) {
3171 NameValue
= AllocateZeroPool ((OpCode
->ValueWidth
* 2 + 1) * sizeof (CHAR16
));
3172 ASSERT (NameValue
!= NULL
);
3174 // Convert Buffer to Hex String
3176 TempBuffer
= (UINT8
*)&Value
->Value
+ OpCode
->ValueWidth
- 1;
3178 for (Index
= 0; Index
< OpCode
->ValueWidth
; Index
++, TempBuffer
--) {
3179 UnicodeValueToStringS (
3181 (OpCode
->ValueWidth
* 2 + 1) * sizeof (CHAR16
) - ((UINTN
)StrPtr
- (UINTN
)NameValue
),
3182 PREFIX_ZERO
| RADIX_HEX
,
3186 StrPtr
+= StrnLenS (StrPtr
, OpCode
->ValueWidth
* 2 + 1 - ((UINTN
)StrPtr
- (UINTN
)NameValue
) / sizeof (CHAR16
));
3189 Status
= SetValueByName (OpCode
->VarStorage
, OpCode
->ValueName
, NameValue
, GetSetValueWithEditBuffer
, NULL
);
3190 FreePool (NameValue
);
3191 if (!EFI_ERROR (Status
)) {
3192 Data1
.Value
.b
= TRUE
;
3197 case EFI_HII_VARSTORE_EFI_VARIABLE
:
3198 Status
= gRT
->SetVariable (
3200 &OpCode
->VarStorage
->Guid
,
3201 OpCode
->VarStorage
->Attributes
,
3205 if (!EFI_ERROR (Status
)) {
3206 Data1
.Value
.b
= TRUE
;
3212 // Not recognize storage.
3214 Status
= EFI_UNSUPPORTED
;
3219 // For Time/Date Data
3221 if ((OpCode
->ValueType
!= EFI_IFR_TYPE_DATE
) && (OpCode
->ValueType
!= EFI_IFR_TYPE_TIME
)) {
3223 // Only support Data/Time data when storage doesn't exist.
3225 Status
= EFI_UNSUPPORTED
;
3229 Status
= gRT
->GetTime (&EfiTime
, NULL
);
3230 if (!EFI_ERROR (Status
)) {
3231 if (OpCode
->ValueType
== EFI_IFR_TYPE_DATE
) {
3232 switch (OpCode
->VarStoreInfo
.VarOffset
) {
3234 EfiTime
.Year
= Value
->Value
.u16
;
3237 EfiTime
.Month
= Value
->Value
.u8
;
3240 EfiTime
.Day
= Value
->Value
.u8
;
3244 // Invalid Date field.
3246 Status
= EFI_INVALID_PARAMETER
;
3250 switch (OpCode
->VarStoreInfo
.VarOffset
) {
3252 EfiTime
.Hour
= Value
->Value
.u8
;
3255 EfiTime
.Minute
= Value
->Value
.u8
;
3258 EfiTime
.Second
= Value
->Value
.u8
;
3262 // Invalid Time field.
3264 Status
= EFI_INVALID_PARAMETER
;
3269 Status
= gRT
->SetTime (&EfiTime
);
3270 if (!EFI_ERROR (Status
)) {
3271 Data1
.Value
.b
= TRUE
;
3282 case EFI_IFR_ADD_OP
:
3283 case EFI_IFR_SUBTRACT_OP
:
3284 case EFI_IFR_MULTIPLY_OP
:
3285 case EFI_IFR_DIVIDE_OP
:
3286 case EFI_IFR_MODULO_OP
:
3287 case EFI_IFR_BITWISE_AND_OP
:
3288 case EFI_IFR_BITWISE_OR_OP
:
3289 case EFI_IFR_SHIFT_LEFT_OP
:
3290 case EFI_IFR_SHIFT_RIGHT_OP
:
3292 // Pop an expression from the expression stack
3294 Status
= PopExpression (&Data2
);
3295 if (EFI_ERROR (Status
)) {
3300 // Pop another expression from the expression stack
3302 Status
= PopExpression (&Data1
);
3303 if (EFI_ERROR (Status
)) {
3307 if (Data2
.Type
> EFI_IFR_TYPE_DATE
) {
3308 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3312 if (Data1
.Type
> EFI_IFR_TYPE_DATE
) {
3313 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3317 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
3319 switch (OpCode
->Operand
) {
3320 case EFI_IFR_ADD_OP
:
3321 Value
->Value
.u64
= HiiValueToUINT64 (&Data1
) + HiiValueToUINT64 (&Data2
);
3324 case EFI_IFR_SUBTRACT_OP
:
3325 Value
->Value
.u64
= HiiValueToUINT64 (&Data1
) - HiiValueToUINT64 (&Data2
);
3328 case EFI_IFR_MULTIPLY_OP
:
3329 Value
->Value
.u64
= MultU64x32 (HiiValueToUINT64 (&Data1
), (UINT32
)HiiValueToUINT64 (&Data2
));
3332 case EFI_IFR_DIVIDE_OP
:
3333 Value
->Value
.u64
= DivU64x32 (HiiValueToUINT64 (&Data1
), (UINT32
)HiiValueToUINT64 (&Data2
));
3336 case EFI_IFR_MODULO_OP
:
3337 DivU64x32Remainder (HiiValueToUINT64 (&Data1
), (UINT32
)HiiValueToUINT64 (&Data2
), &TempValue
);
3338 Value
->Value
.u64
= TempValue
;
3341 case EFI_IFR_BITWISE_AND_OP
:
3342 Value
->Value
.u64
= HiiValueToUINT64 (&Data1
) & HiiValueToUINT64 (&Data2
);
3345 case EFI_IFR_BITWISE_OR_OP
:
3346 Value
->Value
.u64
= HiiValueToUINT64 (&Data1
) | HiiValueToUINT64 (&Data2
);
3349 case EFI_IFR_SHIFT_LEFT_OP
:
3350 Value
->Value
.u64
= LShiftU64 (HiiValueToUINT64 (&Data1
), (UINTN
)HiiValueToUINT64 (&Data2
));
3353 case EFI_IFR_SHIFT_RIGHT_OP
:
3354 Value
->Value
.u64
= RShiftU64 (HiiValueToUINT64 (&Data1
), (UINTN
)HiiValueToUINT64 (&Data2
));
3363 case EFI_IFR_AND_OP
:
3366 // Two Boolean operator
3368 Status
= PopExpression (&Data2
);
3369 if (EFI_ERROR (Status
)) {
3374 // Pop another expression from the expression stack
3376 Status
= PopExpression (&Data1
);
3377 if (EFI_ERROR (Status
)) {
3381 if (Data2
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
3382 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3386 if (Data1
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
3387 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3391 if (OpCode
->Operand
== EFI_IFR_AND_OP
) {
3392 Value
->Value
.b
= (BOOLEAN
)(Data1
.Value
.b
&& Data2
.Value
.b
);
3394 Value
->Value
.b
= (BOOLEAN
)(Data1
.Value
.b
|| Data2
.Value
.b
);
3399 case EFI_IFR_EQUAL_OP
:
3400 case EFI_IFR_NOT_EQUAL_OP
:
3401 case EFI_IFR_GREATER_EQUAL_OP
:
3402 case EFI_IFR_GREATER_THAN_OP
:
3403 case EFI_IFR_LESS_EQUAL_OP
:
3404 case EFI_IFR_LESS_THAN_OP
:
3406 // Compare two integer, string, boolean or date/time
3408 Status
= PopExpression (&Data2
);
3409 if (EFI_ERROR (Status
)) {
3414 // Pop another expression from the expression stack
3416 Status
= PopExpression (&Data1
);
3417 if (EFI_ERROR (Status
)) {
3421 if ((Data2
.Type
> EFI_IFR_TYPE_BOOLEAN
) &&
3422 (Data2
.Type
!= EFI_IFR_TYPE_STRING
) &&
3423 !IsTypeInBuffer (&Data2
))
3425 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3429 if ((Data1
.Type
> EFI_IFR_TYPE_BOOLEAN
) &&
3430 (Data1
.Type
!= EFI_IFR_TYPE_STRING
) &&
3431 !IsTypeInBuffer (&Data1
))
3433 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3437 Status
= CompareHiiValue (&Data1
, &Data2
, &Result
, FormSet
->HiiHandle
);
3438 if (Data1
.Type
== EFI_IFR_TYPE_BUFFER
) {
3439 FreePool (Data1
.Buffer
);
3442 if (Data2
.Type
== EFI_IFR_TYPE_BUFFER
) {
3443 FreePool (Data2
.Buffer
);
3446 if (Status
== EFI_UNSUPPORTED
) {
3447 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3448 Status
= EFI_SUCCESS
;
3452 if (EFI_ERROR (Status
)) {
3456 switch (OpCode
->Operand
) {
3457 case EFI_IFR_EQUAL_OP
:
3458 Value
->Value
.b
= (BOOLEAN
)((Result
== 0) ? TRUE
: FALSE
);
3461 case EFI_IFR_NOT_EQUAL_OP
:
3462 Value
->Value
.b
= (BOOLEAN
)((Result
!= 0) ? TRUE
: FALSE
);
3465 case EFI_IFR_GREATER_EQUAL_OP
:
3466 Value
->Value
.b
= (BOOLEAN
)((Result
>= 0) ? TRUE
: FALSE
);
3469 case EFI_IFR_GREATER_THAN_OP
:
3470 Value
->Value
.b
= (BOOLEAN
)((Result
> 0) ? TRUE
: FALSE
);
3473 case EFI_IFR_LESS_EQUAL_OP
:
3474 Value
->Value
.b
= (BOOLEAN
)((Result
<= 0) ? TRUE
: FALSE
);
3477 case EFI_IFR_LESS_THAN_OP
:
3478 Value
->Value
.b
= (BOOLEAN
)((Result
< 0) ? TRUE
: FALSE
);
3487 case EFI_IFR_MATCH_OP
:
3488 Status
= InitializeUnicodeCollationProtocol ();
3489 if (EFI_ERROR (Status
)) {
3493 Status
= IfrMatch (FormSet
, Value
);
3496 case EFI_IFR_MATCH2_OP
:
3497 Status
= IfrMatch2 (FormSet
, &OpCode
->Guid
, Value
);
3500 case EFI_IFR_CATENATE_OP
:
3501 Status
= IfrCatenate (FormSet
, Value
);
3507 case EFI_IFR_CONDITIONAL_OP
:
3509 // Pop third expression from the expression stack
3511 Status
= PopExpression (&Data3
);
3512 if (EFI_ERROR (Status
)) {
3517 // Pop second expression from the expression stack
3519 Status
= PopExpression (&Data2
);
3520 if (EFI_ERROR (Status
)) {
3525 // Pop first expression from the expression stack
3527 Status
= PopExpression (&Data1
);
3528 if (EFI_ERROR (Status
)) {
3532 if (Data1
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
3533 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3537 if (Data1
.Value
.b
) {
3545 case EFI_IFR_FIND_OP
:
3546 Status
= IfrFind (FormSet
, OpCode
->Format
, Value
);
3549 case EFI_IFR_MID_OP
:
3550 Status
= IfrMid (FormSet
, Value
);
3553 case EFI_IFR_TOKEN_OP
:
3554 Status
= IfrToken (FormSet
, Value
);
3557 case EFI_IFR_SPAN_OP
:
3558 Status
= IfrSpan (FormSet
, OpCode
->Flags
, Value
);
3561 case EFI_IFR_MAP_OP
:
3563 // Pop the check value
3565 Status
= PopExpression (&Data1
);
3566 if (EFI_ERROR (Status
)) {
3571 // Check MapExpression list is valid.
3573 if (OpCode
->MapExpressionList
.ForwardLink
== NULL
) {
3574 Status
= EFI_INVALID_PARAMETER
;
3579 // Go through map expression list.
3581 SubExpressionLink
= GetFirstNode (&OpCode
->MapExpressionList
);
3582 while (!IsNull (&OpCode
->MapExpressionList
, SubExpressionLink
)) {
3583 SubExpression
= FORM_EXPRESSION_FROM_LINK (SubExpressionLink
);
3585 // Evaluate the first expression in this pair.
3587 Status
= EvaluateExpression (FormSet
, Form
, SubExpression
);
3588 if (EFI_ERROR (Status
)) {
3593 // Compare the expression value with current value
3595 if ((CompareHiiValue (&Data1
, &SubExpression
->Result
, &Result
, NULL
) == EFI_SUCCESS
) && (Result
== 0)) {
3597 // Try get the map value.
3599 SubExpressionLink
= GetNextNode (&OpCode
->MapExpressionList
, SubExpressionLink
);
3600 if (IsNull (&OpCode
->MapExpressionList
, SubExpressionLink
)) {
3601 Status
= EFI_INVALID_PARAMETER
;
3605 SubExpression
= FORM_EXPRESSION_FROM_LINK (SubExpressionLink
);
3606 Status
= EvaluateExpression (FormSet
, Form
, SubExpression
);
3607 if (EFI_ERROR (Status
)) {
3611 Value
= &SubExpression
->Result
;
3616 // Skip the second expression on this pair.
3618 SubExpressionLink
= GetNextNode (&OpCode
->MapExpressionList
, SubExpressionLink
);
3619 if (IsNull (&OpCode
->MapExpressionList
, SubExpressionLink
)) {
3620 Status
= EFI_INVALID_PARAMETER
;
3625 // Goto the first expression on next pair.
3627 SubExpressionLink
= GetNextNode (&OpCode
->MapExpressionList
, SubExpressionLink
);
3631 // No map value is found.
3633 if (IsNull (&OpCode
->MapExpressionList
, SubExpressionLink
)) {
3634 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3635 Value
->Value
.u8
= 0;
3644 if (EFI_ERROR (Status
) || (Value
->Type
== EFI_IFR_TYPE_UNDEFINED
)) {
3648 Status
= PushExpression (Value
);
3649 if (EFI_ERROR (Status
)) {
3655 // Pop the final result from expression stack
3658 Status
= PopExpression (Value
);
3659 if (EFI_ERROR (Status
)) {
3664 // After evaluating an expression, there should be only one value left on the expression stack
3666 if (PopExpression (Value
) != EFI_ACCESS_DENIED
) {
3667 Status
= EFI_INVALID_PARAMETER
;
3671 RestoreExpressionEvaluationStackOffset (StackOffset
);
3672 if (!EFI_ERROR (Status
)) {
3673 CopyMem (&Expression
->Result
, Value
, sizeof (EFI_HII_VALUE
));
3680 Check whether the result is TRUE or FALSE.
3682 For the EFI_HII_VALUE value type is numeric, return TRUE if the
3685 @param Result Input the result data.
3687 @retval TRUE The result is TRUE.
3688 @retval FALSE The result is FALSE.
3693 IN EFI_HII_VALUE
*Result
3696 switch (Result
->Type
) {
3697 case EFI_IFR_TYPE_BOOLEAN
:
3698 return Result
->Value
.b
;
3700 case EFI_IFR_TYPE_NUM_SIZE_8
:
3701 return (BOOLEAN
)(Result
->Value
.u8
!= 0);
3703 case EFI_IFR_TYPE_NUM_SIZE_16
:
3704 return (BOOLEAN
)(Result
->Value
.u16
!= 0);
3706 case EFI_IFR_TYPE_NUM_SIZE_32
:
3707 return (BOOLEAN
)(Result
->Value
.u32
!= 0);
3709 case EFI_IFR_TYPE_NUM_SIZE_64
:
3710 return (BOOLEAN
)(Result
->Value
.u64
!= 0);
3718 Return the result of the expression list. Check the expression list and
3719 return the highest priority express result.
3720 Priority: DisableIf > SuppressIf > GrayOutIf > FALSE
3722 @param ExpList The input expression list.
3723 @param Evaluate Whether need to evaluate the expression first.
3724 @param FormSet FormSet associated with this expression.
3725 @param Form Form associated with this expression.
3727 @retval EXPRESS_RESULT Return the higher priority express result.
3728 DisableIf > SuppressIf > GrayOutIf > FALSE
3732 EvaluateExpressionList (
3733 IN FORM_EXPRESSION_LIST
*ExpList
,
3734 IN BOOLEAN Evaluate
,
3735 IN FORM_BROWSER_FORMSET
*FormSet OPTIONAL
,
3736 IN FORM_BROWSER_FORM
*Form OPTIONAL
3740 EXPRESS_RESULT ReturnVal
;
3741 EXPRESS_RESULT CompareOne
;
3744 if (ExpList
== NULL
) {
3745 return ExpressFalse
;
3748 ASSERT (ExpList
->Signature
== FORM_EXPRESSION_LIST_SIGNATURE
);
3752 // Check whether need to evaluate the expression first.
3755 while (ExpList
->Count
> Index
) {
3756 Status
= EvaluateExpression (FormSet
, Form
, ExpList
->Expression
[Index
++]);
3757 if (EFI_ERROR (Status
)) {
3758 return ExpressFalse
;
3764 // Run the list of expressions.
3766 ReturnVal
= ExpressFalse
;
3767 for (Index
= 0; Index
< ExpList
->Count
; Index
++) {
3768 if (IsTrue (&ExpList
->Expression
[Index
]->Result
)) {
3769 switch (ExpList
->Expression
[Index
]->Type
) {
3770 case EFI_HII_EXPRESSION_SUPPRESS_IF
:
3771 CompareOne
= ExpressSuppress
;
3774 case EFI_HII_EXPRESSION_GRAY_OUT_IF
:
3775 CompareOne
= ExpressGrayOut
;
3778 case EFI_HII_EXPRESSION_DISABLE_IF
:
3779 CompareOne
= ExpressDisable
;
3783 return ExpressFalse
;
3786 ReturnVal
= ReturnVal
< CompareOne
? CompareOne
: ReturnVal
;