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
;
45 // Unicode collation protocol interface
47 EFI_UNICODE_COLLATION_PROTOCOL
*mUnicodeCollation
= NULL
;
48 EFI_USER_MANAGER_PROTOCOL
*mUserManager
= NULL
;
51 Grow size of the stack.
53 This is an internal function.
55 @param Stack On input: old stack; On output: new stack
56 @param StackPtr On input: old stack pointer; On output: new stack
58 @param StackEnd On input: old stack end; On output: new stack end
60 @retval EFI_SUCCESS Grow stack success.
61 @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.
66 IN OUT EFI_HII_VALUE
**Stack
,
67 IN OUT EFI_HII_VALUE
**StackPtr
,
68 IN OUT EFI_HII_VALUE
**StackEnd
72 EFI_HII_VALUE
*NewStack
;
74 Size
= EXPRESSION_STACK_SIZE_INCREMENT
;
75 if (*StackPtr
!= NULL
) {
76 Size
= Size
+ (*StackEnd
- *Stack
);
79 NewStack
= AllocatePool (Size
* sizeof (EFI_HII_VALUE
));
80 if (NewStack
== NULL
) {
81 return EFI_OUT_OF_RESOURCES
;
84 if (*StackPtr
!= NULL
) {
86 // Copy from Old Stack to the New Stack
91 (*StackEnd
- *Stack
) * sizeof (EFI_HII_VALUE
)
101 // Make the Stack pointer point to the old data in the new stack
103 *StackPtr
= NewStack
+ (*StackPtr
- *Stack
);
105 *StackEnd
= NewStack
+ Size
;
112 Push an element onto the Boolean Stack.
114 @param Stack On input: old stack; On output: new stack
115 @param StackPtr On input: old stack pointer; On output: new stack
117 @param StackEnd On input: old stack end; On output: new stack end
118 @param Data Data to push.
120 @retval EFI_SUCCESS Push stack success.
125 IN OUT EFI_HII_VALUE
**Stack
,
126 IN OUT EFI_HII_VALUE
**StackPtr
,
127 IN OUT EFI_HII_VALUE
**StackEnd
,
128 IN EFI_HII_VALUE
*Data
134 // Check for a stack overflow condition
136 if (*StackPtr
>= *StackEnd
) {
140 Status
= GrowStack (Stack
, StackPtr
, StackEnd
);
141 if (EFI_ERROR (Status
)) {
147 // Push the item onto the stack
149 CopyMem (*StackPtr
, Data
, sizeof (EFI_HII_VALUE
));
150 if (Data
->Type
== EFI_IFR_TYPE_BUFFER
) {
151 (*StackPtr
)->Buffer
= AllocateCopyPool(Data
->BufferLen
, Data
->Buffer
);
152 ASSERT ((*StackPtr
)->Buffer
!= NULL
);
155 *StackPtr
= *StackPtr
+ 1;
162 Pop an element from the stack.
164 @param Stack On input: old stack
165 @param StackPtr On input: old stack pointer; On output: new stack pointer
166 @param Data Data to pop.
168 @retval EFI_SUCCESS The value was popped onto the stack.
169 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
174 IN EFI_HII_VALUE
*Stack
,
175 IN OUT EFI_HII_VALUE
**StackPtr
,
176 OUT EFI_HII_VALUE
*Data
180 // Check for a stack underflow condition
182 if (*StackPtr
== Stack
) {
183 return EFI_ACCESS_DENIED
;
187 // Pop the item off the stack
189 *StackPtr
= *StackPtr
- 1;
190 CopyMem (Data
, *StackPtr
, sizeof (EFI_HII_VALUE
));
196 Reset stack pointer to begin of the stack.
200 ResetCurrentExpressionStack (
204 mCurrentExpressionPointer
= mCurrentExpressionStack
;
205 mFormExpressionPointer
= mFormExpressionStack
;
206 mStatementExpressionPointer
= mStatementExpressionStack
;
207 mOptionExpressionPointer
= mOptionExpressionStack
;
212 Push current expression onto the Stack
214 @param Pointer Pointer to current expression.
216 @retval EFI_SUCCESS The value was pushed onto the stack.
217 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
221 PushCurrentExpression (
227 Data
.Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
228 Data
.Value
.u64
= (UINT64
) (UINTN
) Pointer
;
231 &mCurrentExpressionStack
,
232 &mCurrentExpressionPointer
,
233 &mCurrentExpressionEnd
,
240 Pop current expression from the Stack
242 @param Pointer Pointer to current expression to be pop.
244 @retval EFI_SUCCESS The value was pushed onto the stack.
245 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
249 PopCurrentExpression (
257 mCurrentExpressionStack
,
258 &mCurrentExpressionPointer
,
262 *Pointer
= (VOID
*) (UINTN
) Data
.Value
.u64
;
268 Reset stack pointer to begin of the stack.
272 ResetMapExpressionListStack (
276 mMapExpressionListPointer
= mMapExpressionListStack
;
281 Grow size of the stack.
283 This is an internal function.
285 @param Stack On input: old stack; On output: new stack
286 @param StackPtr On input: old stack pointer; On output: new stack
288 @param StackEnd On input: old stack end; On output: new stack end
289 @param MemberSize The stack member size.
291 @retval EFI_SUCCESS Grow stack success.
292 @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.
296 GrowConditionalStack (
297 IN OUT FORM_EXPRESSION
***Stack
,
298 IN OUT FORM_EXPRESSION
***StackPtr
,
299 IN OUT FORM_EXPRESSION
***StackEnd
,
304 FORM_EXPRESSION
**NewStack
;
306 Size
= EXPRESSION_STACK_SIZE_INCREMENT
;
307 if (*StackPtr
!= NULL
) {
308 Size
= Size
+ (*StackEnd
- *Stack
);
311 NewStack
= AllocatePool (Size
* MemberSize
);
312 if (NewStack
== NULL
) {
313 return EFI_OUT_OF_RESOURCES
;
316 if (*StackPtr
!= NULL
) {
318 // Copy from Old Stack to the New Stack
323 (*StackEnd
- *Stack
) * MemberSize
327 // Free The Old Stack
333 // Make the Stack pointer point to the old data in the new stack
335 *StackPtr
= NewStack
+ (*StackPtr
- *Stack
);
337 *StackEnd
= NewStack
+ Size
;
343 Push an element onto the Stack.
345 @param Stack On input: old stack; On output: new stack
346 @param StackPtr On input: old stack pointer; On output: new stack
348 @param StackEnd On input: old stack end; On output: new stack end
349 @param Data Data to push.
351 @retval EFI_SUCCESS Push stack success.
355 PushConditionalStack (
356 IN OUT FORM_EXPRESSION
***Stack
,
357 IN OUT FORM_EXPRESSION
***StackPtr
,
358 IN OUT FORM_EXPRESSION
***StackEnd
,
359 IN FORM_EXPRESSION
**Data
365 // Check for a stack overflow condition
367 if (*StackPtr
>= *StackEnd
) {
371 Status
= GrowConditionalStack (Stack
, StackPtr
, StackEnd
, sizeof (FORM_EXPRESSION
*));
372 if (EFI_ERROR (Status
)) {
378 // Push the item onto the stack
380 CopyMem (*StackPtr
, Data
, sizeof (FORM_EXPRESSION
*));
381 *StackPtr
= *StackPtr
+ 1;
388 Pop an element from the stack.
390 @param Stack On input: old stack
391 @param StackPtr On input: old stack pointer; On output: new stack pointer
392 @param Data Data to pop.
394 @retval EFI_SUCCESS The value was popped onto the stack.
395 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
399 PopConditionalStack (
400 IN FORM_EXPRESSION
**Stack
,
401 IN OUT FORM_EXPRESSION
***StackPtr
,
402 OUT FORM_EXPRESSION
**Data
406 // Check for a stack underflow condition
408 if (*StackPtr
== Stack
) {
409 return EFI_ACCESS_DENIED
;
413 // Pop the item off the stack
415 *StackPtr
= *StackPtr
- 1;
416 CopyMem (Data
, *StackPtr
, sizeof (FORM_EXPRESSION
*));
422 Get the expression list count.
424 @param Level Which type this expression belong to. Form,
427 @retval >=0 The expression count
428 @retval -1 Input parameter error.
432 GetConditionalExpressionCount (
433 IN EXPRESS_LEVEL Level
438 return mFormExpressionPointer
- mFormExpressionStack
;
439 case ExpressStatement
:
440 return mStatementExpressionPointer
- mStatementExpressionStack
;
442 return mOptionExpressionPointer
- mOptionExpressionStack
;
450 Get the expression Buffer pointer.
452 @param Level Which type this expression belong to. Form,
455 @retval The start pointer of the expression buffer or NULL.
459 GetConditionalExpressionList (
460 IN EXPRESS_LEVEL Level
465 return mFormExpressionStack
;
466 case ExpressStatement
:
467 return mStatementExpressionStack
;
469 return mOptionExpressionStack
;
478 Push the expression options onto the Stack.
480 @param Pointer Pointer to the current expression.
481 @param Level Which type this expression belong to. Form,
484 @retval EFI_SUCCESS The value was pushed onto the stack.
485 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
489 PushConditionalExpression (
490 IN FORM_EXPRESSION
*Pointer
,
491 IN EXPRESS_LEVEL Level
496 return PushConditionalStack (
497 &mFormExpressionStack
,
498 &mFormExpressionPointer
,
502 case ExpressStatement
:
503 return PushConditionalStack (
504 &mStatementExpressionStack
,
505 &mStatementExpressionPointer
,
506 &mStatementExpressionEnd
,
510 return PushConditionalStack (
511 &mOptionExpressionStack
,
512 &mOptionExpressionPointer
,
513 &mOptionExpressionEnd
,
518 return EFI_INVALID_PARAMETER
;
523 Pop the expression options from the Stack
525 @param Level Which type this expression belong to. Form,
528 @retval EFI_SUCCESS The value was pushed onto the stack.
529 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
533 PopConditionalExpression (
534 IN EXPRESS_LEVEL Level
537 FORM_EXPRESSION
*Pointer
;
541 return PopConditionalStack (
542 mFormExpressionStack
,
543 &mFormExpressionPointer
,
547 case ExpressStatement
:
548 return PopConditionalStack (
549 mStatementExpressionStack
,
550 &mStatementExpressionPointer
,
555 return PopConditionalStack (
556 mOptionExpressionStack
,
557 &mOptionExpressionPointer
,
563 return EFI_INVALID_PARAMETER
;
569 Push the list of map expression onto the Stack
571 @param Pointer Pointer to the list of map expression to be pushed.
573 @retval EFI_SUCCESS The value was pushed onto the stack.
574 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
578 PushMapExpressionList (
584 Data
.Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
585 Data
.Value
.u64
= (UINT64
) (UINTN
) Pointer
;
588 &mMapExpressionListStack
,
589 &mMapExpressionListPointer
,
590 &mMapExpressionListEnd
,
597 Pop the list of map expression from the Stack
599 @param Pointer Pointer to the list of map expression to be pop.
601 @retval EFI_SUCCESS The value was pushed onto the stack.
602 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
606 PopMapExpressionList (
614 mMapExpressionListStack
,
615 &mMapExpressionListPointer
,
619 *Pointer
= (VOID
*) (UINTN
) Data
.Value
.u64
;
625 Reset stack pointer to begin of the stack.
633 mOpCodeScopeStackPointer
= mOpCodeScopeStack
;
638 Push an Operand onto the Stack
640 @param Operand Operand to push.
642 @retval EFI_SUCCESS The value was pushed onto the stack.
643 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
654 Data
.Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
655 Data
.Value
.u8
= Operand
;
659 &mOpCodeScopeStackPointer
,
660 &mOpCodeScopeStackEnd
,
667 Pop an Operand from the Stack
669 @param Operand Operand to pop.
671 @retval EFI_SUCCESS The value was pushed onto the stack.
672 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
686 &mOpCodeScopeStackPointer
,
690 *Operand
= Data
.Value
.u8
;
697 Push an Expression value onto the Stack
699 @param Value Expression value to push.
701 @retval EFI_SUCCESS The value was pushed onto the stack.
702 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
708 IN EFI_HII_VALUE
*Value
712 &mExpressionEvaluationStack
,
713 &mExpressionEvaluationStackPointer
,
714 &mExpressionEvaluationStackEnd
,
721 Pop an Expression value from the stack.
723 @param Value Expression value to pop.
725 @retval EFI_SUCCESS The value was popped onto the stack.
726 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
731 OUT EFI_HII_VALUE
*Value
735 mExpressionEvaluationStack
+ mExpressionEvaluationStackOffset
,
736 &mExpressionEvaluationStackPointer
,
742 Get current stack offset from stack start.
744 @return Stack offset to stack start.
747 SaveExpressionEvaluationStackOffset (
751 UINTN TempStackOffset
;
752 TempStackOffset
= mExpressionEvaluationStackOffset
;
753 mExpressionEvaluationStackOffset
= mExpressionEvaluationStackPointer
- mExpressionEvaluationStack
;
754 return TempStackOffset
;
758 Restore stack offset based on input stack offset
760 @param StackOffset Offset to stack start.
764 RestoreExpressionEvaluationStackOffset (
768 mExpressionEvaluationStackOffset
= StackOffset
;
772 Get Form given its FormId.
774 @param FormSet The formset which contains this form.
775 @param FormId Id of this form.
777 @retval Pointer The form.
778 @retval NULL Specified Form is not found in the formset.
783 IN FORM_BROWSER_FORMSET
*FormSet
,
788 FORM_BROWSER_FORM
*Form
;
790 Link
= GetFirstNode (&FormSet
->FormListHead
);
791 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
792 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
794 if (Form
->FormId
== FormId
) {
798 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
806 Search a Question in Form scope using its QuestionId.
808 @param Form The form which contains this Question.
809 @param QuestionId Id of this Question.
811 @retval Pointer The Question.
812 @retval NULL Specified Question not found in the form.
815 FORM_BROWSER_STATEMENT
*
817 IN FORM_BROWSER_FORM
*Form
,
822 FORM_BROWSER_STATEMENT
*Question
;
824 if (QuestionId
== 0 || Form
== NULL
) {
826 // The value of zero is reserved
831 Link
= GetFirstNode (&Form
->StatementListHead
);
832 while (!IsNull (&Form
->StatementListHead
, Link
)) {
833 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
835 if (Question
->QuestionId
== QuestionId
) {
839 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
847 Search a Question in Formset scope using its QuestionId.
849 @param FormSet The formset which contains this form.
850 @param Form The form which contains this Question.
851 @param QuestionId Id of this Question.
853 @retval Pointer The Question.
854 @retval NULL Specified Question not found in the form.
857 FORM_BROWSER_STATEMENT
*
859 IN FORM_BROWSER_FORMSET
*FormSet
,
860 IN FORM_BROWSER_FORM
*Form
,
865 FORM_BROWSER_STATEMENT
*Question
;
868 // Search in the form scope first
870 Question
= IdToQuestion2 (Form
, QuestionId
);
871 if (Question
!= NULL
) {
876 // Search in the formset scope
878 Link
= GetFirstNode (&FormSet
->FormListHead
);
879 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
880 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
882 Question
= IdToQuestion2 (Form
, QuestionId
);
883 if (Question
!= NULL
) {
885 // EFI variable storage may be updated by Callback() asynchronous,
886 // to keep synchronous, always reload the Question Value.
888 if (Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
889 GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithHiiDriver
);
895 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
903 Get Expression given its RuleId.
905 @param Form The form which contains this Expression.
906 @param RuleId Id of this Expression.
908 @retval Pointer The Expression.
909 @retval NULL Specified Expression not found in the form.
914 IN FORM_BROWSER_FORM
*Form
,
919 FORM_EXPRESSION
*Expression
;
921 Link
= GetFirstNode (&Form
->ExpressionListHead
);
922 while (!IsNull (&Form
->ExpressionListHead
, Link
)) {
923 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
925 if (Expression
->Type
== EFI_HII_EXPRESSION_RULE
&& Expression
->RuleId
== RuleId
) {
929 Link
= GetNextNode (&Form
->ExpressionListHead
, Link
);
937 Locate the Unicode Collation Protocol interface for later use.
939 @retval EFI_SUCCESS Protocol interface initialize success.
940 @retval Other Protocol interface initialize failed.
944 InitializeUnicodeCollationProtocol (
950 if (mUnicodeCollation
!= NULL
) {
955 // BUGBUG: Proper impelmentation is to locate all Unicode Collation Protocol
956 // instances first and then select one which support English language.
957 // Current implementation just pick the first instance.
959 Status
= gBS
->LocateProtocol (
960 &gEfiUnicodeCollation2ProtocolGuid
,
962 (VOID
**) &mUnicodeCollation
968 Convert the input Unicode character to upper.
970 @param String Th Unicode character to be converted.
978 while (*String
!= 0) {
979 if ((*String
>= 'a') && (*String
<= 'z')) {
980 *String
= (UINT16
) ((*String
) & ((UINT16
) ~0x20));
987 Check whether this value type can be transfer to EFI_IFR_TYPE_BUFFER type.
989 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to
990 EFI_IFR_TYPE_BUFFER when do the value compare.
992 @param Value Expression value to compare on.
994 @retval TRUE This value type can be transter to EFI_IFR_TYPE_BUFFER type.
995 @retval FALSE This value type can't be transter to EFI_IFR_TYPE_BUFFER type.
1000 IN EFI_HII_VALUE
*Value
1003 switch (Value
->Type
) {
1004 case EFI_IFR_TYPE_BUFFER
:
1005 case EFI_IFR_TYPE_DATE
:
1006 case EFI_IFR_TYPE_TIME
:
1007 case EFI_IFR_TYPE_REF
:
1016 Check whether this value type can be transfer to EFI_IFR_TYPE_UINT64
1018 @param Value Expression value to compare on.
1020 @retval TRUE This value type can be transter to EFI_IFR_TYPE_BUFFER type.
1021 @retval FALSE This value type can't be transter to EFI_IFR_TYPE_BUFFER type.
1026 IN EFI_HII_VALUE
*Value
1029 switch (Value
->Type
) {
1030 case EFI_IFR_TYPE_NUM_SIZE_8
:
1031 case EFI_IFR_TYPE_NUM_SIZE_16
:
1032 case EFI_IFR_TYPE_NUM_SIZE_32
:
1033 case EFI_IFR_TYPE_NUM_SIZE_64
:
1034 case EFI_IFR_TYPE_BOOLEAN
:
1043 Return the buffer length for this value.
1045 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to
1046 EFI_IFR_TYPE_BUFFER when do the value compare.
1048 @param Value Expression value to compare on.
1050 @retval BufLen Return the buffer length.
1055 IN EFI_HII_VALUE
*Value
1058 switch (Value
->Type
) {
1059 case EFI_IFR_TYPE_BUFFER
:
1060 return Value
->BufferLen
;
1062 case EFI_IFR_TYPE_DATE
:
1063 return (UINT16
) sizeof (EFI_HII_DATE
);
1065 case EFI_IFR_TYPE_TIME
:
1066 return (UINT16
) sizeof (EFI_HII_TIME
);
1068 case EFI_IFR_TYPE_REF
:
1069 return (UINT16
) sizeof (EFI_HII_REF
);
1077 Return the buffer pointer for this value.
1079 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to
1080 EFI_IFR_TYPE_BUFFER when do the value compare.
1082 @param Value Expression value to compare on.
1084 @retval Buf Return the buffer pointer.
1089 IN EFI_HII_VALUE
*Value
1092 switch (Value
->Type
) {
1093 case EFI_IFR_TYPE_BUFFER
:
1094 return Value
->Buffer
;
1096 case EFI_IFR_TYPE_DATE
:
1097 return (UINT8
*) (&Value
->Value
.date
);
1099 case EFI_IFR_TYPE_TIME
:
1100 return (UINT8
*) (&Value
->Value
.time
);
1102 case EFI_IFR_TYPE_REF
:
1103 return (UINT8
*) (&Value
->Value
.ref
);
1111 Evaluate opcode EFI_IFR_TO_STRING.
1113 @param FormSet Formset which contains this opcode.
1114 @param Format String format in EFI_IFR_TO_STRING.
1115 @param Result Evaluation result for this opcode.
1117 @retval EFI_SUCCESS Opcode evaluation success.
1118 @retval Other Opcode evaluation failed.
1123 IN FORM_BROWSER_FORMSET
*FormSet
,
1125 OUT EFI_HII_VALUE
*Result
1129 EFI_HII_VALUE Value
;
1131 CHAR16
*PrintFormat
;
1132 CHAR16 Buffer
[MAXIMUM_VALUE_CHARACTERS
];
1138 Status
= PopExpression (&Value
);
1139 if (EFI_ERROR (Status
)) {
1143 switch (Value
.Type
) {
1144 case EFI_IFR_TYPE_NUM_SIZE_8
:
1145 case EFI_IFR_TYPE_NUM_SIZE_16
:
1146 case EFI_IFR_TYPE_NUM_SIZE_32
:
1147 case EFI_IFR_TYPE_NUM_SIZE_64
:
1148 BufferSize
= MAXIMUM_VALUE_CHARACTERS
* sizeof (CHAR16
);
1150 case EFI_IFR_STRING_UNSIGNED_DEC
:
1151 case EFI_IFR_STRING_SIGNED_DEC
:
1152 PrintFormat
= L
"%ld";
1155 case EFI_IFR_STRING_LOWERCASE_HEX
:
1156 PrintFormat
= L
"%lx";
1159 case EFI_IFR_STRING_UPPERCASE_HEX
:
1160 PrintFormat
= L
"%lX";
1164 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1167 UnicodeSPrint (Buffer
, BufferSize
, PrintFormat
, Value
.Value
.u64
);
1171 case EFI_IFR_TYPE_STRING
:
1172 CopyMem (Result
, &Value
, sizeof (EFI_HII_VALUE
));
1175 case EFI_IFR_TYPE_BOOLEAN
:
1176 String
= (Value
.Value
.b
) ? L
"True" : L
"False";
1179 case EFI_IFR_TYPE_BUFFER
:
1180 case EFI_IFR_TYPE_DATE
:
1181 case EFI_IFR_TYPE_TIME
:
1182 case EFI_IFR_TYPE_REF
:
1184 // + 3 is base on the unicode format, the length may be odd number,
1185 // so need 1 byte to align, also need 2 bytes for L'\0'.
1187 if (Value
.Type
== EFI_IFR_TYPE_BUFFER
) {
1188 SrcLen
= Value
.BufferLen
;
1189 SrcBuf
= Value
.Buffer
;
1191 SrcBuf
= GetBufferForValue(&Value
);
1192 SrcLen
= GetLengthForValue(&Value
);
1195 TmpBuf
= AllocateZeroPool (SrcLen
+ 3);
1196 ASSERT (TmpBuf
!= NULL
);
1197 if (Format
== EFI_IFR_STRING_ASCII
) {
1198 CopyMem (TmpBuf
, SrcBuf
, SrcLen
);
1199 PrintFormat
= L
"%a";
1201 // Format == EFI_IFR_STRING_UNICODE
1202 CopyMem (TmpBuf
, SrcBuf
, SrcLen
* sizeof (CHAR16
));
1203 PrintFormat
= L
"%s";
1205 UnicodeSPrint (Buffer
, sizeof (Buffer
), PrintFormat
, TmpBuf
);
1208 if (Value
.Type
== EFI_IFR_TYPE_BUFFER
) {
1209 FreePool (Value
.Buffer
);
1214 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1218 Result
->Type
= EFI_IFR_TYPE_STRING
;
1219 Result
->Value
.string
= NewString (String
, FormSet
->HiiHandle
);
1225 Evaluate opcode EFI_IFR_TO_UINT.
1227 @param FormSet Formset which contains this opcode.
1228 @param Result Evaluation result for this opcode.
1230 @retval EFI_SUCCESS Opcode evaluation success.
1231 @retval Other Opcode evaluation failed.
1236 IN FORM_BROWSER_FORMSET
*FormSet
,
1237 OUT EFI_HII_VALUE
*Result
1241 EFI_HII_VALUE Value
;
1245 Status
= PopExpression (&Value
);
1246 if (EFI_ERROR (Status
)) {
1250 if (Value
.Type
>= EFI_IFR_TYPE_OTHER
&& !IsTypeInBuffer(&Value
)) {
1251 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1255 Status
= EFI_SUCCESS
;
1256 if (Value
.Type
== EFI_IFR_TYPE_STRING
) {
1257 String
= GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
1258 if (String
== NULL
) {
1259 return EFI_NOT_FOUND
;
1262 IfrStrToUpper (String
);
1263 StringPtr
= StrStr (String
, L
"0X");
1264 if (StringPtr
!= NULL
) {
1268 Result
->Value
.u64
= StrHexToUint64 (String
);
1273 Result
->Value
.u64
= StrDecimalToUint64 (String
);
1276 } else if (IsTypeInBuffer(&Value
)) {
1277 if (GetLengthForValue (&Value
) > 8) {
1278 if (Value
.Type
== EFI_IFR_TYPE_BUFFER
) {
1279 FreePool (Value
.Buffer
);
1281 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1285 ASSERT (GetBufferForValue (&Value
) != NULL
);
1286 Result
->Value
.u64
= *(UINT64
*) GetBufferForValue (&Value
);
1288 if (Value
.Type
== EFI_IFR_TYPE_BUFFER
) {
1289 FreePool (Value
.Buffer
);
1292 CopyMem (Result
, &Value
, sizeof (EFI_HII_VALUE
));
1295 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1301 Evaluate opcode EFI_IFR_CATENATE.
1303 @param FormSet Formset which contains this opcode.
1304 @param Result Evaluation result for this opcode.
1306 @retval EFI_SUCCESS Opcode evaluation success.
1307 @retval Other Opcode evaluation failed.
1312 IN FORM_BROWSER_FORMSET
*FormSet
,
1313 OUT EFI_HII_VALUE
*Result
1317 EFI_HII_VALUE Value
[2];
1328 // String[0] - The second string
1329 // String[1] - The first string
1334 Status
= EFI_SUCCESS
;
1335 ZeroMem (Value
, sizeof (Value
));
1337 Status
= PopExpression (&Value
[0]);
1338 if (EFI_ERROR (Status
)) {
1342 Status
= PopExpression (&Value
[1]);
1343 if (EFI_ERROR (Status
)) {
1347 for (Index
= 0; Index
< 2; Index
++) {
1348 if (Value
[Index
].Type
!= EFI_IFR_TYPE_STRING
&& !IsTypeInBuffer(&Value
[Index
])) {
1349 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1350 Status
= EFI_SUCCESS
;
1354 if (Value
[Index
].Type
== EFI_IFR_TYPE_STRING
) {
1355 String
[Index
] = GetToken (Value
[Index
].Value
.string
, FormSet
->HiiHandle
);
1356 if (String
[Index
] == NULL
) {
1357 Status
= EFI_NOT_FOUND
;
1363 if (Value
[0].Type
== EFI_IFR_TYPE_STRING
) {
1364 Size
= StrSize (String
[0]);
1365 MaxLen
= (StrSize (String
[1]) + Size
) / sizeof (CHAR16
);
1366 StringPtr
= AllocatePool (MaxLen
* sizeof (CHAR16
));
1367 ASSERT (StringPtr
!= NULL
);
1368 StrCpyS (StringPtr
, MaxLen
, String
[1]);
1369 StrCatS (StringPtr
, MaxLen
, String
[0]);
1371 Result
->Type
= EFI_IFR_TYPE_STRING
;
1372 Result
->Value
.string
= NewString (StringPtr
, FormSet
->HiiHandle
);
1374 Result
->Type
= EFI_IFR_TYPE_BUFFER
;
1375 Length0
= GetLengthForValue(&Value
[0]);
1376 Length1
= GetLengthForValue(&Value
[1]);
1377 Result
->BufferLen
= (UINT16
) (Length0
+ Length1
);
1379 Result
->Buffer
= AllocateZeroPool (Result
->BufferLen
);
1380 ASSERT (Result
->Buffer
!= NULL
);
1382 TmpBuf
= GetBufferForValue(&Value
[0]);
1383 ASSERT (TmpBuf
!= NULL
);
1384 CopyMem (Result
->Buffer
, TmpBuf
, Length0
);
1385 TmpBuf
= GetBufferForValue(&Value
[1]);
1386 ASSERT (TmpBuf
!= NULL
);
1387 CopyMem (&Result
->Buffer
[Length0
], TmpBuf
, Length1
);
1390 if (Value
[0].Buffer
!= NULL
) {
1391 FreePool (Value
[0].Buffer
);
1393 if (Value
[1].Buffer
!= NULL
) {
1394 FreePool (Value
[1].Buffer
);
1396 if (String
[0] != NULL
) {
1397 FreePool (String
[0]);
1399 if (String
[1] != NULL
) {
1400 FreePool (String
[1]);
1402 if (StringPtr
!= NULL
) {
1403 FreePool (StringPtr
);
1411 Evaluate opcode EFI_IFR_MATCH.
1413 @param FormSet Formset which contains this opcode.
1414 @param Result Evaluation result for this opcode.
1416 @retval EFI_SUCCESS Opcode evaluation success.
1417 @retval Other Opcode evaluation failed.
1422 IN FORM_BROWSER_FORMSET
*FormSet
,
1423 OUT EFI_HII_VALUE
*Result
1427 EFI_HII_VALUE Value
[2];
1432 // String[0] - The string to search
1433 // String[1] - pattern
1437 Status
= EFI_SUCCESS
;
1438 ZeroMem (Value
, sizeof (Value
));
1440 Status
= PopExpression (&Value
[0]);
1441 if (EFI_ERROR (Status
)) {
1445 Status
= PopExpression (&Value
[1]);
1446 if (EFI_ERROR (Status
)) {
1450 for (Index
= 0; Index
< 2; Index
++) {
1451 if (Value
[Index
].Type
!= EFI_IFR_TYPE_STRING
) {
1452 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1453 Status
= EFI_SUCCESS
;
1457 String
[Index
] = GetToken (Value
[Index
].Value
.string
, FormSet
->HiiHandle
);
1458 if (String
[Index
] == NULL
) {
1459 Status
= EFI_NOT_FOUND
;
1464 Result
->Type
= EFI_IFR_TYPE_BOOLEAN
;
1465 Result
->Value
.b
= mUnicodeCollation
->MetaiMatch (mUnicodeCollation
, String
[0], String
[1]);
1468 if (String
[0] != NULL
) {
1469 FreePool (String
[0]);
1471 if (String
[1] != NULL
) {
1472 FreePool (String
[1]);
1479 Evaluate opcode EFI_IFR_MATCH2.
1481 @param FormSet Formset which contains this opcode.
1482 @param SyntaxType Syntax type for match2.
1483 @param Result Evaluation result for this opcode.
1485 @retval EFI_SUCCESS Opcode evaluation success.
1486 @retval Other Opcode evaluation failed.
1491 IN FORM_BROWSER_FORMSET
*FormSet
,
1492 IN EFI_GUID
*SyntaxType
,
1493 OUT EFI_HII_VALUE
*Result
1497 EFI_HII_VALUE Value
[2];
1501 EFI_HANDLE
*HandleBuffer
;
1503 EFI_REGULAR_EXPRESSION_PROTOCOL
*RegularExpressionProtocol
;
1504 UINTN RegExSyntaxTypeListSize
;
1505 EFI_REGEX_SYNTAX_TYPE
*RegExSyntaxTypeList
;
1506 UINTN CapturesCount
;
1509 // String[0] - The string to search
1510 // String[1] - pattern
1514 HandleBuffer
= NULL
;
1515 RegExSyntaxTypeList
= NULL
;
1516 Status
= EFI_SUCCESS
;
1517 ZeroMem (Value
, sizeof (Value
));
1519 Status
= PopExpression (&Value
[0]);
1520 if (EFI_ERROR (Status
)) {
1524 Status
= PopExpression (&Value
[1]);
1525 if (EFI_ERROR (Status
)) {
1529 for (Index
= 0; Index
< 2; Index
++) {
1530 if (Value
[Index
].Type
!= EFI_IFR_TYPE_STRING
) {
1531 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1532 Status
= EFI_SUCCESS
;
1536 String
[Index
] = GetToken (Value
[Index
].Value
.string
, FormSet
->HiiHandle
);
1537 if (String
[Index
] == NULL
) {
1538 Status
= EFI_NOT_FOUND
;
1544 HandleBuffer
= NULL
;
1545 Status
= gBS
->LocateHandle(
1547 &gEfiRegularExpressionProtocolGuid
,
1551 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1552 HandleBuffer
= AllocateZeroPool(BufferSize
);
1553 if (HandleBuffer
== NULL
) {
1554 Status
= EFI_OUT_OF_RESOURCES
;
1557 Status
= gBS
->LocateHandle(
1559 &gEfiRegularExpressionProtocolGuid
,
1566 if (EFI_ERROR (Status
)) {
1567 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1568 Status
= EFI_SUCCESS
;
1572 ASSERT (HandleBuffer
!= NULL
);
1573 for ( Index
= 0; Index
< BufferSize
/ sizeof(EFI_HANDLE
); Index
++) {
1574 Status
= gBS
->HandleProtocol (
1575 HandleBuffer
[Index
],
1576 &gEfiRegularExpressionProtocolGuid
,
1577 (VOID
**)&RegularExpressionProtocol
1579 if (EFI_ERROR (Status
)) {
1583 RegExSyntaxTypeListSize
= 0;
1584 RegExSyntaxTypeList
= NULL
;
1586 Status
= RegularExpressionProtocol
->GetInfo (
1587 RegularExpressionProtocol
,
1588 &RegExSyntaxTypeListSize
,
1591 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1592 RegExSyntaxTypeList
= AllocateZeroPool(RegExSyntaxTypeListSize
);
1593 if (RegExSyntaxTypeList
== NULL
) {
1594 Status
= EFI_OUT_OF_RESOURCES
;
1597 Status
= RegularExpressionProtocol
->GetInfo (
1598 RegularExpressionProtocol
,
1599 &RegExSyntaxTypeListSize
,
1602 } else if (EFI_ERROR (Status
)) {
1606 for (GuidIndex
= 0; GuidIndex
< RegExSyntaxTypeListSize
/ sizeof(EFI_GUID
); GuidIndex
++) {
1607 if (CompareGuid (&RegExSyntaxTypeList
[GuidIndex
], SyntaxType
)) {
1609 // Find the match type, return the value.
1611 Result
->Type
= EFI_IFR_TYPE_BOOLEAN
;
1612 Status
= RegularExpressionProtocol
->MatchString (
1613 RegularExpressionProtocol
,
1625 if (RegExSyntaxTypeList
!= NULL
) {
1626 FreePool (RegExSyntaxTypeList
);
1631 // Type specified by SyntaxType is not supported
1632 // in any of the EFI_REGULAR_EXPRESSION_PROTOCOL instances.
1634 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1635 Status
= EFI_SUCCESS
;
1638 if (String
[0] != NULL
) {
1639 FreePool (String
[0]);
1641 if (String
[1] != NULL
) {
1642 FreePool (String
[1]);
1644 if (RegExSyntaxTypeList
!= NULL
) {
1645 FreePool (RegExSyntaxTypeList
);
1647 if (HandleBuffer
!= NULL
) {
1648 FreePool (HandleBuffer
);
1654 Evaluate opcode EFI_IFR_FIND.
1656 @param FormSet Formset which contains this opcode.
1657 @param Format Case sensitive or insensitive.
1658 @param Result Evaluation result for this opcode.
1660 @retval EFI_SUCCESS Opcode evaluation success.
1661 @retval Other Opcode evaluation failed.
1666 IN FORM_BROWSER_FORMSET
*FormSet
,
1668 OUT EFI_HII_VALUE
*Result
1672 EFI_HII_VALUE Value
[3];
1678 ZeroMem (Value
, sizeof (Value
));
1680 if (Format
> EFI_IFR_FF_CASE_INSENSITIVE
) {
1681 return EFI_INVALID_PARAMETER
;
1684 Status
= PopExpression (&Value
[0]);
1685 if (EFI_ERROR (Status
)) {
1689 Status
= PopExpression (&Value
[1]);
1690 if (EFI_ERROR (Status
)) {
1694 Status
= PopExpression (&Value
[2]);
1695 if (EFI_ERROR (Status
)) {
1699 if (Value
[0].Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1700 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1703 Base
= (UINTN
) Value
[0].Value
.u64
;
1706 // String[0] - sub-string
1707 // String[1] - The string to search
1711 for (Index
= 0; Index
< 2; Index
++) {
1712 if (Value
[Index
+ 1].Type
!= EFI_IFR_TYPE_STRING
) {
1713 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1714 Status
= EFI_SUCCESS
;
1718 String
[Index
] = GetToken (Value
[Index
+ 1].Value
.string
, FormSet
->HiiHandle
);
1719 if (String
[Index
] == NULL
) {
1720 Status
= EFI_NOT_FOUND
;
1724 if (Format
== EFI_IFR_FF_CASE_INSENSITIVE
) {
1726 // Case insensitive, convert both string to upper case
1728 IfrStrToUpper (String
[Index
]);
1732 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1733 if (Base
>= StrLen (String
[1])) {
1734 Result
->Value
.u64
= 0xFFFFFFFFFFFFFFFFULL
;
1736 StringPtr
= StrStr (String
[1] + Base
, String
[0]);
1737 Result
->Value
.u64
= (StringPtr
== NULL
) ? 0xFFFFFFFFFFFFFFFFULL
: (StringPtr
- String
[1]);
1741 if (String
[0] != NULL
) {
1742 FreePool (String
[0]);
1744 if (String
[1] != NULL
) {
1745 FreePool (String
[1]);
1753 Evaluate opcode EFI_IFR_MID.
1755 @param FormSet Formset which contains this opcode.
1756 @param Result Evaluation result for this opcode.
1758 @retval EFI_SUCCESS Opcode evaluation success.
1759 @retval Other Opcode evaluation failed.
1764 IN FORM_BROWSER_FORMSET
*FormSet
,
1765 OUT EFI_HII_VALUE
*Result
1769 EFI_HII_VALUE Value
[3];
1777 ZeroMem (Value
, sizeof (Value
));
1779 Status
= PopExpression (&Value
[0]);
1780 if (EFI_ERROR (Status
)) {
1784 Status
= PopExpression (&Value
[1]);
1785 if (EFI_ERROR (Status
)) {
1789 Status
= PopExpression (&Value
[2]);
1790 if (EFI_ERROR (Status
)) {
1794 if (Value
[0].Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1795 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1798 Length
= (UINTN
) Value
[0].Value
.u64
;
1800 if (Value
[1].Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1801 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
;
1810 if (Value
[2].Type
== EFI_IFR_TYPE_STRING
) {
1811 String
= GetToken (Value
[2].Value
.string
, FormSet
->HiiHandle
);
1812 if (String
== NULL
) {
1813 return EFI_NOT_FOUND
;
1816 if (Length
== 0 || Base
>= StrLen (String
)) {
1817 SubString
= gEmptyString
;
1819 SubString
= String
+ Base
;
1820 if ((Base
+ Length
) < StrLen (String
)) {
1821 SubString
[Length
] = L
'\0';
1825 Result
->Type
= EFI_IFR_TYPE_STRING
;
1826 Result
->Value
.string
= NewString (SubString
, FormSet
->HiiHandle
);
1830 BufferLen
= GetLengthForValue (&Value
[2]);
1831 Buffer
= GetBufferForValue (&Value
[2]);
1833 Result
->Type
= EFI_IFR_TYPE_BUFFER
;
1834 if (Length
== 0 || Base
>= BufferLen
) {
1835 Result
->BufferLen
= 0;
1836 Result
->Buffer
= NULL
;
1838 Result
->BufferLen
= (UINT16
)((BufferLen
- Base
) < Length
? (BufferLen
- Base
) : Length
);
1839 Result
->Buffer
= AllocateZeroPool (Result
->BufferLen
);
1840 ASSERT (Result
->Buffer
!= NULL
);
1841 CopyMem (Result
->Buffer
, &Buffer
[Base
], Result
->BufferLen
);
1844 if (Value
[2].Type
== EFI_IFR_TYPE_BUFFER
) {
1845 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
;
1899 Count
= (UINTN
) Value
[0].Value
.u64
;
1902 // String[0] - Delimiter
1903 // String[1] - The string to search
1907 for (Index
= 0; Index
< 2; Index
++) {
1908 if (Value
[Index
+ 1].Type
!= EFI_IFR_TYPE_STRING
) {
1909 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1910 Status
= EFI_SUCCESS
;
1914 String
[Index
] = GetToken (Value
[Index
+ 1].Value
.string
, FormSet
->HiiHandle
);
1915 if (String
[Index
] == NULL
) {
1916 Status
= EFI_NOT_FOUND
;
1921 Delimiter
= String
[0];
1922 SubString
= String
[1];
1924 SubString
= StrStr (SubString
, Delimiter
);
1925 if (SubString
!= NULL
) {
1927 // Skip over the delimiter
1929 SubString
= SubString
+ StrLen (Delimiter
);
1936 if (SubString
== NULL
) {
1938 // nth delimited sub-string not found, push an empty string
1940 SubString
= gEmptyString
;
1943 // Put a NULL terminator for nth delimited sub-string
1945 StringPtr
= StrStr (SubString
, Delimiter
);
1946 if (StringPtr
!= NULL
) {
1951 Result
->Type
= EFI_IFR_TYPE_STRING
;
1952 Result
->Value
.string
= NewString (SubString
, FormSet
->HiiHandle
);
1955 if (String
[0] != NULL
) {
1956 FreePool (String
[0]);
1958 if (String
[1] != NULL
) {
1959 FreePool (String
[1]);
1967 Evaluate opcode EFI_IFR_SPAN.
1969 @param FormSet Formset which contains this opcode.
1970 @param Flags FIRST_MATCHING or FIRST_NON_MATCHING.
1971 @param Result Evaluation result for this opcode.
1973 @retval EFI_SUCCESS Opcode evaluation success.
1974 @retval Other Opcode evaluation failed.
1979 IN FORM_BROWSER_FORMSET
*FormSet
,
1981 OUT EFI_HII_VALUE
*Result
1985 EFI_HII_VALUE Value
[3];
1993 ZeroMem (Value
, sizeof (Value
));
1995 Status
= PopExpression (&Value
[0]);
1996 if (EFI_ERROR (Status
)) {
2000 Status
= PopExpression (&Value
[1]);
2001 if (EFI_ERROR (Status
)) {
2005 Status
= PopExpression (&Value
[2]);
2006 if (EFI_ERROR (Status
)) {
2010 if (Value
[0].Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
2011 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2014 Base
= (UINTN
) Value
[0].Value
.u64
;
2017 // String[0] - Charset
2018 // String[1] - The string to search
2022 for (Index
= 0; Index
< 2; Index
++) {
2023 if (Value
[Index
+ 1].Type
!= EFI_IFR_TYPE_STRING
) {
2024 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2025 Status
= EFI_SUCCESS
;
2029 String
[Index
] = GetToken (Value
[Index
+ 1].Value
.string
, FormSet
->HiiHandle
);
2030 if (String
[Index
] == NULL
) {
2031 Status
= EFI_NOT_FOUND
;
2036 if (Base
>= StrLen (String
[1])) {
2037 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2038 Status
= EFI_SUCCESS
;
2043 StringPtr
= String
[1] + Base
;
2044 Charset
= String
[0];
2045 while (*StringPtr
!= 0 && !Found
) {
2047 while (Charset
[Index
] != 0) {
2048 if (*StringPtr
>= Charset
[Index
] && *StringPtr
<= Charset
[Index
+ 1]) {
2049 if (Flags
== EFI_IFR_FLAGS_FIRST_MATCHING
) {
2054 if (Flags
== EFI_IFR_FLAGS_FIRST_NON_MATCHING
) {
2060 // Skip characters pair representing low-end of a range and high-end of a range
2070 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
2071 Result
->Value
.u64
= StringPtr
- String
[1];
2074 if (String
[0] != NULL
) {
2075 FreePool (String
[0]);
2077 if (String
[1] != NULL
) {
2078 FreePool (String
[1]);
2086 Zero extend integer/boolean/date/time to UINT64 for comparing.
2088 @param Value HII Value to be converted.
2093 IN EFI_HII_VALUE
*Value
2099 switch (Value
->Type
) {
2100 case EFI_IFR_TYPE_NUM_SIZE_8
:
2101 Temp
= Value
->Value
.u8
;
2104 case EFI_IFR_TYPE_NUM_SIZE_16
:
2105 Temp
= Value
->Value
.u16
;
2108 case EFI_IFR_TYPE_NUM_SIZE_32
:
2109 Temp
= Value
->Value
.u32
;
2112 case EFI_IFR_TYPE_BOOLEAN
:
2113 Temp
= Value
->Value
.b
;
2116 case EFI_IFR_TYPE_TIME
:
2117 Temp
= Value
->Value
.u32
& 0xffffff;
2120 case EFI_IFR_TYPE_DATE
:
2121 Temp
= Value
->Value
.u32
;
2128 Value
->Value
.u64
= Temp
;
2132 Get UINT64 type value.
2134 @param Value Input Hii value.
2136 @retval UINT64 Return the UINT64 type value.
2141 IN EFI_HII_VALUE
*Value
2148 switch (Value
->Type
) {
2149 case EFI_IFR_TYPE_NUM_SIZE_8
:
2150 RetVal
= Value
->Value
.u8
;
2153 case EFI_IFR_TYPE_NUM_SIZE_16
:
2154 RetVal
= Value
->Value
.u16
;
2157 case EFI_IFR_TYPE_NUM_SIZE_32
:
2158 RetVal
= Value
->Value
.u32
;
2161 case EFI_IFR_TYPE_BOOLEAN
:
2162 RetVal
= Value
->Value
.b
;
2165 case EFI_IFR_TYPE_DATE
:
2166 RetVal
= *(UINT64
*) &Value
->Value
.date
;
2169 case EFI_IFR_TYPE_TIME
:
2170 RetVal
= (*(UINT64
*) &Value
->Value
.time
) & 0xffffff;
2174 RetVal
= Value
->Value
.u64
;
2182 Compare two Hii value.
2184 @param Value1 Expression value to compare on left-hand.
2185 @param Value2 Expression value to compare on right-hand.
2186 @param Result Return value after compare.
2187 retval 0 Two operators equal.
2188 return Positive value if Value1 is greater than Value2.
2189 retval Negative value if Value1 is less than Value2.
2190 @param HiiHandle Only required for string compare.
2192 @retval other Could not perform compare on two values.
2193 @retval EFI_SUCCESS Compare the value success.
2198 IN EFI_HII_VALUE
*Value1
,
2199 IN EFI_HII_VALUE
*Value2
,
2201 IN EFI_HII_HANDLE HiiHandle OPTIONAL
2213 if (Value1
->Type
== EFI_IFR_TYPE_STRING
&& Value2
->Type
== EFI_IFR_TYPE_STRING
) {
2214 if (Value1
->Value
.string
== 0 || Value2
->Value
.string
== 0) {
2216 // StringId 0 is reserved
2218 return EFI_INVALID_PARAMETER
;
2221 if (Value1
->Value
.string
== Value2
->Value
.string
) {
2226 Str1
= GetToken (Value1
->Value
.string
, HiiHandle
);
2231 return EFI_NOT_FOUND
;
2234 Str2
= GetToken (Value2
->Value
.string
, HiiHandle
);
2237 return EFI_NOT_FOUND
;
2240 *Result
= StrCmp (Str1
, Str2
);
2249 // Take types(date, time, ref, buffer) as buffer
2251 if (IsTypeInBuffer(Value1
) && IsTypeInBuffer(Value2
)) {
2252 Buf1
= GetBufferForValue(Value1
);
2253 Buf1Len
= GetLengthForValue(Value1
);
2254 Buf2
= GetBufferForValue(Value2
);
2255 Buf2Len
= GetLengthForValue(Value2
);
2257 Len
= Buf1Len
> Buf2Len
? Buf2Len
: Buf1Len
;
2258 *Result
= CompareMem (Buf1
, Buf2
, Len
);
2259 if ((*Result
== 0) && (Buf1Len
!= Buf2Len
)) {
2261 // In this case, means base on samll number buffer, the data is same
2262 // So which value has more data, which value is bigger.
2264 *Result
= Buf1Len
> Buf2Len
? 1 : -1;
2270 // Take types(integer, boolean) as integer
2272 if (IsTypeInUINT64(Value1
) && IsTypeInUINT64(Value2
)) {
2273 Temp64
= HiiValueToUINT64(Value1
) - HiiValueToUINT64(Value2
);
2276 } else if (Temp64
< 0) {
2285 return EFI_UNSUPPORTED
;
2289 Check if current user has the privilege specified by the permissions GUID.
2291 @param[in] Guid A GUID specifying setup access permissions.
2293 @retval TRUE Current user has the privilege.
2294 @retval FALSE Current user does not have the privilege.
2297 CheckUserPrivilege (
2302 EFI_USER_PROFILE_HANDLE UserProfileHandle
;
2303 EFI_USER_INFO_HANDLE UserInfoHandle
;
2304 EFI_USER_INFO
*UserInfo
;
2305 EFI_GUID
*UserPermissionsGuid
;
2307 UINTN AccessControlDataSize
;
2308 EFI_USER_INFO_ACCESS_CONTROL
*AccessControl
;
2311 if (mUserManager
== NULL
) {
2312 Status
= gBS
->LocateProtocol (
2313 &gEfiUserManagerProtocolGuid
,
2315 (VOID
**) &mUserManager
2317 if (EFI_ERROR (Status
)) {
2319 /// If the system does not support user management, then it is assumed that
2320 /// all users have admin privilege and evaluation of each EFI_IFR_SECURITY
2321 /// op-code is always TRUE.
2327 Status
= mUserManager
->Current (mUserManager
, &UserProfileHandle
);
2328 ASSERT_EFI_ERROR (Status
);
2331 /// Enumerate all user information of the current user profile
2332 /// to look for any EFI_USER_INFO_ACCESS_SETUP record.
2335 for (UserInfoHandle
= NULL
;;) {
2336 Status
= mUserManager
->GetNextInfo (mUserManager
, UserProfileHandle
, &UserInfoHandle
);
2337 if (EFI_ERROR (Status
)) {
2342 Status
= mUserManager
->GetInfo (mUserManager
, UserProfileHandle
, UserInfoHandle
, NULL
, &UserInfoSize
);
2343 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
2347 UserInfo
= (EFI_USER_INFO
*) AllocatePool (UserInfoSize
);
2348 if (UserInfo
== NULL
) {
2352 Status
= mUserManager
->GetInfo (mUserManager
, UserProfileHandle
, UserInfoHandle
, UserInfo
, &UserInfoSize
);
2353 if (EFI_ERROR (Status
) ||
2354 UserInfo
->InfoType
!= EFI_USER_INFO_ACCESS_POLICY_RECORD
||
2355 UserInfo
->InfoSize
<= sizeof (EFI_USER_INFO
)) {
2356 FreePool (UserInfo
);
2360 RemainSize
= UserInfo
->InfoSize
- sizeof (EFI_USER_INFO
);
2361 AccessControl
= (EFI_USER_INFO_ACCESS_CONTROL
*)(UserInfo
+ 1);
2362 while (RemainSize
>= sizeof (EFI_USER_INFO_ACCESS_CONTROL
)) {
2363 if (RemainSize
< AccessControl
->Size
|| AccessControl
->Size
< sizeof (EFI_USER_INFO_ACCESS_CONTROL
)) {
2366 if (AccessControl
->Type
== EFI_USER_INFO_ACCESS_SETUP
) {
2368 /// Check if current user has the privilege specified by the permissions GUID.
2371 UserPermissionsGuid
= (EFI_GUID
*)(AccessControl
+ 1);
2372 AccessControlDataSize
= AccessControl
->Size
- sizeof (EFI_USER_INFO_ACCESS_CONTROL
);
2373 while (AccessControlDataSize
>= sizeof (EFI_GUID
)) {
2374 if (CompareGuid (Guid
, UserPermissionsGuid
)) {
2375 FreePool (UserInfo
);
2378 UserPermissionsGuid
++;
2379 AccessControlDataSize
-= sizeof (EFI_GUID
);
2382 RemainSize
-= AccessControl
->Size
;
2383 AccessControl
= (EFI_USER_INFO_ACCESS_CONTROL
*)((UINT8
*)AccessControl
+ AccessControl
->Size
);
2386 FreePool (UserInfo
);
2392 Get question value from the predefined formset.
2394 @param DevicePath The driver's device path which produece the formset data.
2395 @param InputHiiHandle The hii handle associate with the formset data.
2396 @param FormSetGuid The formset guid which include the question.
2397 @param QuestionId The question id which need to get value from.
2398 @param Value The return data about question's value.
2400 @retval TRUE Get the question value success.
2401 @retval FALSE Get the question value failed.
2404 GetQuestionValueFromForm (
2405 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
2406 IN EFI_HII_HANDLE InputHiiHandle
,
2407 IN EFI_GUID
*FormSetGuid
,
2408 IN EFI_QUESTION_ID QuestionId
,
2409 OUT EFI_HII_VALUE
*Value
2413 EFI_HII_HANDLE HiiHandle
;
2414 FORM_BROWSER_STATEMENT
*Question
;
2415 FORM_BROWSER_FORMSET
*FormSet
;
2416 FORM_BROWSER_FORM
*Form
;
2421 // The input parameter DevicePath or InputHiiHandle must have one valid input.
2423 ASSERT ((DevicePath
!= NULL
&& InputHiiHandle
== NULL
) ||
2424 (DevicePath
== NULL
&& InputHiiHandle
!= NULL
) );
2434 if (DevicePath
!= NULL
) {
2435 HiiHandle
= DevicePathToHiiHandle (DevicePath
, FormSetGuid
);
2436 if (HiiHandle
== NULL
) {
2440 HiiHandle
= InputHiiHandle
;
2442 ASSERT (HiiHandle
!= NULL
);
2445 // Get the formset data include this question.
2447 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
2448 ASSERT (FormSet
!= NULL
);
2449 Status
= InitializeFormSet(HiiHandle
, FormSetGuid
, FormSet
);
2450 if (EFI_ERROR (Status
)) {
2456 // Base on the Question Id to get the question info.
2458 Question
= IdToQuestion(FormSet
, NULL
, QuestionId
);
2459 if (Question
== NULL
) {
2465 // Search form in the formset scope
2467 Link
= GetFirstNode (&FormSet
->FormListHead
);
2468 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2469 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2471 Question
= IdToQuestion2 (Form
, QuestionId
);
2472 if (Question
!= NULL
) {
2476 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2479 ASSERT (Form
!= NULL
);
2482 // Get the question value.
2484 Status
= GetQuestionValue(FormSet
, Form
, Question
, GetSetValueWithEditBuffer
);
2485 if (EFI_ERROR (Status
)) {
2490 CopyMem (Value
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
2494 // Clean the formset structure and restore the global parameter.
2496 if (FormSet
!= NULL
) {
2497 DestroyFormSet (FormSet
);
2504 Evaluate the result of a HII expression.
2506 If Expression is NULL, then ASSERT.
2508 @param FormSet FormSet associated with this expression.
2509 @param Form Form associated with this expression.
2510 @param Expression Expression to be evaluated.
2512 @retval EFI_SUCCESS The expression evaluated successfuly
2513 @retval EFI_NOT_FOUND The Question which referenced by a QuestionId
2515 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
2517 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
2518 @retval EFI_INVALID_PARAMETER Syntax error with the Expression
2522 EvaluateExpression (
2523 IN FORM_BROWSER_FORMSET
*FormSet
,
2524 IN FORM_BROWSER_FORM
*Form
,
2525 IN OUT FORM_EXPRESSION
*Expression
2530 EXPRESSION_OPCODE
*OpCode
;
2531 FORM_BROWSER_STATEMENT
*Question
;
2532 FORM_BROWSER_STATEMENT
*Question2
;
2534 EFI_HII_VALUE Data1
;
2535 EFI_HII_VALUE Data2
;
2536 EFI_HII_VALUE Data3
;
2537 FORM_EXPRESSION
*RuleExpression
;
2538 EFI_HII_VALUE
*Value
;
2543 LIST_ENTRY
*SubExpressionLink
;
2544 FORM_EXPRESSION
*SubExpression
;
2551 EFI_HII_VALUE QuestionVal
;
2552 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2557 // Save current stack offset.
2559 StackOffset
= SaveExpressionEvaluationStackOffset ();
2561 ASSERT (Expression
!= NULL
);
2562 Expression
->Result
.Type
= EFI_IFR_TYPE_OTHER
;
2564 Link
= GetFirstNode (&Expression
->OpCodeListHead
);
2565 while (!IsNull (&Expression
->OpCodeListHead
, Link
)) {
2566 OpCode
= EXPRESSION_OPCODE_FROM_LINK (Link
);
2568 Link
= GetNextNode (&Expression
->OpCodeListHead
, Link
);
2570 ZeroMem (&Data1
, sizeof (EFI_HII_VALUE
));
2571 ZeroMem (&Data2
, sizeof (EFI_HII_VALUE
));
2572 ZeroMem (&Data3
, sizeof (EFI_HII_VALUE
));
2575 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
2576 Status
= EFI_SUCCESS
;
2578 switch (OpCode
->Operand
) {
2580 // Built-in functions
2582 case EFI_IFR_EQ_ID_VAL_OP
:
2583 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
2584 if (Question
== NULL
) {
2585 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2589 Status
= CompareHiiValue (&Question
->HiiValue
, &OpCode
->Value
, &Result
, NULL
);
2590 if (Status
== EFI_UNSUPPORTED
) {
2591 Status
= EFI_SUCCESS
;
2592 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2596 if (EFI_ERROR (Status
)) {
2599 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
2602 case EFI_IFR_EQ_ID_ID_OP
:
2603 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
2604 if (Question
== NULL
) {
2605 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2609 Question2
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId2
);
2610 if (Question2
== NULL
) {
2611 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2615 Status
= CompareHiiValue (&Question
->HiiValue
, &Question2
->HiiValue
, &Result
, FormSet
->HiiHandle
);
2616 if (Status
== EFI_UNSUPPORTED
) {
2617 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2618 Status
= EFI_SUCCESS
;
2621 if (EFI_ERROR (Status
)) {
2624 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
2627 case EFI_IFR_EQ_ID_VAL_LIST_OP
:
2628 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
2629 if (Question
== NULL
) {
2630 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2634 Value
->Value
.b
= FALSE
;
2635 for (Index
=0; Index
< OpCode
->ListLength
; Index
++) {
2636 if (Question
->HiiValue
.Value
.u16
== OpCode
->ValueList
[Index
]) {
2637 Value
->Value
.b
= TRUE
;
2643 case EFI_IFR_DUP_OP
:
2644 Status
= PopExpression (Value
);
2645 if (EFI_ERROR (Status
)) {
2649 Status
= PushExpression (Value
);
2652 case EFI_IFR_QUESTION_REF1_OP
:
2653 case EFI_IFR_THIS_OP
:
2654 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
2655 if (Question
== NULL
) {
2656 Status
= EFI_NOT_FOUND
;
2660 Value
= &Question
->HiiValue
;
2663 case EFI_IFR_SECURITY_OP
:
2664 Value
->Value
.b
= CheckUserPrivilege (&OpCode
->Guid
);
2667 case EFI_IFR_GET_OP
:
2669 // Get Value from VarStore buffer, EFI VarStore, Name/Value VarStore.
2671 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2672 Value
->Value
.u8
= 0;
2673 if (OpCode
->VarStorage
!= NULL
) {
2674 switch (OpCode
->VarStorage
->Type
) {
2675 case EFI_HII_VARSTORE_BUFFER
:
2676 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
2678 // Get value from Edit Buffer
2680 Value
->Type
= OpCode
->ValueType
;
2681 CopyMem (&Value
->Value
, OpCode
->VarStorage
->EditBuffer
+ OpCode
->VarStoreInfo
.VarOffset
, OpCode
->ValueWidth
);
2683 case EFI_HII_VARSTORE_NAME_VALUE
:
2684 if (OpCode
->ValueType
!= EFI_IFR_TYPE_STRING
) {
2686 // Get value from string except for STRING value.
2688 Status
= GetValueByName (OpCode
->VarStorage
, OpCode
->ValueName
, &StrPtr
, GetSetValueWithEditBuffer
);
2689 if (!EFI_ERROR (Status
)) {
2690 ASSERT (StrPtr
!= NULL
);
2691 TempLength
= StrLen (StrPtr
);
2692 if (OpCode
->ValueWidth
>= ((TempLength
+ 1) / 2)) {
2693 Value
->Type
= OpCode
->ValueType
;
2694 TempBuffer
= (UINT8
*) &Value
->Value
;
2695 ZeroMem (TempStr
, sizeof (TempStr
));
2696 for (Index
= 0; Index
< TempLength
; Index
++) {
2697 TempStr
[0] = StrPtr
[TempLength
- Index
- 1];
2698 DigitUint8
= (UINT8
) StrHexToUint64 (TempStr
);
2699 if ((Index
& 1) == 0) {
2700 TempBuffer
[Index
/2] = DigitUint8
;
2702 TempBuffer
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + TempBuffer
[Index
/2]);
2709 case EFI_HII_VARSTORE_EFI_VARIABLE
:
2711 // Get value from variable.
2713 TempLength
= OpCode
->ValueWidth
;
2714 Value
->Type
= OpCode
->ValueType
;
2715 Status
= gRT
->GetVariable (
2717 &OpCode
->VarStorage
->Guid
,
2722 if (EFI_ERROR (Status
)) {
2723 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2724 Value
->Value
.u8
= 0;
2729 // Not recognize storage.
2731 Status
= EFI_UNSUPPORTED
;
2736 // For Time/Date Data
2738 if (OpCode
->ValueType
!= EFI_IFR_TYPE_DATE
&& OpCode
->ValueType
!= EFI_IFR_TYPE_TIME
) {
2740 // Only support Data/Time data when storage doesn't exist.
2742 Status
= EFI_UNSUPPORTED
;
2745 Status
= gRT
->GetTime (&EfiTime
, NULL
);
2746 if (!EFI_ERROR (Status
)) {
2747 if (OpCode
->ValueType
== EFI_IFR_TYPE_DATE
) {
2748 switch (OpCode
->VarStoreInfo
.VarOffset
) {
2750 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_16
;
2751 Value
->Value
.u16
= EfiTime
.Year
;
2754 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
2755 Value
->Value
.u8
= EfiTime
.Month
;
2758 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
2759 Value
->Value
.u8
= EfiTime
.Day
;
2763 // Invalid Date field.
2765 Status
= EFI_INVALID_PARAMETER
;
2769 switch (OpCode
->VarStoreInfo
.VarOffset
) {
2771 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
2772 Value
->Value
.u8
= EfiTime
.Hour
;
2775 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
2776 Value
->Value
.u8
= EfiTime
.Minute
;
2779 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
2780 Value
->Value
.u8
= EfiTime
.Second
;
2784 // Invalid Time field.
2786 Status
= EFI_INVALID_PARAMETER
;
2795 case EFI_IFR_QUESTION_REF3_OP
:
2797 // EFI_IFR_QUESTION_REF3
2798 // Pop an expression from the expression stack
2800 Status
= PopExpression (Value
);
2801 if (EFI_ERROR (Status
)) {
2806 // Validate the expression value
2808 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
2809 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2813 if (OpCode
->DevicePath
!= 0) {
2814 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2816 StrPtr
= GetToken (OpCode
->DevicePath
, FormSet
->HiiHandle
);
2817 if (StrPtr
!= NULL
&& mPathFromText
!= NULL
) {
2818 DevicePath
= mPathFromText
->ConvertTextToDevicePath(StrPtr
);
2819 if (DevicePath
!= NULL
&& GetQuestionValueFromForm(DevicePath
, NULL
, &OpCode
->Guid
, Value
->Value
.u16
, &QuestionVal
)) {
2820 Value
= &QuestionVal
;
2822 if (DevicePath
!= NULL
) {
2823 FreePool (DevicePath
);
2827 if (StrPtr
!= NULL
) {
2830 } else if (IsZeroGuid (&OpCode
->Guid
)) {
2831 if (!GetQuestionValueFromForm(NULL
, FormSet
->HiiHandle
, &OpCode
->Guid
, Value
->Value
.u16
, &QuestionVal
)){
2832 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2835 Value
= &QuestionVal
;
2837 Question
= IdToQuestion (FormSet
, Form
, Value
->Value
.u16
);
2838 if (Question
== NULL
) {
2839 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2844 // push the questions' value on to the expression stack
2846 Value
= &Question
->HiiValue
;
2850 case EFI_IFR_RULE_REF_OP
:
2852 // Find expression for this rule
2854 RuleExpression
= RuleIdToExpression (Form
, OpCode
->RuleId
);
2855 if (RuleExpression
== NULL
) {
2856 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2861 // Evaluate this rule expression
2863 Status
= EvaluateExpression (FormSet
, Form
, RuleExpression
);
2864 if (EFI_ERROR (Status
) || RuleExpression
->Result
.Type
== EFI_IFR_TYPE_UNDEFINED
) {
2865 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2869 Value
= &RuleExpression
->Result
;
2872 case EFI_IFR_STRING_REF1_OP
:
2873 Value
->Type
= EFI_IFR_TYPE_STRING
;
2874 Value
->Value
.string
= OpCode
->Value
.Value
.string
;
2880 case EFI_IFR_TRUE_OP
:
2881 case EFI_IFR_FALSE_OP
:
2882 case EFI_IFR_ONE_OP
:
2883 case EFI_IFR_ONES_OP
:
2884 case EFI_IFR_UINT8_OP
:
2885 case EFI_IFR_UINT16_OP
:
2886 case EFI_IFR_UINT32_OP
:
2887 case EFI_IFR_UINT64_OP
:
2888 case EFI_IFR_UNDEFINED_OP
:
2889 case EFI_IFR_VERSION_OP
:
2890 case EFI_IFR_ZERO_OP
:
2891 Value
= &OpCode
->Value
;
2897 case EFI_IFR_LENGTH_OP
:
2898 Status
= PopExpression (Value
);
2899 if (EFI_ERROR (Status
)) {
2902 if (Value
->Type
!= EFI_IFR_TYPE_STRING
&& !IsTypeInBuffer (Value
)) {
2903 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2907 if (Value
->Type
== EFI_IFR_TYPE_STRING
) {
2908 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->HiiHandle
);
2909 if (StrPtr
== NULL
) {
2910 Status
= EFI_INVALID_PARAMETER
;
2914 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
2915 Value
->Value
.u64
= StrLen (StrPtr
);
2918 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
2919 Value
->Value
.u64
= GetLengthForValue(Value
);
2920 FreePool (Value
->Buffer
);
2924 case EFI_IFR_NOT_OP
:
2925 Status
= PopExpression (Value
);
2926 if (EFI_ERROR (Status
)) {
2929 if (Value
->Type
!= EFI_IFR_TYPE_BOOLEAN
) {
2930 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2933 Value
->Value
.b
= (BOOLEAN
) (!Value
->Value
.b
);
2936 case EFI_IFR_QUESTION_REF2_OP
:
2938 // Pop an expression from the expression stack
2940 Status
= PopExpression (Value
);
2941 if (EFI_ERROR (Status
)) {
2946 // Validate the expression value
2948 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
2949 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2953 Question
= IdToQuestion (FormSet
, Form
, Value
->Value
.u16
);
2954 if (Question
== NULL
) {
2955 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2959 Value
= &Question
->HiiValue
;
2962 case EFI_IFR_STRING_REF2_OP
:
2964 // Pop an expression from the expression stack
2966 Status
= PopExpression (Value
);
2967 if (EFI_ERROR (Status
)) {
2972 // Validate the expression value
2974 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
2975 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2979 Value
->Type
= EFI_IFR_TYPE_STRING
;
2980 StrPtr
= GetToken (Value
->Value
.u16
, FormSet
->HiiHandle
);
2981 if (StrPtr
== NULL
) {
2983 // If String not exit, push an empty string
2985 Value
->Value
.string
= NewString (gEmptyString
, FormSet
->HiiHandle
);
2987 Index
= (UINT16
) Value
->Value
.u64
;
2988 Value
->Value
.string
= Index
;
2993 case EFI_IFR_TO_BOOLEAN_OP
:
2995 // Pop an expression from the expression stack
2997 Status
= PopExpression (Value
);
2998 if (EFI_ERROR (Status
)) {
3003 // Convert an expression to a Boolean
3005 if (Value
->Type
<= EFI_IFR_TYPE_DATE
) {
3007 // When converting from an unsigned integer, zero will be converted to
3008 // FALSE and any other value will be converted to TRUE.
3010 Value
->Value
.b
= (BOOLEAN
) (HiiValueToUINT64(Value
) != 0);
3012 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
3013 } else if (Value
->Type
== EFI_IFR_TYPE_STRING
) {
3015 // When converting from a string, if case-insensitive compare
3016 // with "true" is True, then push True. If a case-insensitive compare
3017 // with "false" is True, then push False. Otherwise, push Undefined.
3019 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->HiiHandle
);
3020 if (StrPtr
== NULL
) {
3021 Status
= EFI_INVALID_PARAMETER
;
3025 IfrStrToUpper (StrPtr
);
3026 if (StrCmp (StrPtr
, L
"TRUE") == 0){
3027 Value
->Value
.b
= TRUE
;
3028 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
3029 } else if (StrCmp (StrPtr
, L
"FALSE") == 0) {
3030 Value
->Value
.b
= FALSE
;
3031 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
3033 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3036 } else if (Value
->Type
== EFI_IFR_TYPE_BUFFER
) {
3038 // When converting from a buffer, if the buffer is all zeroes,
3039 // then push False. Otherwise push True.
3041 for (Index
=0; Index
< Value
->BufferLen
; Index
++) {
3042 if (Value
->Buffer
[Index
] != 0) {
3047 if (Index
>= Value
->BufferLen
) {
3048 Value
->Value
.b
= FALSE
;
3050 Value
->Value
.b
= TRUE
;
3052 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
3053 FreePool (Value
->Buffer
);
3057 case EFI_IFR_TO_STRING_OP
:
3058 Status
= IfrToString (FormSet
, OpCode
->Format
, Value
);
3061 case EFI_IFR_TO_UINT_OP
:
3062 Status
= IfrToUint (FormSet
, Value
);
3065 case EFI_IFR_TO_LOWER_OP
:
3066 case EFI_IFR_TO_UPPER_OP
:
3067 Status
= InitializeUnicodeCollationProtocol ();
3068 if (EFI_ERROR (Status
)) {
3072 Status
= PopExpression (Value
);
3073 if (EFI_ERROR (Status
)) {
3077 if (Value
->Type
!= EFI_IFR_TYPE_STRING
) {
3078 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3082 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->HiiHandle
);
3083 if (StrPtr
== NULL
) {
3084 Status
= EFI_NOT_FOUND
;
3088 if (OpCode
->Operand
== EFI_IFR_TO_LOWER_OP
) {
3089 mUnicodeCollation
->StrLwr (mUnicodeCollation
, StrPtr
);
3091 mUnicodeCollation
->StrUpr (mUnicodeCollation
, StrPtr
);
3093 Value
->Value
.string
= NewString (StrPtr
, FormSet
->HiiHandle
);
3097 case EFI_IFR_BITWISE_NOT_OP
:
3099 // Pop an expression from the expression stack
3101 Status
= PopExpression (Value
);
3102 if (EFI_ERROR (Status
)) {
3105 if (Value
->Type
> EFI_IFR_TYPE_DATE
) {
3106 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3110 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
3111 Value
->Value
.u64
= ~ HiiValueToUINT64(Value
);
3114 case EFI_IFR_SET_OP
:
3116 // Pop an expression from the expression stack
3118 Status
= PopExpression (Value
);
3119 if (EFI_ERROR (Status
)) {
3122 Data1
.Type
= EFI_IFR_TYPE_BOOLEAN
;
3123 Data1
.Value
.b
= FALSE
;
3125 // Set value to var storage buffer
3127 if (OpCode
->VarStorage
!= NULL
) {
3128 switch (OpCode
->VarStorage
->Type
) {
3129 case EFI_HII_VARSTORE_BUFFER
:
3130 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
3131 CopyMem (OpCode
->VarStorage
->EditBuffer
+ OpCode
->VarStoreInfo
.VarOffset
, &Value
->Value
, OpCode
->ValueWidth
);
3132 Data1
.Value
.b
= TRUE
;
3134 case EFI_HII_VARSTORE_NAME_VALUE
:
3135 if (OpCode
->ValueType
!= EFI_IFR_TYPE_STRING
) {
3136 NameValue
= AllocateZeroPool ((OpCode
->ValueWidth
* 2 + 1) * sizeof (CHAR16
));
3137 ASSERT (NameValue
!= NULL
);
3139 // Convert Buffer to Hex String
3141 TempBuffer
= (UINT8
*) &Value
->Value
+ OpCode
->ValueWidth
- 1;
3143 for (Index
= 0; Index
< OpCode
->ValueWidth
; Index
++, TempBuffer
--) {
3144 UnicodeValueToStringS (
3146 (OpCode
->ValueWidth
* 2 + 1) * sizeof (CHAR16
) - ((UINTN
)StrPtr
- (UINTN
)NameValue
),
3147 PREFIX_ZERO
| RADIX_HEX
,
3151 StrPtr
+= StrnLenS (StrPtr
, OpCode
->ValueWidth
* 2 + 1 - ((UINTN
)StrPtr
- (UINTN
)NameValue
) / sizeof (CHAR16
));
3153 Status
= SetValueByName (OpCode
->VarStorage
, OpCode
->ValueName
, NameValue
, GetSetValueWithEditBuffer
, NULL
);
3154 FreePool (NameValue
);
3155 if (!EFI_ERROR (Status
)) {
3156 Data1
.Value
.b
= TRUE
;
3160 case EFI_HII_VARSTORE_EFI_VARIABLE
:
3161 Status
= gRT
->SetVariable (
3163 &OpCode
->VarStorage
->Guid
,
3164 OpCode
->VarStorage
->Attributes
,
3168 if (!EFI_ERROR (Status
)) {
3169 Data1
.Value
.b
= TRUE
;
3174 // Not recognize storage.
3176 Status
= EFI_UNSUPPORTED
;
3181 // For Time/Date Data
3183 if (OpCode
->ValueType
!= EFI_IFR_TYPE_DATE
&& OpCode
->ValueType
!= EFI_IFR_TYPE_TIME
) {
3185 // Only support Data/Time data when storage doesn't exist.
3187 Status
= EFI_UNSUPPORTED
;
3190 Status
= gRT
->GetTime (&EfiTime
, NULL
);
3191 if (!EFI_ERROR (Status
)) {
3192 if (OpCode
->ValueType
== EFI_IFR_TYPE_DATE
) {
3193 switch (OpCode
->VarStoreInfo
.VarOffset
) {
3195 EfiTime
.Year
= Value
->Value
.u16
;
3198 EfiTime
.Month
= Value
->Value
.u8
;
3201 EfiTime
.Day
= Value
->Value
.u8
;
3205 // Invalid Date field.
3207 Status
= EFI_INVALID_PARAMETER
;
3211 switch (OpCode
->VarStoreInfo
.VarOffset
) {
3213 EfiTime
.Hour
= Value
->Value
.u8
;
3216 EfiTime
.Minute
= Value
->Value
.u8
;
3219 EfiTime
.Second
= Value
->Value
.u8
;
3223 // Invalid Time field.
3225 Status
= EFI_INVALID_PARAMETER
;
3229 Status
= gRT
->SetTime (&EfiTime
);
3230 if (!EFI_ERROR (Status
)) {
3231 Data1
.Value
.b
= TRUE
;
3241 case EFI_IFR_ADD_OP
:
3242 case EFI_IFR_SUBTRACT_OP
:
3243 case EFI_IFR_MULTIPLY_OP
:
3244 case EFI_IFR_DIVIDE_OP
:
3245 case EFI_IFR_MODULO_OP
:
3246 case EFI_IFR_BITWISE_AND_OP
:
3247 case EFI_IFR_BITWISE_OR_OP
:
3248 case EFI_IFR_SHIFT_LEFT_OP
:
3249 case EFI_IFR_SHIFT_RIGHT_OP
:
3251 // Pop an expression from the expression stack
3253 Status
= PopExpression (&Data2
);
3254 if (EFI_ERROR (Status
)) {
3259 // Pop another expression from the expression stack
3261 Status
= PopExpression (&Data1
);
3262 if (EFI_ERROR (Status
)) {
3266 if (Data2
.Type
> EFI_IFR_TYPE_DATE
) {
3267 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3272 if (Data1
.Type
> EFI_IFR_TYPE_DATE
) {
3273 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3277 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
3279 switch (OpCode
->Operand
) {
3280 case EFI_IFR_ADD_OP
:
3281 Value
->Value
.u64
= HiiValueToUINT64(&Data1
) + HiiValueToUINT64(&Data2
);
3284 case EFI_IFR_SUBTRACT_OP
:
3285 Value
->Value
.u64
= HiiValueToUINT64(&Data1
) - HiiValueToUINT64(&Data2
);
3288 case EFI_IFR_MULTIPLY_OP
:
3289 Value
->Value
.u64
= MultU64x32 (HiiValueToUINT64(&Data1
), (UINT32
) HiiValueToUINT64(&Data2
));
3292 case EFI_IFR_DIVIDE_OP
:
3293 Value
->Value
.u64
= DivU64x32 (HiiValueToUINT64(&Data1
), (UINT32
) HiiValueToUINT64(&Data2
));
3296 case EFI_IFR_MODULO_OP
:
3297 DivU64x32Remainder (HiiValueToUINT64(&Data1
), (UINT32
) HiiValueToUINT64(&Data2
), &TempValue
);
3298 Value
->Value
.u64
= TempValue
;
3301 case EFI_IFR_BITWISE_AND_OP
:
3302 Value
->Value
.u64
= HiiValueToUINT64(&Data1
) & HiiValueToUINT64(&Data2
);
3305 case EFI_IFR_BITWISE_OR_OP
:
3306 Value
->Value
.u64
= HiiValueToUINT64(&Data1
) | HiiValueToUINT64(&Data2
);
3309 case EFI_IFR_SHIFT_LEFT_OP
:
3310 Value
->Value
.u64
= LShiftU64 (HiiValueToUINT64(&Data1
), (UINTN
) HiiValueToUINT64(&Data2
));
3313 case EFI_IFR_SHIFT_RIGHT_OP
:
3314 Value
->Value
.u64
= RShiftU64 (HiiValueToUINT64(&Data1
), (UINTN
) HiiValueToUINT64(&Data2
));
3322 case EFI_IFR_AND_OP
:
3325 // Two Boolean operator
3327 Status
= PopExpression (&Data2
);
3328 if (EFI_ERROR (Status
)) {
3333 // Pop another expression from the expression stack
3335 Status
= PopExpression (&Data1
);
3336 if (EFI_ERROR (Status
)) {
3340 if (Data2
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
3341 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3345 if (Data1
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
3346 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3350 if (OpCode
->Operand
== EFI_IFR_AND_OP
) {
3351 Value
->Value
.b
= (BOOLEAN
) (Data1
.Value
.b
&& Data2
.Value
.b
);
3353 Value
->Value
.b
= (BOOLEAN
) (Data1
.Value
.b
|| Data2
.Value
.b
);
3357 case EFI_IFR_EQUAL_OP
:
3358 case EFI_IFR_NOT_EQUAL_OP
:
3359 case EFI_IFR_GREATER_EQUAL_OP
:
3360 case EFI_IFR_GREATER_THAN_OP
:
3361 case EFI_IFR_LESS_EQUAL_OP
:
3362 case EFI_IFR_LESS_THAN_OP
:
3364 // Compare two integer, string, boolean or date/time
3366 Status
= PopExpression (&Data2
);
3367 if (EFI_ERROR (Status
)) {
3372 // Pop another expression from the expression stack
3374 Status
= PopExpression (&Data1
);
3375 if (EFI_ERROR (Status
)) {
3379 if (Data2
.Type
> EFI_IFR_TYPE_BOOLEAN
&&
3380 Data2
.Type
!= EFI_IFR_TYPE_STRING
&&
3381 !IsTypeInBuffer(&Data2
)) {
3382 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3386 if (Data1
.Type
> EFI_IFR_TYPE_BOOLEAN
&&
3387 Data1
.Type
!= EFI_IFR_TYPE_STRING
&&
3388 !IsTypeInBuffer(&Data1
)) {
3389 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3393 Status
= CompareHiiValue (&Data1
, &Data2
, &Result
, FormSet
->HiiHandle
);
3394 if (Data1
.Type
== EFI_IFR_TYPE_BUFFER
) {
3395 FreePool (Data1
.Buffer
);
3397 if (Data2
.Type
== EFI_IFR_TYPE_BUFFER
) {
3398 FreePool (Data2
.Buffer
);
3401 if (Status
== EFI_UNSUPPORTED
) {
3402 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3403 Status
= EFI_SUCCESS
;
3407 if (EFI_ERROR (Status
)) {
3411 switch (OpCode
->Operand
) {
3412 case EFI_IFR_EQUAL_OP
:
3413 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
3416 case EFI_IFR_NOT_EQUAL_OP
:
3417 Value
->Value
.b
= (BOOLEAN
) ((Result
!= 0) ? TRUE
: FALSE
);
3420 case EFI_IFR_GREATER_EQUAL_OP
:
3421 Value
->Value
.b
= (BOOLEAN
) ((Result
>= 0) ? TRUE
: FALSE
);
3424 case EFI_IFR_GREATER_THAN_OP
:
3425 Value
->Value
.b
= (BOOLEAN
) ((Result
> 0) ? TRUE
: FALSE
);
3428 case EFI_IFR_LESS_EQUAL_OP
:
3429 Value
->Value
.b
= (BOOLEAN
) ((Result
<= 0) ? TRUE
: FALSE
);
3432 case EFI_IFR_LESS_THAN_OP
:
3433 Value
->Value
.b
= (BOOLEAN
) ((Result
< 0) ? TRUE
: FALSE
);
3441 case EFI_IFR_MATCH_OP
:
3442 Status
= InitializeUnicodeCollationProtocol ();
3443 if (EFI_ERROR (Status
)) {
3447 Status
= IfrMatch (FormSet
, Value
);
3450 case EFI_IFR_MATCH2_OP
:
3451 Status
= IfrMatch2 (FormSet
, &OpCode
->Guid
, Value
);
3454 case EFI_IFR_CATENATE_OP
:
3455 Status
= IfrCatenate (FormSet
, Value
);
3461 case EFI_IFR_CONDITIONAL_OP
:
3463 // Pop third expression from the expression stack
3465 Status
= PopExpression (&Data3
);
3466 if (EFI_ERROR (Status
)) {
3471 // Pop second expression from the expression stack
3473 Status
= PopExpression (&Data2
);
3474 if (EFI_ERROR (Status
)) {
3479 // Pop first expression from the expression stack
3481 Status
= PopExpression (&Data1
);
3482 if (EFI_ERROR (Status
)) {
3485 if (Data1
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
3486 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3490 if (Data1
.Value
.b
) {
3497 case EFI_IFR_FIND_OP
:
3498 Status
= IfrFind (FormSet
, OpCode
->Format
, Value
);
3501 case EFI_IFR_MID_OP
:
3502 Status
= IfrMid (FormSet
, Value
);
3505 case EFI_IFR_TOKEN_OP
:
3506 Status
= IfrToken (FormSet
, Value
);
3509 case EFI_IFR_SPAN_OP
:
3510 Status
= IfrSpan (FormSet
, OpCode
->Flags
, Value
);
3513 case EFI_IFR_MAP_OP
:
3515 // Pop the check value
3517 Status
= PopExpression (&Data1
);
3518 if (EFI_ERROR (Status
)) {
3522 // Check MapExpression list is valid.
3524 if (OpCode
->MapExpressionList
.ForwardLink
== NULL
) {
3525 Status
= EFI_INVALID_PARAMETER
;
3529 // Go through map expression list.
3531 SubExpressionLink
= GetFirstNode(&OpCode
->MapExpressionList
);
3532 while (!IsNull (&OpCode
->MapExpressionList
, SubExpressionLink
)) {
3533 SubExpression
= FORM_EXPRESSION_FROM_LINK (SubExpressionLink
);
3535 // Evaluate the first expression in this pair.
3537 Status
= EvaluateExpression (FormSet
, Form
, SubExpression
);
3538 if (EFI_ERROR (Status
)) {
3542 // Compare the expression value with current value
3544 if ((CompareHiiValue (&Data1
, &SubExpression
->Result
, &Result
, NULL
) == EFI_SUCCESS
) && (Result
== 0)) {
3546 // Try get the map value.
3548 SubExpressionLink
= GetNextNode (&OpCode
->MapExpressionList
, SubExpressionLink
);
3549 if (IsNull (&OpCode
->MapExpressionList
, SubExpressionLink
)) {
3550 Status
= EFI_INVALID_PARAMETER
;
3553 SubExpression
= FORM_EXPRESSION_FROM_LINK (SubExpressionLink
);
3554 Status
= EvaluateExpression (FormSet
, Form
, SubExpression
);
3555 if (EFI_ERROR (Status
)) {
3558 Value
= &SubExpression
->Result
;
3562 // Skip the second expression on this pair.
3564 SubExpressionLink
= GetNextNode (&OpCode
->MapExpressionList
, SubExpressionLink
);
3565 if (IsNull (&OpCode
->MapExpressionList
, SubExpressionLink
)) {
3566 Status
= EFI_INVALID_PARAMETER
;
3570 // Goto the first expression on next pair.
3572 SubExpressionLink
= GetNextNode (&OpCode
->MapExpressionList
, SubExpressionLink
);
3576 // No map value is found.
3578 if (IsNull (&OpCode
->MapExpressionList
, SubExpressionLink
)) {
3579 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3580 Value
->Value
.u8
= 0;
3587 if (EFI_ERROR (Status
) || Value
->Type
== EFI_IFR_TYPE_UNDEFINED
) {
3591 Status
= PushExpression (Value
);
3592 if (EFI_ERROR (Status
)) {
3598 // Pop the final result from expression stack
3601 Status
= PopExpression (Value
);
3602 if (EFI_ERROR (Status
)) {
3607 // After evaluating an expression, there should be only one value left on the expression stack
3609 if (PopExpression (Value
) != EFI_ACCESS_DENIED
) {
3610 Status
= EFI_INVALID_PARAMETER
;
3614 RestoreExpressionEvaluationStackOffset (StackOffset
);
3615 if (!EFI_ERROR (Status
)) {
3616 CopyMem (&Expression
->Result
, Value
, sizeof (EFI_HII_VALUE
));
3623 Check whether the result is TRUE or FALSE.
3625 For the EFI_HII_VALUE value type is numeric, return TRUE if the
3628 @param Result Input the result data.
3630 @retval TRUE The result is TRUE.
3631 @retval FALSE The result is FALSE.
3636 IN EFI_HII_VALUE
*Result
3639 switch (Result
->Type
) {
3640 case EFI_IFR_TYPE_BOOLEAN
:
3641 return Result
->Value
.b
;
3643 case EFI_IFR_TYPE_NUM_SIZE_8
:
3644 return (BOOLEAN
)(Result
->Value
.u8
!= 0);
3646 case EFI_IFR_TYPE_NUM_SIZE_16
:
3647 return (BOOLEAN
)(Result
->Value
.u16
!= 0);
3649 case EFI_IFR_TYPE_NUM_SIZE_32
:
3650 return (BOOLEAN
)(Result
->Value
.u32
!= 0);
3652 case EFI_IFR_TYPE_NUM_SIZE_64
:
3653 return (BOOLEAN
)(Result
->Value
.u64
!= 0);
3661 Return the result of the expression list. Check the expression list and
3662 return the highest priority express result.
3663 Priority: DisableIf > SuppressIf > GrayOutIf > FALSE
3665 @param ExpList The input expression list.
3666 @param Evaluate Whether need to evaluate the expression first.
3667 @param FormSet FormSet associated with this expression.
3668 @param Form Form associated with this expression.
3670 @retval EXPRESS_RESULT Return the higher priority express result.
3671 DisableIf > SuppressIf > GrayOutIf > FALSE
3675 EvaluateExpressionList (
3676 IN FORM_EXPRESSION_LIST
*ExpList
,
3677 IN BOOLEAN Evaluate
,
3678 IN FORM_BROWSER_FORMSET
*FormSet OPTIONAL
,
3679 IN FORM_BROWSER_FORM
*Form OPTIONAL
3683 EXPRESS_RESULT ReturnVal
;
3684 EXPRESS_RESULT CompareOne
;
3687 if (ExpList
== NULL
) {
3688 return ExpressFalse
;
3691 ASSERT(ExpList
->Signature
== FORM_EXPRESSION_LIST_SIGNATURE
);
3695 // Check whether need to evaluate the expression first.
3698 while (ExpList
->Count
> Index
) {
3699 Status
= EvaluateExpression (FormSet
, Form
, ExpList
->Expression
[Index
++]);
3700 if (EFI_ERROR (Status
)) {
3701 return ExpressFalse
;
3707 // Run the list of expressions.
3709 ReturnVal
= ExpressFalse
;
3710 for (Index
= 0; Index
< ExpList
->Count
; Index
++) {
3711 if (IsTrue (&ExpList
->Expression
[Index
]->Result
)) {
3712 switch (ExpList
->Expression
[Index
]->Type
) {
3713 case EFI_HII_EXPRESSION_SUPPRESS_IF
:
3714 CompareOne
= ExpressSuppress
;
3717 case EFI_HII_EXPRESSION_GRAY_OUT_IF
:
3718 CompareOne
= ExpressGrayOut
;
3721 case EFI_HII_EXPRESSION_DISABLE_IF
:
3722 CompareOne
= ExpressDisable
;
3726 return ExpressFalse
;
3729 ReturnVal
= ReturnVal
< CompareOne
? CompareOne
: ReturnVal
;