2 Utility functions for expression evaluation.
4 Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 // Global stack used to evaluate boolean expresions
20 EFI_HII_VALUE
*mOpCodeScopeStack
= NULL
;
21 EFI_HII_VALUE
*mOpCodeScopeStackEnd
= NULL
;
22 EFI_HII_VALUE
*mOpCodeScopeStackPointer
= NULL
;
24 EFI_HII_VALUE
*mExpressionEvaluationStack
= NULL
;
25 EFI_HII_VALUE
*mExpressionEvaluationStackEnd
= NULL
;
26 EFI_HII_VALUE
*mExpressionEvaluationStackPointer
= NULL
;
27 UINTN mExpressionEvaluationStackOffset
= 0;
29 EFI_HII_VALUE
*mCurrentExpressionStack
= NULL
;
30 EFI_HII_VALUE
*mCurrentExpressionEnd
= NULL
;
31 EFI_HII_VALUE
*mCurrentExpressionPointer
= NULL
;
33 EFI_HII_VALUE
*mMapExpressionListStack
= NULL
;
34 EFI_HII_VALUE
*mMapExpressionListEnd
= NULL
;
35 EFI_HII_VALUE
*mMapExpressionListPointer
= NULL
;
37 FORM_EXPRESSION
**mFormExpressionStack
= NULL
;
38 FORM_EXPRESSION
**mFormExpressionEnd
= NULL
;
39 FORM_EXPRESSION
**mFormExpressionPointer
= NULL
;
41 FORM_EXPRESSION
**mStatementExpressionStack
= NULL
;
42 FORM_EXPRESSION
**mStatementExpressionEnd
= NULL
;
43 FORM_EXPRESSION
**mStatementExpressionPointer
= NULL
;
45 FORM_EXPRESSION
**mOptionExpressionStack
= NULL
;
46 FORM_EXPRESSION
**mOptionExpressionEnd
= NULL
;
47 FORM_EXPRESSION
**mOptionExpressionPointer
= NULL
;
51 // Unicode collation protocol interface
53 EFI_UNICODE_COLLATION_PROTOCOL
*mUnicodeCollation
= NULL
;
54 EFI_USER_MANAGER_PROTOCOL
*mUserManager
= NULL
;
57 Grow size of the stack.
59 This is an internal function.
61 @param Stack On input: old stack; On output: new stack
62 @param StackPtr On input: old stack pointer; On output: new stack
64 @param StackEnd On input: old stack end; On output: new stack end
66 @retval EFI_SUCCESS Grow stack success.
67 @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.
72 IN OUT EFI_HII_VALUE
**Stack
,
73 IN OUT EFI_HII_VALUE
**StackPtr
,
74 IN OUT EFI_HII_VALUE
**StackEnd
78 EFI_HII_VALUE
*NewStack
;
80 Size
= EXPRESSION_STACK_SIZE_INCREMENT
;
81 if (*StackPtr
!= NULL
) {
82 Size
= Size
+ (*StackEnd
- *Stack
);
85 NewStack
= AllocatePool (Size
* sizeof (EFI_HII_VALUE
));
86 if (NewStack
== NULL
) {
87 return EFI_OUT_OF_RESOURCES
;
90 if (*StackPtr
!= NULL
) {
92 // Copy from Old Stack to the New Stack
97 (*StackEnd
- *Stack
) * sizeof (EFI_HII_VALUE
)
101 // Free The Old Stack
107 // Make the Stack pointer point to the old data in the new stack
109 *StackPtr
= NewStack
+ (*StackPtr
- *Stack
);
111 *StackEnd
= NewStack
+ Size
;
118 Push an element onto the Boolean Stack.
120 @param Stack On input: old stack; On output: new stack
121 @param StackPtr On input: old stack pointer; On output: new stack
123 @param StackEnd On input: old stack end; On output: new stack end
124 @param Data Data to push.
126 @retval EFI_SUCCESS Push stack success.
131 IN OUT EFI_HII_VALUE
**Stack
,
132 IN OUT EFI_HII_VALUE
**StackPtr
,
133 IN OUT EFI_HII_VALUE
**StackEnd
,
134 IN EFI_HII_VALUE
*Data
140 // Check for a stack overflow condition
142 if (*StackPtr
>= *StackEnd
) {
146 Status
= GrowStack (Stack
, StackPtr
, StackEnd
);
147 if (EFI_ERROR (Status
)) {
153 // Push the item onto the stack
155 CopyMem (*StackPtr
, Data
, sizeof (EFI_HII_VALUE
));
156 if (Data
->Type
== EFI_IFR_TYPE_BUFFER
) {
157 (*StackPtr
)->Buffer
= AllocateCopyPool(Data
->BufferLen
, Data
->Buffer
);
158 ASSERT ((*StackPtr
)->Buffer
!= NULL
);
161 *StackPtr
= *StackPtr
+ 1;
168 Pop an element from the stack.
170 @param Stack On input: old stack
171 @param StackPtr On input: old stack pointer; On output: new stack pointer
172 @param Data Data to pop.
174 @retval EFI_SUCCESS The value was popped onto the stack.
175 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
180 IN EFI_HII_VALUE
*Stack
,
181 IN OUT EFI_HII_VALUE
**StackPtr
,
182 OUT EFI_HII_VALUE
*Data
186 // Check for a stack underflow condition
188 if (*StackPtr
== Stack
) {
189 return EFI_ACCESS_DENIED
;
193 // Pop the item off the stack
195 *StackPtr
= *StackPtr
- 1;
196 CopyMem (Data
, *StackPtr
, sizeof (EFI_HII_VALUE
));
202 Reset stack pointer to begin of the stack.
206 ResetCurrentExpressionStack (
210 mCurrentExpressionPointer
= mCurrentExpressionStack
;
211 mFormExpressionPointer
= mFormExpressionStack
;
212 mStatementExpressionPointer
= mStatementExpressionStack
;
213 mOptionExpressionPointer
= mOptionExpressionStack
;
218 Push current expression onto the Stack
220 @param Pointer Pointer to current expression.
222 @retval EFI_SUCCESS The value was pushed onto the stack.
223 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
227 PushCurrentExpression (
233 Data
.Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
234 Data
.Value
.u64
= (UINT64
) (UINTN
) Pointer
;
237 &mCurrentExpressionStack
,
238 &mCurrentExpressionPointer
,
239 &mCurrentExpressionEnd
,
246 Pop current expression from the Stack
248 @param Pointer Pointer to current expression to be pop.
250 @retval EFI_SUCCESS The value was pushed onto the stack.
251 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
255 PopCurrentExpression (
263 mCurrentExpressionStack
,
264 &mCurrentExpressionPointer
,
268 *Pointer
= (VOID
*) (UINTN
) Data
.Value
.u64
;
274 Reset stack pointer to begin of the stack.
278 ResetMapExpressionListStack (
282 mMapExpressionListPointer
= mMapExpressionListStack
;
287 Grow size of the stack.
289 This is an internal function.
291 @param Stack On input: old stack; On output: new stack
292 @param StackPtr On input: old stack pointer; On output: new stack
294 @param StackEnd On input: old stack end; On output: new stack end
295 @param MemberSize The stack member size.
297 @retval EFI_SUCCESS Grow stack success.
298 @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.
302 GrowConditionalStack (
303 IN OUT FORM_EXPRESSION
***Stack
,
304 IN OUT FORM_EXPRESSION
***StackPtr
,
305 IN OUT FORM_EXPRESSION
***StackEnd
,
310 FORM_EXPRESSION
**NewStack
;
312 Size
= EXPRESSION_STACK_SIZE_INCREMENT
;
313 if (*StackPtr
!= NULL
) {
314 Size
= Size
+ (*StackEnd
- *Stack
);
317 NewStack
= AllocatePool (Size
* MemberSize
);
318 if (NewStack
== NULL
) {
319 return EFI_OUT_OF_RESOURCES
;
322 if (*StackPtr
!= NULL
) {
324 // Copy from Old Stack to the New Stack
329 (*StackEnd
- *Stack
) * MemberSize
333 // Free The Old Stack
339 // Make the Stack pointer point to the old data in the new stack
341 *StackPtr
= NewStack
+ (*StackPtr
- *Stack
);
343 *StackEnd
= NewStack
+ Size
;
349 Push an element onto the Stack.
351 @param Stack On input: old stack; On output: new stack
352 @param StackPtr On input: old stack pointer; On output: new stack
354 @param StackEnd On input: old stack end; On output: new stack end
355 @param Data Data to push.
357 @retval EFI_SUCCESS Push stack success.
361 PushConditionalStack (
362 IN OUT FORM_EXPRESSION
***Stack
,
363 IN OUT FORM_EXPRESSION
***StackPtr
,
364 IN OUT FORM_EXPRESSION
***StackEnd
,
365 IN FORM_EXPRESSION
**Data
371 // Check for a stack overflow condition
373 if (*StackPtr
>= *StackEnd
) {
377 Status
= GrowConditionalStack (Stack
, StackPtr
, StackEnd
, sizeof (FORM_EXPRESSION
*));
378 if (EFI_ERROR (Status
)) {
384 // Push the item onto the stack
386 CopyMem (*StackPtr
, Data
, sizeof (FORM_EXPRESSION
*));
387 *StackPtr
= *StackPtr
+ 1;
394 Pop an element from the stack.
396 @param Stack On input: old stack
397 @param StackPtr On input: old stack pointer; On output: new stack pointer
398 @param Data Data to pop.
400 @retval EFI_SUCCESS The value was popped onto the stack.
401 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
405 PopConditionalStack (
406 IN FORM_EXPRESSION
**Stack
,
407 IN OUT FORM_EXPRESSION
***StackPtr
,
408 OUT FORM_EXPRESSION
**Data
412 // Check for a stack underflow condition
414 if (*StackPtr
== Stack
) {
415 return EFI_ACCESS_DENIED
;
419 // Pop the item off the stack
421 *StackPtr
= *StackPtr
- 1;
422 CopyMem (Data
, *StackPtr
, sizeof (FORM_EXPRESSION
*));
428 Get the expression list count.
430 @param Level Which type this expression belong to. Form,
433 @retval >=0 The expression count
434 @retval -1 Input parameter error.
438 GetConditionalExpressionCount (
439 IN EXPRESS_LEVEL Level
444 return mFormExpressionPointer
- mFormExpressionStack
;
445 case ExpressStatement
:
446 return mStatementExpressionPointer
- mStatementExpressionStack
;
448 return mOptionExpressionPointer
- mOptionExpressionStack
;
456 Get the expression Buffer pointer.
458 @param Level Which type this expression belong to. Form,
461 @retval The start pointer of the expression buffer or NULL.
465 GetConditionalExpressionList (
466 IN EXPRESS_LEVEL Level
471 return mFormExpressionStack
;
472 case ExpressStatement
:
473 return mStatementExpressionStack
;
475 return mOptionExpressionStack
;
484 Push the expression options onto the Stack.
486 @param Pointer Pointer to the current expression.
487 @param Level Which type this expression belong to. Form,
490 @retval EFI_SUCCESS The value was pushed onto the stack.
491 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
495 PushConditionalExpression (
496 IN FORM_EXPRESSION
*Pointer
,
497 IN EXPRESS_LEVEL Level
502 return PushConditionalStack (
503 &mFormExpressionStack
,
504 &mFormExpressionPointer
,
508 case ExpressStatement
:
509 return PushConditionalStack (
510 &mStatementExpressionStack
,
511 &mStatementExpressionPointer
,
512 &mStatementExpressionEnd
,
516 return PushConditionalStack (
517 &mOptionExpressionStack
,
518 &mOptionExpressionPointer
,
519 &mOptionExpressionEnd
,
524 return EFI_INVALID_PARAMETER
;
529 Pop the expression options from the Stack
531 @param Level Which type this expression belong to. Form,
534 @retval EFI_SUCCESS The value was pushed onto the stack.
535 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
539 PopConditionalExpression (
540 IN EXPRESS_LEVEL Level
543 FORM_EXPRESSION
*Pointer
;
547 return PopConditionalStack (
548 mFormExpressionStack
,
549 &mFormExpressionPointer
,
553 case ExpressStatement
:
554 return PopConditionalStack (
555 mStatementExpressionStack
,
556 &mStatementExpressionPointer
,
561 return PopConditionalStack (
562 mOptionExpressionStack
,
563 &mOptionExpressionPointer
,
569 return EFI_INVALID_PARAMETER
;
575 Push the list of map expression onto the Stack
577 @param Pointer Pointer to the list of map expression to be pushed.
579 @retval EFI_SUCCESS The value was pushed onto the stack.
580 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
584 PushMapExpressionList (
590 Data
.Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
591 Data
.Value
.u64
= (UINT64
) (UINTN
) Pointer
;
594 &mMapExpressionListStack
,
595 &mMapExpressionListPointer
,
596 &mMapExpressionListEnd
,
603 Pop the list of map expression from the Stack
605 @param Pointer Pointer to the list of map expression to be pop.
607 @retval EFI_SUCCESS The value was pushed onto the stack.
608 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
612 PopMapExpressionList (
620 mMapExpressionListStack
,
621 &mMapExpressionListPointer
,
625 *Pointer
= (VOID
*) (UINTN
) Data
.Value
.u64
;
631 Reset stack pointer to begin of the stack.
639 mOpCodeScopeStackPointer
= mOpCodeScopeStack
;
644 Push an Operand onto the Stack
646 @param Operand Operand to push.
648 @retval EFI_SUCCESS The value was pushed onto the stack.
649 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
660 Data
.Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
661 Data
.Value
.u8
= Operand
;
665 &mOpCodeScopeStackPointer
,
666 &mOpCodeScopeStackEnd
,
673 Pop an Operand from the Stack
675 @param Operand Operand to pop.
677 @retval EFI_SUCCESS The value was pushed onto the stack.
678 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
692 &mOpCodeScopeStackPointer
,
696 *Operand
= Data
.Value
.u8
;
703 Push an Expression value onto the Stack
705 @param Value Expression value to push.
707 @retval EFI_SUCCESS The value was pushed onto the stack.
708 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
714 IN EFI_HII_VALUE
*Value
718 &mExpressionEvaluationStack
,
719 &mExpressionEvaluationStackPointer
,
720 &mExpressionEvaluationStackEnd
,
727 Pop an Expression value from the stack.
729 @param Value Expression value to pop.
731 @retval EFI_SUCCESS The value was popped onto the stack.
732 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
737 OUT EFI_HII_VALUE
*Value
741 mExpressionEvaluationStack
+ mExpressionEvaluationStackOffset
,
742 &mExpressionEvaluationStackPointer
,
748 Get current stack offset from stack start.
750 @return Stack offset to stack start.
753 SaveExpressionEvaluationStackOffset (
756 UINTN TempStackOffset
;
757 TempStackOffset
= mExpressionEvaluationStackOffset
;
758 mExpressionEvaluationStackOffset
= mExpressionEvaluationStackPointer
- mExpressionEvaluationStack
;
759 return TempStackOffset
;
763 Restore stack offset based on input stack offset
765 @param StackOffset Offset to stack start.
769 RestoreExpressionEvaluationStackOffset (
773 mExpressionEvaluationStackOffset
= StackOffset
;
777 Get Form given its FormId.
779 @param FormSet The formset which contains this form.
780 @param FormId Id of this form.
782 @retval Pointer The form.
783 @retval NULL Specified Form is not found in the formset.
788 IN FORM_BROWSER_FORMSET
*FormSet
,
793 FORM_BROWSER_FORM
*Form
;
795 Link
= GetFirstNode (&FormSet
->FormListHead
);
796 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
797 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
799 if (Form
->FormId
== FormId
) {
803 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
811 Search a Question in Form scope using its QuestionId.
813 @param Form The form which contains this Question.
814 @param QuestionId Id of this Question.
816 @retval Pointer The Question.
817 @retval NULL Specified Question not found in the form.
820 FORM_BROWSER_STATEMENT
*
822 IN FORM_BROWSER_FORM
*Form
,
827 FORM_BROWSER_STATEMENT
*Question
;
829 if (QuestionId
== 0 || Form
== NULL
) {
831 // The value of zero is reserved
836 Link
= GetFirstNode (&Form
->StatementListHead
);
837 while (!IsNull (&Form
->StatementListHead
, Link
)) {
838 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
840 if (Question
->QuestionId
== QuestionId
) {
844 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
852 Search a Question in Formset scope using its QuestionId.
854 @param FormSet The formset which contains this form.
855 @param Form The form which contains this Question.
856 @param QuestionId Id of this Question.
858 @retval Pointer The Question.
859 @retval NULL Specified Question not found in the form.
862 FORM_BROWSER_STATEMENT
*
864 IN FORM_BROWSER_FORMSET
*FormSet
,
865 IN FORM_BROWSER_FORM
*Form
,
870 FORM_BROWSER_STATEMENT
*Question
;
873 // Search in the form scope first
875 Question
= IdToQuestion2 (Form
, QuestionId
);
876 if (Question
!= NULL
) {
881 // Search in the formset scope
883 Link
= GetFirstNode (&FormSet
->FormListHead
);
884 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
885 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
887 Question
= IdToQuestion2 (Form
, QuestionId
);
888 if (Question
!= NULL
) {
890 // EFI variable storage may be updated by Callback() asynchronous,
891 // to keep synchronous, always reload the Question Value.
893 if (Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
894 GetQuestionValue (FormSet
, Form
, Question
, GetSetValueWithHiiDriver
);
900 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
908 Get Expression given its RuleId.
910 @param Form The form which contains this Expression.
911 @param RuleId Id of this Expression.
913 @retval Pointer The Expression.
914 @retval NULL Specified Expression not found in the form.
919 IN FORM_BROWSER_FORM
*Form
,
924 FORM_EXPRESSION
*Expression
;
926 Link
= GetFirstNode (&Form
->ExpressionListHead
);
927 while (!IsNull (&Form
->ExpressionListHead
, Link
)) {
928 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
930 if (Expression
->Type
== EFI_HII_EXPRESSION_RULE
&& Expression
->RuleId
== RuleId
) {
934 Link
= GetNextNode (&Form
->ExpressionListHead
, Link
);
942 Locate the Unicode Collation Protocol interface for later use.
944 @retval EFI_SUCCESS Protocol interface initialize success.
945 @retval Other Protocol interface initialize failed.
949 InitializeUnicodeCollationProtocol (
955 if (mUnicodeCollation
!= NULL
) {
960 // BUGBUG: Proper impelmentation is to locate all Unicode Collation Protocol
961 // instances first and then select one which support English language.
962 // Current implementation just pick the first instance.
964 Status
= gBS
->LocateProtocol (
965 &gEfiUnicodeCollation2ProtocolGuid
,
967 (VOID
**) &mUnicodeCollation
973 Convert the input Unicode character to upper.
975 @param String Th Unicode character to be converted.
983 while (*String
!= 0) {
984 if ((*String
>= 'a') && (*String
<= 'z')) {
985 *String
= (UINT16
) ((*String
) & ((UINT16
) ~0x20));
992 Check whether this value type can be transfer to EFI_IFR_TYPE_BUFFER type.
994 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to
995 EFI_IFR_TYPE_BUFFER when do the value compare.
997 @param Value Expression value to compare on.
999 @retval TRUE This value type can be transter to EFI_IFR_TYPE_BUFFER type.
1000 @retval FALSE This value type can't be transter to EFI_IFR_TYPE_BUFFER type.
1005 IN EFI_HII_VALUE
*Value
1008 switch (Value
->Type
) {
1009 case EFI_IFR_TYPE_BUFFER
:
1010 case EFI_IFR_TYPE_DATE
:
1011 case EFI_IFR_TYPE_TIME
:
1012 case EFI_IFR_TYPE_REF
:
1021 Check whether this value type can be transfer to EFI_IFR_TYPE_UINT64
1023 @param Value Expression value to compare on.
1025 @retval TRUE This value type can be transter to EFI_IFR_TYPE_BUFFER type.
1026 @retval FALSE This value type can't be transter to EFI_IFR_TYPE_BUFFER type.
1031 IN EFI_HII_VALUE
*Value
1034 switch (Value
->Type
) {
1035 case EFI_IFR_TYPE_NUM_SIZE_8
:
1036 case EFI_IFR_TYPE_NUM_SIZE_16
:
1037 case EFI_IFR_TYPE_NUM_SIZE_32
:
1038 case EFI_IFR_TYPE_NUM_SIZE_64
:
1039 case EFI_IFR_TYPE_BOOLEAN
:
1048 Return the buffer length for this value.
1050 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to
1051 EFI_IFR_TYPE_BUFFER when do the value compare.
1053 @param Value Expression value to compare on.
1055 @retval BufLen Return the buffer length.
1060 IN EFI_HII_VALUE
*Value
1063 switch (Value
->Type
) {
1064 case EFI_IFR_TYPE_BUFFER
:
1065 return Value
->BufferLen
;
1067 case EFI_IFR_TYPE_DATE
:
1068 return (UINT16
) sizeof (EFI_HII_DATE
);
1070 case EFI_IFR_TYPE_TIME
:
1071 return (UINT16
) sizeof (EFI_HII_TIME
);
1073 case EFI_IFR_TYPE_REF
:
1074 return (UINT16
) sizeof (EFI_HII_REF
);
1082 Return the buffer pointer for this value.
1084 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to
1085 EFI_IFR_TYPE_BUFFER when do the value compare.
1087 @param Value Expression value to compare on.
1089 @retval Buf Return the buffer pointer.
1094 IN EFI_HII_VALUE
*Value
1097 switch (Value
->Type
) {
1098 case EFI_IFR_TYPE_BUFFER
:
1099 return Value
->Buffer
;
1101 case EFI_IFR_TYPE_DATE
:
1102 return (UINT8
*) (&Value
->Value
.date
);
1104 case EFI_IFR_TYPE_TIME
:
1105 return (UINT8
*) (&Value
->Value
.time
);
1107 case EFI_IFR_TYPE_REF
:
1108 return (UINT8
*) (&Value
->Value
.ref
);
1116 Evaluate opcode EFI_IFR_TO_STRING.
1118 @param FormSet Formset which contains this opcode.
1119 @param Format String format in EFI_IFR_TO_STRING.
1120 @param Result Evaluation result for this opcode.
1122 @retval EFI_SUCCESS Opcode evaluation success.
1123 @retval Other Opcode evaluation failed.
1128 IN FORM_BROWSER_FORMSET
*FormSet
,
1130 OUT EFI_HII_VALUE
*Result
1134 EFI_HII_VALUE Value
;
1136 CHAR16
*PrintFormat
;
1137 CHAR16 Buffer
[MAXIMUM_VALUE_CHARACTERS
];
1143 Status
= PopExpression (&Value
);
1144 if (EFI_ERROR (Status
)) {
1148 switch (Value
.Type
) {
1149 case EFI_IFR_TYPE_NUM_SIZE_8
:
1150 case EFI_IFR_TYPE_NUM_SIZE_16
:
1151 case EFI_IFR_TYPE_NUM_SIZE_32
:
1152 case EFI_IFR_TYPE_NUM_SIZE_64
:
1153 BufferSize
= MAXIMUM_VALUE_CHARACTERS
* sizeof (CHAR16
);
1155 case EFI_IFR_STRING_UNSIGNED_DEC
:
1156 case EFI_IFR_STRING_SIGNED_DEC
:
1157 PrintFormat
= L
"%ld";
1160 case EFI_IFR_STRING_LOWERCASE_HEX
:
1161 PrintFormat
= L
"%lx";
1164 case EFI_IFR_STRING_UPPERCASE_HEX
:
1165 PrintFormat
= L
"%lX";
1169 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1172 UnicodeSPrint (Buffer
, BufferSize
, PrintFormat
, Value
.Value
.u64
);
1176 case EFI_IFR_TYPE_STRING
:
1177 CopyMem (Result
, &Value
, sizeof (EFI_HII_VALUE
));
1180 case EFI_IFR_TYPE_BOOLEAN
:
1181 String
= (Value
.Value
.b
) ? L
"True" : L
"False";
1184 case EFI_IFR_TYPE_BUFFER
:
1185 case EFI_IFR_TYPE_DATE
:
1186 case EFI_IFR_TYPE_TIME
:
1187 case EFI_IFR_TYPE_REF
:
1189 // + 3 is base on the unicode format, the length may be odd number,
1190 // so need 1 byte to align, also need 2 bytes for L'\0'.
1192 if (Value
.Type
== EFI_IFR_TYPE_BUFFER
) {
1193 SrcLen
= Value
.BufferLen
;
1194 SrcBuf
= Value
.Buffer
;
1196 SrcBuf
= GetBufferForValue(&Value
);
1197 SrcLen
= GetLengthForValue(&Value
);
1200 TmpBuf
= AllocateZeroPool (SrcLen
+ 3);
1201 ASSERT (TmpBuf
!= NULL
);
1202 if (Format
== EFI_IFR_STRING_ASCII
) {
1203 CopyMem (TmpBuf
, SrcBuf
, SrcLen
);
1204 PrintFormat
= L
"%a";
1206 // Format == EFI_IFR_STRING_UNICODE
1207 CopyMem (TmpBuf
, SrcBuf
, SrcLen
* sizeof (CHAR16
));
1208 PrintFormat
= L
"%s";
1210 UnicodeSPrint (Buffer
, sizeof (Buffer
), PrintFormat
, TmpBuf
);
1213 if (Value
.Type
== EFI_IFR_TYPE_BUFFER
) {
1214 FreePool (Value
.Buffer
);
1219 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1223 Result
->Type
= EFI_IFR_TYPE_STRING
;
1224 Result
->Value
.string
= NewString (String
, FormSet
->HiiHandle
);
1230 Evaluate opcode EFI_IFR_TO_UINT.
1232 @param FormSet Formset which contains this opcode.
1233 @param Result Evaluation result for this opcode.
1235 @retval EFI_SUCCESS Opcode evaluation success.
1236 @retval Other Opcode evaluation failed.
1241 IN FORM_BROWSER_FORMSET
*FormSet
,
1242 OUT EFI_HII_VALUE
*Result
1246 EFI_HII_VALUE Value
;
1250 Status
= PopExpression (&Value
);
1251 if (EFI_ERROR (Status
)) {
1255 if (Value
.Type
>= EFI_IFR_TYPE_OTHER
&& !IsTypeInBuffer(&Value
)) {
1256 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1260 Status
= EFI_SUCCESS
;
1261 if (Value
.Type
== EFI_IFR_TYPE_STRING
) {
1262 String
= GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
1263 if (String
== NULL
) {
1264 return EFI_NOT_FOUND
;
1267 IfrStrToUpper (String
);
1268 StringPtr
= StrStr (String
, L
"0X");
1269 if (StringPtr
!= NULL
) {
1273 Result
->Value
.u64
= StrHexToUint64 (String
);
1278 Result
->Value
.u64
= StrDecimalToUint64 (String
);
1281 } else if (IsTypeInBuffer(&Value
)) {
1282 if (GetLengthForValue (&Value
) > 8) {
1283 if (Value
.Type
== EFI_IFR_TYPE_BUFFER
) {
1284 FreePool (Value
.Buffer
);
1286 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1289 Result
->Value
.u64
= *(UINT64
*) GetBufferForValue (&Value
);
1290 if (Value
.Type
== EFI_IFR_TYPE_BUFFER
) {
1291 FreePool (Value
.Buffer
);
1294 CopyMem (Result
, &Value
, sizeof (EFI_HII_VALUE
));
1297 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1303 Evaluate opcode EFI_IFR_CATENATE.
1305 @param FormSet Formset which contains this opcode.
1306 @param Result Evaluation result for this opcode.
1308 @retval EFI_SUCCESS Opcode evaluation success.
1309 @retval Other Opcode evaluation failed.
1314 IN FORM_BROWSER_FORMSET
*FormSet
,
1315 OUT EFI_HII_VALUE
*Result
1319 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 StringPtr
= AllocatePool (StrSize (String
[1]) + Size
);
1366 ASSERT (StringPtr
!= NULL
);
1367 StrCpy (StringPtr
, String
[1]);
1368 StrCat (StringPtr
, String
[0]);
1370 Result
->Type
= EFI_IFR_TYPE_STRING
;
1371 Result
->Value
.string
= NewString (StringPtr
, FormSet
->HiiHandle
);
1373 Result
->Type
= EFI_IFR_TYPE_BUFFER
;
1374 Length0
= GetLengthForValue(&Value
[0]);
1375 Length1
= GetLengthForValue(&Value
[1]);
1376 Result
->BufferLen
= (UINT16
) (Length0
+ Length1
);
1378 Result
->Buffer
= AllocateZeroPool (Result
->BufferLen
);
1379 ASSERT (Result
->Buffer
!= NULL
);
1381 CopyMem (Result
->Buffer
, GetBufferForValue(&Value
[0]), Length0
);
1382 CopyMem (&Result
->Buffer
[Length0
], GetBufferForValue(&Value
[1]), Length1
);
1385 if (Value
[0].Buffer
!= NULL
) {
1386 FreePool (Value
[0].Buffer
);
1388 if (Value
[1].Buffer
!= NULL
) {
1389 FreePool (Value
[1].Buffer
);
1391 if (String
[0] != NULL
) {
1392 FreePool (String
[0]);
1394 if (String
[1] != NULL
) {
1395 FreePool (String
[1]);
1397 if (StringPtr
!= NULL
) {
1398 FreePool (StringPtr
);
1406 Evaluate opcode EFI_IFR_MATCH.
1408 @param FormSet Formset which contains this opcode.
1409 @param Result Evaluation result for this opcode.
1411 @retval EFI_SUCCESS Opcode evaluation success.
1412 @retval Other Opcode evaluation failed.
1417 IN FORM_BROWSER_FORMSET
*FormSet
,
1418 OUT EFI_HII_VALUE
*Result
1422 EFI_HII_VALUE Value
[2];
1427 // String[0] - The string to search
1428 // String[1] - pattern
1432 Status
= EFI_SUCCESS
;
1433 ZeroMem (Value
, sizeof (Value
));
1435 Status
= PopExpression (&Value
[0]);
1436 if (EFI_ERROR (Status
)) {
1440 Status
= PopExpression (&Value
[1]);
1441 if (EFI_ERROR (Status
)) {
1445 for (Index
= 0; Index
< 2; Index
++) {
1446 if (Value
[Index
].Type
!= EFI_IFR_TYPE_STRING
) {
1447 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1448 Status
= EFI_SUCCESS
;
1452 String
[Index
] = GetToken (Value
[Index
].Value
.string
, FormSet
->HiiHandle
);
1453 if (String
[Index
] == NULL
) {
1454 Status
= EFI_NOT_FOUND
;
1459 Result
->Type
= EFI_IFR_TYPE_BOOLEAN
;
1460 Result
->Value
.b
= mUnicodeCollation
->MetaiMatch (mUnicodeCollation
, String
[0], String
[1]);
1463 if (String
[0] != NULL
) {
1464 FreePool (String
[0]);
1466 if (String
[1] != NULL
) {
1467 FreePool (String
[1]);
1475 Evaluate opcode EFI_IFR_FIND.
1477 @param FormSet Formset which contains this opcode.
1478 @param Format Case sensitive or insensitive.
1479 @param Result Evaluation result for this opcode.
1481 @retval EFI_SUCCESS Opcode evaluation success.
1482 @retval Other Opcode evaluation failed.
1487 IN FORM_BROWSER_FORMSET
*FormSet
,
1489 OUT EFI_HII_VALUE
*Result
1493 EFI_HII_VALUE Value
[3];
1499 ZeroMem (Value
, sizeof (Value
));
1501 if (Format
> EFI_IFR_FF_CASE_INSENSITIVE
) {
1502 return EFI_INVALID_PARAMETER
;
1505 Status
= PopExpression (&Value
[0]);
1506 if (EFI_ERROR (Status
)) {
1510 Status
= PopExpression (&Value
[1]);
1511 if (EFI_ERROR (Status
)) {
1515 Status
= PopExpression (&Value
[2]);
1516 if (EFI_ERROR (Status
)) {
1520 if (Value
[0].Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1521 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1524 Base
= (UINTN
) Value
[0].Value
.u64
;
1527 // String[0] - sub-string
1528 // String[1] - The string to search
1532 for (Index
= 0; Index
< 2; Index
++) {
1533 if (Value
[Index
+ 1].Type
!= EFI_IFR_TYPE_STRING
) {
1534 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1535 Status
= EFI_SUCCESS
;
1539 String
[Index
] = GetToken (Value
[Index
+ 1].Value
.string
, FormSet
->HiiHandle
);
1540 if (String
[Index
] == NULL
) {
1541 Status
= EFI_NOT_FOUND
;
1545 if (Format
== EFI_IFR_FF_CASE_INSENSITIVE
) {
1547 // Case insensitive, convert both string to upper case
1549 IfrStrToUpper (String
[Index
]);
1553 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1554 if (Base
>= StrLen (String
[1])) {
1555 Result
->Value
.u64
= 0xFFFFFFFFFFFFFFFFULL
;
1557 StringPtr
= StrStr (String
[1] + Base
, String
[0]);
1558 Result
->Value
.u64
= (StringPtr
== NULL
) ? 0xFFFFFFFFFFFFFFFFULL
: (StringPtr
- String
[1]);
1562 if (String
[0] != NULL
) {
1563 FreePool (String
[0]);
1565 if (String
[1] != NULL
) {
1566 FreePool (String
[1]);
1574 Evaluate opcode EFI_IFR_MID.
1576 @param FormSet Formset which contains this opcode.
1577 @param Result Evaluation result for this opcode.
1579 @retval EFI_SUCCESS Opcode evaluation success.
1580 @retval Other Opcode evaluation failed.
1585 IN FORM_BROWSER_FORMSET
*FormSet
,
1586 OUT EFI_HII_VALUE
*Result
1590 EFI_HII_VALUE Value
[3];
1598 ZeroMem (Value
, sizeof (Value
));
1600 Status
= PopExpression (&Value
[0]);
1601 if (EFI_ERROR (Status
)) {
1605 Status
= PopExpression (&Value
[1]);
1606 if (EFI_ERROR (Status
)) {
1610 Status
= PopExpression (&Value
[2]);
1611 if (EFI_ERROR (Status
)) {
1615 if (Value
[0].Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1616 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1619 Length
= (UINTN
) Value
[0].Value
.u64
;
1621 if (Value
[1].Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1622 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1625 Base
= (UINTN
) Value
[1].Value
.u64
;
1627 if (Value
[2].Type
!= EFI_IFR_TYPE_STRING
&& !IsTypeInBuffer(&Value
[2])) {
1628 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1631 if (Value
[2].Type
== EFI_IFR_TYPE_STRING
) {
1632 String
= GetToken (Value
[2].Value
.string
, FormSet
->HiiHandle
);
1633 if (String
== NULL
) {
1634 return EFI_NOT_FOUND
;
1637 if (Length
== 0 || Base
>= StrLen (String
)) {
1638 SubString
= gEmptyString
;
1640 SubString
= String
+ Base
;
1641 if ((Base
+ Length
) < StrLen (String
)) {
1642 SubString
[Length
] = L
'\0';
1646 Result
->Type
= EFI_IFR_TYPE_STRING
;
1647 Result
->Value
.string
= NewString (SubString
, FormSet
->HiiHandle
);
1651 BufferLen
= GetLengthForValue (&Value
[2]);
1652 Buffer
= GetBufferForValue (&Value
[2]);
1654 Result
->Type
= EFI_IFR_TYPE_BUFFER
;
1655 if (Length
== 0 || Base
>= BufferLen
) {
1656 Result
->BufferLen
= 0;
1657 Result
->Buffer
= NULL
;
1659 Result
->BufferLen
= (UINT16
)((BufferLen
- Base
) < Length
? (BufferLen
- Base
) : Length
);
1660 Result
->Buffer
= AllocateZeroPool (Result
->BufferLen
);
1661 ASSERT (Result
->Buffer
!= NULL
);
1662 CopyMem (Result
->Buffer
, &Buffer
[Base
], Result
->BufferLen
);
1665 if (Value
[2].Type
== EFI_IFR_TYPE_BUFFER
) {
1666 FreePool (Value
[2].Buffer
);
1675 Evaluate opcode EFI_IFR_TOKEN.
1677 @param FormSet Formset which contains this opcode.
1678 @param Result Evaluation result for this opcode.
1680 @retval EFI_SUCCESS Opcode evaluation success.
1681 @retval Other Opcode evaluation failed.
1686 IN FORM_BROWSER_FORMSET
*FormSet
,
1687 OUT EFI_HII_VALUE
*Result
1691 EFI_HII_VALUE Value
[3];
1699 ZeroMem (Value
, sizeof (Value
));
1701 Status
= PopExpression (&Value
[0]);
1702 if (EFI_ERROR (Status
)) {
1706 Status
= PopExpression (&Value
[1]);
1707 if (EFI_ERROR (Status
)) {
1711 Status
= PopExpression (&Value
[2]);
1712 if (EFI_ERROR (Status
)) {
1716 if (Value
[0].Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1717 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1720 Count
= (UINTN
) Value
[0].Value
.u64
;
1723 // String[0] - Delimiter
1724 // String[1] - The string to search
1728 for (Index
= 0; Index
< 2; Index
++) {
1729 if (Value
[Index
+ 1].Type
!= EFI_IFR_TYPE_STRING
) {
1730 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1731 Status
= EFI_SUCCESS
;
1735 String
[Index
] = GetToken (Value
[Index
+ 1].Value
.string
, FormSet
->HiiHandle
);
1736 if (String
[Index
] == NULL
) {
1737 Status
= EFI_NOT_FOUND
;
1742 Delimiter
= String
[0];
1743 SubString
= String
[1];
1745 SubString
= StrStr (SubString
, Delimiter
);
1746 if (SubString
!= NULL
) {
1748 // Skip over the delimiter
1750 SubString
= SubString
+ StrLen (Delimiter
);
1757 if (SubString
== NULL
) {
1759 // nth delimited sub-string not found, push an empty string
1761 SubString
= gEmptyString
;
1764 // Put a NULL terminator for nth delimited sub-string
1766 StringPtr
= StrStr (SubString
, Delimiter
);
1767 if (StringPtr
!= NULL
) {
1772 Result
->Type
= EFI_IFR_TYPE_STRING
;
1773 Result
->Value
.string
= NewString (SubString
, FormSet
->HiiHandle
);
1776 if (String
[0] != NULL
) {
1777 FreePool (String
[0]);
1779 if (String
[1] != NULL
) {
1780 FreePool (String
[1]);
1788 Evaluate opcode EFI_IFR_SPAN.
1790 @param FormSet Formset which contains this opcode.
1791 @param Flags FIRST_MATCHING or FIRST_NON_MATCHING.
1792 @param Result Evaluation result for this opcode.
1794 @retval EFI_SUCCESS Opcode evaluation success.
1795 @retval Other Opcode evaluation failed.
1800 IN FORM_BROWSER_FORMSET
*FormSet
,
1802 OUT EFI_HII_VALUE
*Result
1806 EFI_HII_VALUE Value
[3];
1814 ZeroMem (Value
, sizeof (Value
));
1816 Status
= PopExpression (&Value
[0]);
1817 if (EFI_ERROR (Status
)) {
1821 Status
= PopExpression (&Value
[1]);
1822 if (EFI_ERROR (Status
)) {
1826 Status
= PopExpression (&Value
[2]);
1827 if (EFI_ERROR (Status
)) {
1831 if (Value
[0].Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1832 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1835 Base
= (UINTN
) Value
[0].Value
.u64
;
1838 // String[0] - Charset
1839 // String[1] - The string to search
1843 for (Index
= 0; Index
< 2; Index
++) {
1844 if (Value
[Index
+ 1].Type
!= EFI_IFR_TYPE_STRING
) {
1845 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1846 Status
= EFI_SUCCESS
;
1850 String
[Index
] = GetToken (Value
[Index
+ 1].Value
.string
, FormSet
->HiiHandle
);
1851 if (String
[Index
] == NULL
) {
1852 Status
= EFI_NOT_FOUND
;
1857 if (Base
>= StrLen (String
[1])) {
1858 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1859 Status
= EFI_SUCCESS
;
1864 StringPtr
= String
[1] + Base
;
1865 Charset
= String
[0];
1866 while (*StringPtr
!= 0 && !Found
) {
1868 while (Charset
[Index
] != 0) {
1869 if (*StringPtr
>= Charset
[Index
] && *StringPtr
<= Charset
[Index
+ 1]) {
1870 if (Flags
== EFI_IFR_FLAGS_FIRST_MATCHING
) {
1875 if (Flags
== EFI_IFR_FLAGS_FIRST_NON_MATCHING
) {
1881 // Skip characters pair representing low-end of a range and high-end of a range
1891 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1892 Result
->Value
.u64
= StringPtr
- String
[1];
1895 if (String
[0] != NULL
) {
1896 FreePool (String
[0]);
1898 if (String
[1] != NULL
) {
1899 FreePool (String
[1]);
1907 Zero extend integer/boolean/date/time to UINT64 for comparing.
1909 @param Value HII Value to be converted.
1914 IN EFI_HII_VALUE
*Value
1920 switch (Value
->Type
) {
1921 case EFI_IFR_TYPE_NUM_SIZE_8
:
1922 Temp
= Value
->Value
.u8
;
1925 case EFI_IFR_TYPE_NUM_SIZE_16
:
1926 Temp
= Value
->Value
.u16
;
1929 case EFI_IFR_TYPE_NUM_SIZE_32
:
1930 Temp
= Value
->Value
.u32
;
1933 case EFI_IFR_TYPE_BOOLEAN
:
1934 Temp
= Value
->Value
.b
;
1937 case EFI_IFR_TYPE_TIME
:
1938 Temp
= Value
->Value
.u32
& 0xffffff;
1941 case EFI_IFR_TYPE_DATE
:
1942 Temp
= Value
->Value
.u32
;
1949 Value
->Value
.u64
= Temp
;
1953 Get UINT64 type value.
1955 @param Value Input Hii value.
1957 @retval UINT64 Return the UINT64 type value.
1962 IN EFI_HII_VALUE
*Value
1969 switch (Value
->Type
) {
1970 case EFI_IFR_TYPE_NUM_SIZE_8
:
1971 RetVal
= Value
->Value
.u8
;
1974 case EFI_IFR_TYPE_NUM_SIZE_16
:
1975 RetVal
= Value
->Value
.u16
;
1978 case EFI_IFR_TYPE_NUM_SIZE_32
:
1979 RetVal
= Value
->Value
.u32
;
1982 case EFI_IFR_TYPE_BOOLEAN
:
1983 RetVal
= Value
->Value
.b
;
1986 case EFI_IFR_TYPE_DATE
:
1987 RetVal
= *(UINT64
*) &Value
->Value
.date
;
1990 case EFI_IFR_TYPE_TIME
:
1991 RetVal
= (*(UINT64
*) &Value
->Value
.time
) & 0xffffff;
1995 RetVal
= Value
->Value
.u64
;
2003 Compare two Hii value.
2005 @param Value1 Expression value to compare on left-hand.
2006 @param Value2 Expression value to compare on right-hand.
2007 @param Result Return value after compare.
2008 retval 0 Two operators equal.
2009 return Positive value if Value1 is greater than Value2.
2010 retval Negative value if Value1 is less than Value2.
2011 @param HiiHandle Only required for string compare.
2013 @retval other Could not perform compare on two values.
2014 @retval EFI_SUCCESS Compare the value success.
2019 IN EFI_HII_VALUE
*Value1
,
2020 IN EFI_HII_VALUE
*Value2
,
2022 IN EFI_HII_HANDLE HiiHandle OPTIONAL
2034 if (Value1
->Type
== EFI_IFR_TYPE_STRING
&& Value2
->Type
== EFI_IFR_TYPE_STRING
) {
2035 if (Value1
->Value
.string
== 0 || Value2
->Value
.string
== 0) {
2037 // StringId 0 is reserved
2039 return EFI_INVALID_PARAMETER
;
2042 if (Value1
->Value
.string
== Value2
->Value
.string
) {
2047 Str1
= GetToken (Value1
->Value
.string
, HiiHandle
);
2052 return EFI_NOT_FOUND
;
2055 Str2
= GetToken (Value2
->Value
.string
, HiiHandle
);
2058 return EFI_NOT_FOUND
;
2061 *Result
= StrCmp (Str1
, Str2
);
2070 // Take types(date, time, ref, buffer) as buffer
2072 if (IsTypeInBuffer(Value1
) && IsTypeInBuffer(Value2
)) {
2073 Buf1
= GetBufferForValue(Value1
);
2074 Buf1Len
= GetLengthForValue(Value1
);
2075 Buf2
= GetBufferForValue(Value2
);
2076 Buf2Len
= GetLengthForValue(Value2
);
2078 Len
= Buf1Len
> Buf2Len
? Buf2Len
: Buf1Len
;
2079 *Result
= CompareMem (Buf1
, Buf2
, Len
);
2080 if ((*Result
== 0) && (Buf1Len
!= Buf2Len
)) {
2082 // In this case, means base on samll number buffer, the data is same
2083 // So which value has more data, which value is bigger.
2085 *Result
= Buf1Len
> Buf2Len
? 1 : -1;
2091 // Take types(integer, boolean) as integer
2093 if (IsTypeInUINT64(Value1
) && IsTypeInUINT64(Value2
)) {
2094 Temp64
= HiiValueToUINT64(Value1
) - HiiValueToUINT64(Value2
);
2097 } else if (Temp64
< 0) {
2106 return EFI_UNSUPPORTED
;
2110 Check if current user has the privilege specified by the permissions GUID.
2112 @param[in] Guid A GUID specifying setup access permissions.
2114 @retval TRUE Current user has the privilege.
2115 @retval FALSE Current user does not have the privilege.
2118 CheckUserPrivilege (
2123 EFI_USER_PROFILE_HANDLE UserProfileHandle
;
2124 EFI_USER_INFO_HANDLE UserInfoHandle
;
2125 EFI_USER_INFO
*UserInfo
;
2126 EFI_GUID
*UserPermissionsGuid
;
2128 UINTN AccessControlDataSize
;
2129 EFI_USER_INFO_ACCESS_CONTROL
*AccessControl
;
2132 if (mUserManager
== NULL
) {
2133 Status
= gBS
->LocateProtocol (
2134 &gEfiUserManagerProtocolGuid
,
2136 (VOID
**) &mUserManager
2138 if (EFI_ERROR (Status
)) {
2140 /// If the system does not support user management, then it is assumed that
2141 /// all users have admin privilege and evaluation of each EFI_IFR_SECURITY
2142 /// op-code is always TRUE.
2148 Status
= mUserManager
->Current (mUserManager
, &UserProfileHandle
);
2149 ASSERT_EFI_ERROR (Status
);
2152 /// Enumerate all user information of the current user profile
2153 /// to look for any EFI_USER_INFO_ACCESS_SETUP record.
2156 for (UserInfoHandle
= NULL
;;) {
2157 Status
= mUserManager
->GetNextInfo (mUserManager
, UserProfileHandle
, &UserInfoHandle
);
2158 if (EFI_ERROR (Status
)) {
2163 Status
= mUserManager
->GetInfo (mUserManager
, UserProfileHandle
, UserInfoHandle
, NULL
, &UserInfoSize
);
2164 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
2168 UserInfo
= (EFI_USER_INFO
*) AllocatePool (UserInfoSize
);
2169 if (UserInfo
== NULL
) {
2173 Status
= mUserManager
->GetInfo (mUserManager
, UserProfileHandle
, UserInfoHandle
, UserInfo
, &UserInfoSize
);
2174 if (EFI_ERROR (Status
) ||
2175 UserInfo
->InfoType
!= EFI_USER_INFO_ACCESS_POLICY_RECORD
||
2176 UserInfo
->InfoSize
<= sizeof (EFI_USER_INFO
)) {
2177 FreePool (UserInfo
);
2181 RemainSize
= UserInfo
->InfoSize
- sizeof (EFI_USER_INFO
);
2182 AccessControl
= (EFI_USER_INFO_ACCESS_CONTROL
*)(UserInfo
+ 1);
2183 while (RemainSize
>= sizeof (EFI_USER_INFO_ACCESS_CONTROL
)) {
2184 if (RemainSize
< AccessControl
->Size
|| AccessControl
->Size
< sizeof (EFI_USER_INFO_ACCESS_CONTROL
)) {
2187 if (AccessControl
->Type
== EFI_USER_INFO_ACCESS_SETUP
) {
2189 /// Check if current user has the privilege specified by the permissions GUID.
2192 UserPermissionsGuid
= (EFI_GUID
*)(AccessControl
+ 1);
2193 AccessControlDataSize
= AccessControl
->Size
- sizeof (EFI_USER_INFO_ACCESS_CONTROL
);
2194 while (AccessControlDataSize
>= sizeof (EFI_GUID
)) {
2195 if (CompareGuid (Guid
, UserPermissionsGuid
)) {
2196 FreePool (UserInfo
);
2199 UserPermissionsGuid
++;
2200 AccessControlDataSize
-= sizeof (EFI_GUID
);
2203 RemainSize
-= AccessControl
->Size
;
2204 AccessControl
= (EFI_USER_INFO_ACCESS_CONTROL
*)((UINT8
*)AccessControl
+ AccessControl
->Size
);
2207 FreePool (UserInfo
);
2213 Get question value from the predefined formset.
2215 @param DevicePath The driver's device path which produece the formset data.
2216 @param InputHiiHandle The hii handle associate with the formset data.
2217 @param FormSetGuid The formset guid which include the question.
2218 @param QuestionId The question id which need to get value from.
2219 @param Value The return data about question's value.
2221 @retval TRUE Get the question value success.
2222 @retval FALSE Get the question value failed.
2225 GetQuestionValueFromForm (
2226 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
2227 IN EFI_HII_HANDLE InputHiiHandle
,
2228 IN EFI_GUID
*FormSetGuid
,
2229 IN EFI_QUESTION_ID QuestionId
,
2230 OUT EFI_HII_VALUE
*Value
2234 EFI_HII_HANDLE HiiHandle
;
2235 FORM_BROWSER_STATEMENT
*Question
;
2236 FORM_BROWSER_FORMSET
*FormSet
;
2237 FORM_BROWSER_FORM
*Form
;
2242 // The input parameter DevicePath or InputHiiHandle must have one valid input.
2244 ASSERT ((DevicePath
!= NULL
&& InputHiiHandle
== NULL
) ||
2245 (DevicePath
== NULL
&& InputHiiHandle
!= NULL
) );
2255 if (DevicePath
!= NULL
) {
2256 HiiHandle
= DevicePathToHiiHandle (DevicePath
, FormSetGuid
);
2257 if (HiiHandle
== NULL
) {
2261 HiiHandle
= InputHiiHandle
;
2263 ASSERT (HiiHandle
!= NULL
);
2266 // Get the formset data include this question.
2268 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
2269 ASSERT (FormSet
!= NULL
);
2270 Status
= InitializeFormSet(HiiHandle
, FormSetGuid
, FormSet
);
2271 if (EFI_ERROR (Status
)) {
2277 // Base on the Question Id to get the question info.
2279 Question
= IdToQuestion(FormSet
, NULL
, QuestionId
);
2280 if (Question
== NULL
) {
2286 // Search form in the formset scope
2288 Link
= GetFirstNode (&FormSet
->FormListHead
);
2289 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2290 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2292 Question
= IdToQuestion2 (Form
, QuestionId
);
2293 if (Question
!= NULL
) {
2297 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2300 ASSERT (Form
!= NULL
);
2303 // Get the question value.
2305 Status
= GetQuestionValue(FormSet
, Form
, Question
, GetSetValueWithHiiDriver
);
2306 if (EFI_ERROR (Status
)) {
2311 CopyMem (Value
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
2315 // Clean the formset structure and restore the global parameter.
2317 if (FormSet
!= NULL
) {
2318 DestroyFormSet (FormSet
);
2325 Evaluate the result of a HII expression.
2327 If Expression is NULL, then ASSERT.
2329 @param FormSet FormSet associated with this expression.
2330 @param Form Form associated with this expression.
2331 @param Expression Expression to be evaluated.
2333 @retval EFI_SUCCESS The expression evaluated successfuly
2334 @retval EFI_NOT_FOUND The Question which referenced by a QuestionId
2336 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
2338 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
2339 @retval EFI_INVALID_PARAMETER Syntax error with the Expression
2343 EvaluateExpression (
2344 IN FORM_BROWSER_FORMSET
*FormSet
,
2345 IN FORM_BROWSER_FORM
*Form
,
2346 IN OUT FORM_EXPRESSION
*Expression
2351 EXPRESSION_OPCODE
*OpCode
;
2352 FORM_BROWSER_STATEMENT
*Question
;
2353 FORM_BROWSER_STATEMENT
*Question2
;
2355 EFI_HII_VALUE Data1
;
2356 EFI_HII_VALUE Data2
;
2357 EFI_HII_VALUE Data3
;
2358 FORM_EXPRESSION
*RuleExpression
;
2359 EFI_HII_VALUE
*Value
;
2364 LIST_ENTRY
*SubExpressionLink
;
2365 FORM_EXPRESSION
*SubExpression
;
2372 EFI_HII_VALUE QuestionVal
;
2373 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2378 // Save current stack offset.
2380 StackOffset
= SaveExpressionEvaluationStackOffset ();
2382 ASSERT (Expression
!= NULL
);
2383 Expression
->Result
.Type
= EFI_IFR_TYPE_OTHER
;
2385 Link
= GetFirstNode (&Expression
->OpCodeListHead
);
2386 while (!IsNull (&Expression
->OpCodeListHead
, Link
)) {
2387 OpCode
= EXPRESSION_OPCODE_FROM_LINK (Link
);
2389 Link
= GetNextNode (&Expression
->OpCodeListHead
, Link
);
2391 ZeroMem (&Data1
, sizeof (EFI_HII_VALUE
));
2392 ZeroMem (&Data2
, sizeof (EFI_HII_VALUE
));
2393 ZeroMem (&Data3
, sizeof (EFI_HII_VALUE
));
2396 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
2397 Status
= EFI_SUCCESS
;
2399 switch (OpCode
->Operand
) {
2401 // Built-in functions
2403 case EFI_IFR_EQ_ID_VAL_OP
:
2404 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
2405 if (Question
== NULL
) {
2406 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2410 Status
= CompareHiiValue (&Question
->HiiValue
, &OpCode
->Value
, &Result
, NULL
);
2411 if (Status
== EFI_UNSUPPORTED
) {
2412 Status
= EFI_SUCCESS
;
2413 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2417 if (EFI_ERROR (Status
)) {
2420 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
2423 case EFI_IFR_EQ_ID_ID_OP
:
2424 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
2425 if (Question
== NULL
) {
2426 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2430 Question2
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId2
);
2431 if (Question2
== NULL
) {
2432 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2436 Status
= CompareHiiValue (&Question
->HiiValue
, &Question2
->HiiValue
, &Result
, FormSet
->HiiHandle
);
2437 if (Status
== EFI_UNSUPPORTED
) {
2438 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2439 Status
= EFI_SUCCESS
;
2442 if (EFI_ERROR (Status
)) {
2445 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
2448 case EFI_IFR_EQ_ID_VAL_LIST_OP
:
2449 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
2450 if (Question
== NULL
) {
2451 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2455 Value
->Value
.b
= FALSE
;
2456 for (Index
=0; Index
< OpCode
->ListLength
; Index
++) {
2457 if (Question
->HiiValue
.Value
.u16
== OpCode
->ValueList
[Index
]) {
2458 Value
->Value
.b
= TRUE
;
2464 case EFI_IFR_DUP_OP
:
2465 Status
= PopExpression (Value
);
2466 if (EFI_ERROR (Status
)) {
2470 Status
= PushExpression (Value
);
2473 case EFI_IFR_QUESTION_REF1_OP
:
2474 case EFI_IFR_THIS_OP
:
2475 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
2476 if (Question
== NULL
) {
2477 Status
= EFI_NOT_FOUND
;
2481 Value
= &Question
->HiiValue
;
2484 case EFI_IFR_SECURITY_OP
:
2485 Value
->Value
.b
= CheckUserPrivilege (&OpCode
->Guid
);
2488 case EFI_IFR_GET_OP
:
2490 // Get Value from VarStore buffer, EFI VarStore, Name/Value VarStore.
2492 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2493 Value
->Value
.u8
= 0;
2494 if (OpCode
->VarStorage
!= NULL
) {
2495 switch (OpCode
->VarStorage
->Type
) {
2496 case EFI_HII_VARSTORE_BUFFER
:
2497 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
2499 // Get value from Edit Buffer
2501 Value
->Type
= OpCode
->ValueType
;
2502 CopyMem (&Value
->Value
, OpCode
->VarStorage
->EditBuffer
+ OpCode
->VarStoreInfo
.VarOffset
, OpCode
->ValueWidth
);
2504 case EFI_HII_VARSTORE_NAME_VALUE
:
2505 if (OpCode
->ValueType
!= EFI_IFR_TYPE_STRING
) {
2507 // Get value from string except for STRING value.
2509 Status
= GetValueByName (OpCode
->VarStorage
, OpCode
->ValueName
, &StrPtr
, GetSetValueWithEditBuffer
);
2510 if (!EFI_ERROR (Status
)) {
2511 ASSERT (StrPtr
!= NULL
);
2512 TempLength
= StrLen (StrPtr
);
2513 if (OpCode
->ValueWidth
>= ((TempLength
+ 1) / 2)) {
2514 Value
->Type
= OpCode
->ValueType
;
2515 TempBuffer
= (UINT8
*) &Value
->Value
;
2516 ZeroMem (TempStr
, sizeof (TempStr
));
2517 for (Index
= 0; Index
< TempLength
; Index
++) {
2518 TempStr
[0] = StrPtr
[TempLength
- Index
- 1];
2519 DigitUint8
= (UINT8
) StrHexToUint64 (TempStr
);
2520 if ((Index
& 1) == 0) {
2521 TempBuffer
[Index
/2] = DigitUint8
;
2523 TempBuffer
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + TempBuffer
[Index
/2]);
2530 case EFI_HII_VARSTORE_EFI_VARIABLE
:
2532 // Get value from variable.
2534 TempLength
= OpCode
->ValueWidth
;
2535 Value
->Type
= OpCode
->ValueType
;
2536 Status
= gRT
->GetVariable (
2538 &OpCode
->VarStorage
->Guid
,
2543 if (EFI_ERROR (Status
)) {
2544 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2545 Value
->Value
.u8
= 0;
2550 // Not recognize storage.
2552 Status
= EFI_UNSUPPORTED
;
2557 // For Time/Date Data
2559 if (OpCode
->ValueType
!= EFI_IFR_TYPE_DATE
&& OpCode
->ValueType
!= EFI_IFR_TYPE_TIME
) {
2561 // Only support Data/Time data when storage doesn't exist.
2563 Status
= EFI_UNSUPPORTED
;
2566 Status
= gRT
->GetTime (&EfiTime
, NULL
);
2567 if (!EFI_ERROR (Status
)) {
2568 if (OpCode
->ValueType
== EFI_IFR_TYPE_DATE
) {
2569 switch (OpCode
->VarStoreInfo
.VarOffset
) {
2571 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_16
;
2572 Value
->Value
.u16
= EfiTime
.Year
;
2575 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
2576 Value
->Value
.u8
= EfiTime
.Month
;
2579 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
2580 Value
->Value
.u8
= EfiTime
.Day
;
2584 // Invalid Date field.
2586 Status
= EFI_INVALID_PARAMETER
;
2590 switch (OpCode
->VarStoreInfo
.VarOffset
) {
2592 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
2593 Value
->Value
.u8
= EfiTime
.Hour
;
2596 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
2597 Value
->Value
.u8
= EfiTime
.Minute
;
2600 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
2601 Value
->Value
.u8
= EfiTime
.Second
;
2605 // Invalid Time field.
2607 Status
= EFI_INVALID_PARAMETER
;
2616 case EFI_IFR_QUESTION_REF3_OP
:
2618 // EFI_IFR_QUESTION_REF3
2619 // Pop an expression from the expression stack
2621 Status
= PopExpression (Value
);
2622 if (EFI_ERROR (Status
)) {
2627 // Validate the expression value
2629 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
2630 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2634 if (OpCode
->DevicePath
!= 0) {
2635 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2637 StrPtr
= GetToken (OpCode
->DevicePath
, FormSet
->HiiHandle
);
2638 if (StrPtr
!= NULL
&& mPathFromText
!= NULL
) {
2639 DevicePath
= mPathFromText
->ConvertTextToDevicePath(StrPtr
);
2640 if (DevicePath
!= NULL
&& GetQuestionValueFromForm(DevicePath
, NULL
, &OpCode
->Guid
, Value
->Value
.u16
, &QuestionVal
)) {
2641 Value
= &QuestionVal
;
2643 if (DevicePath
!= NULL
) {
2644 FreePool (DevicePath
);
2648 if (StrPtr
!= NULL
) {
2651 } else if (CompareGuid (&OpCode
->Guid
, &gZeroGuid
) != 0) {
2652 if (!GetQuestionValueFromForm(NULL
, FormSet
->HiiHandle
, &OpCode
->Guid
, Value
->Value
.u16
, &QuestionVal
)){
2653 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2656 Value
= &QuestionVal
;
2658 Question
= IdToQuestion (FormSet
, Form
, Value
->Value
.u16
);
2659 if (Question
== NULL
) {
2660 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2665 // push the questions' value on to the expression stack
2667 Value
= &Question
->HiiValue
;
2671 case EFI_IFR_RULE_REF_OP
:
2673 // Find expression for this rule
2675 RuleExpression
= RuleIdToExpression (Form
, OpCode
->RuleId
);
2676 if (RuleExpression
== NULL
) {
2677 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2682 // Evaluate this rule expression
2684 Status
= EvaluateExpression (FormSet
, Form
, RuleExpression
);
2685 if (EFI_ERROR (Status
) || RuleExpression
->Result
.Type
== EFI_IFR_TYPE_UNDEFINED
) {
2686 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2690 Value
= &RuleExpression
->Result
;
2693 case EFI_IFR_STRING_REF1_OP
:
2694 Value
->Type
= EFI_IFR_TYPE_STRING
;
2695 Value
->Value
.string
= OpCode
->Value
.Value
.string
;
2701 case EFI_IFR_TRUE_OP
:
2702 case EFI_IFR_FALSE_OP
:
2703 case EFI_IFR_ONE_OP
:
2704 case EFI_IFR_ONES_OP
:
2705 case EFI_IFR_UINT8_OP
:
2706 case EFI_IFR_UINT16_OP
:
2707 case EFI_IFR_UINT32_OP
:
2708 case EFI_IFR_UINT64_OP
:
2709 case EFI_IFR_UNDEFINED_OP
:
2710 case EFI_IFR_VERSION_OP
:
2711 case EFI_IFR_ZERO_OP
:
2712 Value
= &OpCode
->Value
;
2718 case EFI_IFR_LENGTH_OP
:
2719 Status
= PopExpression (Value
);
2720 if (EFI_ERROR (Status
)) {
2723 if (Value
->Type
!= EFI_IFR_TYPE_STRING
&& !IsTypeInBuffer (Value
)) {
2724 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2728 if (Value
->Type
== EFI_IFR_TYPE_STRING
) {
2729 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->HiiHandle
);
2730 if (StrPtr
== NULL
) {
2731 Status
= EFI_INVALID_PARAMETER
;
2735 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
2736 Value
->Value
.u64
= StrLen (StrPtr
);
2739 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
2740 Value
->Value
.u64
= GetLengthForValue(Value
);
2741 FreePool (Value
->Buffer
);
2745 case EFI_IFR_NOT_OP
:
2746 Status
= PopExpression (Value
);
2747 if (EFI_ERROR (Status
)) {
2750 if (Value
->Type
!= EFI_IFR_TYPE_BOOLEAN
) {
2751 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2754 Value
->Value
.b
= (BOOLEAN
) (!Value
->Value
.b
);
2757 case EFI_IFR_QUESTION_REF2_OP
:
2759 // Pop an expression from the expression stack
2761 Status
= PopExpression (Value
);
2762 if (EFI_ERROR (Status
)) {
2767 // Validate the expression value
2769 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
2770 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2774 Question
= IdToQuestion (FormSet
, Form
, Value
->Value
.u16
);
2775 if (Question
== NULL
) {
2776 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2780 Value
= &Question
->HiiValue
;
2783 case EFI_IFR_STRING_REF2_OP
:
2785 // Pop an expression from the expression stack
2787 Status
= PopExpression (Value
);
2788 if (EFI_ERROR (Status
)) {
2793 // Validate the expression value
2795 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
2796 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2800 Value
->Type
= EFI_IFR_TYPE_STRING
;
2801 StrPtr
= GetToken (Value
->Value
.u16
, FormSet
->HiiHandle
);
2802 if (StrPtr
== NULL
) {
2804 // If String not exit, push an empty string
2806 Value
->Value
.string
= NewString (gEmptyString
, FormSet
->HiiHandle
);
2808 Index
= (UINT16
) Value
->Value
.u64
;
2809 Value
->Value
.string
= Index
;
2814 case EFI_IFR_TO_BOOLEAN_OP
:
2816 // Pop an expression from the expression stack
2818 Status
= PopExpression (Value
);
2819 if (EFI_ERROR (Status
)) {
2824 // Convert an expression to a Boolean
2826 if (Value
->Type
<= EFI_IFR_TYPE_DATE
) {
2828 // When converting from an unsigned integer, zero will be converted to
2829 // FALSE and any other value will be converted to TRUE.
2831 Value
->Value
.b
= (BOOLEAN
) (HiiValueToUINT64(Value
) != 0);
2833 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
2834 } else if (Value
->Type
== EFI_IFR_TYPE_STRING
) {
2836 // When converting from a string, if case-insensitive compare
2837 // with "true" is True, then push True. If a case-insensitive compare
2838 // with "false" is True, then push False. Otherwise, push Undefined.
2840 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->HiiHandle
);
2841 if (StrPtr
== NULL
) {
2842 Status
= EFI_INVALID_PARAMETER
;
2846 IfrStrToUpper (StrPtr
);
2847 if (StrCmp (StrPtr
, L
"TRUE") == 0){
2848 Value
->Value
.b
= TRUE
;
2849 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
2850 } else if (StrCmp (StrPtr
, L
"FALSE") == 0) {
2851 Value
->Value
.b
= FALSE
;
2852 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
2854 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2857 } else if (Value
->Type
== EFI_IFR_TYPE_BUFFER
) {
2859 // When converting from a buffer, if the buffer is all zeroes,
2860 // then push False. Otherwise push True.
2862 for (Index
=0; Index
< Value
->BufferLen
; Index
++) {
2863 if (Value
->Buffer
[Index
] != 0) {
2868 if (Index
>= Value
->BufferLen
) {
2869 Value
->Value
.b
= FALSE
;
2871 Value
->Value
.b
= TRUE
;
2873 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
2874 FreePool (Value
->Buffer
);
2878 case EFI_IFR_TO_STRING_OP
:
2879 Status
= IfrToString (FormSet
, OpCode
->Format
, Value
);
2882 case EFI_IFR_TO_UINT_OP
:
2883 Status
= IfrToUint (FormSet
, Value
);
2886 case EFI_IFR_TO_LOWER_OP
:
2887 case EFI_IFR_TO_UPPER_OP
:
2888 Status
= InitializeUnicodeCollationProtocol ();
2889 if (EFI_ERROR (Status
)) {
2893 Status
= PopExpression (Value
);
2894 if (EFI_ERROR (Status
)) {
2898 if (Value
->Type
!= EFI_IFR_TYPE_STRING
) {
2899 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2903 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->HiiHandle
);
2904 if (StrPtr
== NULL
) {
2905 Status
= EFI_NOT_FOUND
;
2909 if (OpCode
->Operand
== EFI_IFR_TO_LOWER_OP
) {
2910 mUnicodeCollation
->StrLwr (mUnicodeCollation
, StrPtr
);
2912 mUnicodeCollation
->StrUpr (mUnicodeCollation
, StrPtr
);
2914 Value
->Value
.string
= NewString (StrPtr
, FormSet
->HiiHandle
);
2918 case EFI_IFR_BITWISE_NOT_OP
:
2920 // Pop an expression from the expression stack
2922 Status
= PopExpression (Value
);
2923 if (EFI_ERROR (Status
)) {
2926 if (Value
->Type
> EFI_IFR_TYPE_DATE
) {
2927 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2931 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
2932 Value
->Value
.u64
= ~ HiiValueToUINT64(Value
);
2935 case EFI_IFR_SET_OP
:
2937 // Pop an expression from the expression stack
2939 Status
= PopExpression (Value
);
2940 if (EFI_ERROR (Status
)) {
2943 Data1
.Type
= EFI_IFR_TYPE_BOOLEAN
;
2944 Data1
.Value
.b
= FALSE
;
2946 // Set value to var storage buffer
2948 if (OpCode
->VarStorage
!= NULL
) {
2949 switch (OpCode
->VarStorage
->Type
) {
2950 case EFI_HII_VARSTORE_BUFFER
:
2951 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
2952 CopyMem (OpCode
->VarStorage
->EditBuffer
+ OpCode
->VarStoreInfo
.VarOffset
, &Value
->Value
, OpCode
->ValueWidth
);
2953 Data1
.Value
.b
= TRUE
;
2955 case EFI_HII_VARSTORE_NAME_VALUE
:
2956 if (OpCode
->ValueType
!= EFI_IFR_TYPE_STRING
) {
2957 NameValue
= AllocateZeroPool ((OpCode
->ValueWidth
* 2 + 1) * sizeof (CHAR16
));
2958 ASSERT (Value
!= NULL
);
2960 // Convert Buffer to Hex String
2962 TempBuffer
= (UINT8
*) &Value
->Value
+ OpCode
->ValueWidth
- 1;
2964 for (Index
= 0; Index
< OpCode
->ValueWidth
; Index
++, TempBuffer
--) {
2965 StrPtr
+= UnicodeValueToString (StrPtr
, PREFIX_ZERO
| RADIX_HEX
, *TempBuffer
, 2);
2967 Status
= SetValueByName (OpCode
->VarStorage
, OpCode
->ValueName
, NameValue
, GetSetValueWithEditBuffer
, NULL
);
2968 FreePool (NameValue
);
2969 if (!EFI_ERROR (Status
)) {
2970 Data1
.Value
.b
= TRUE
;
2974 case EFI_HII_VARSTORE_EFI_VARIABLE
:
2975 Status
= gRT
->SetVariable (
2977 &OpCode
->VarStorage
->Guid
,
2978 OpCode
->VarStorage
->Attributes
,
2982 if (!EFI_ERROR (Status
)) {
2983 Data1
.Value
.b
= TRUE
;
2988 // Not recognize storage.
2990 Status
= EFI_UNSUPPORTED
;
2996 // For Time/Date Data
2998 if (OpCode
->ValueType
!= EFI_IFR_TYPE_DATE
&& OpCode
->ValueType
!= EFI_IFR_TYPE_TIME
) {
3000 // Only support Data/Time data when storage doesn't exist.
3002 Status
= EFI_UNSUPPORTED
;
3005 Status
= gRT
->GetTime (&EfiTime
, NULL
);
3006 if (!EFI_ERROR (Status
)) {
3007 if (OpCode
->ValueType
== EFI_IFR_TYPE_DATE
) {
3008 switch (OpCode
->VarStoreInfo
.VarOffset
) {
3010 EfiTime
.Year
= Value
->Value
.u16
;
3013 EfiTime
.Month
= Value
->Value
.u8
;
3016 EfiTime
.Day
= Value
->Value
.u8
;
3020 // Invalid Date field.
3022 Status
= EFI_INVALID_PARAMETER
;
3026 switch (OpCode
->VarStoreInfo
.VarOffset
) {
3028 EfiTime
.Hour
= Value
->Value
.u8
;
3031 EfiTime
.Minute
= Value
->Value
.u8
;
3034 EfiTime
.Second
= Value
->Value
.u8
;
3038 // Invalid Time field.
3040 Status
= EFI_INVALID_PARAMETER
;
3044 Status
= gRT
->SetTime (&EfiTime
);
3045 if (!EFI_ERROR (Status
)) {
3046 Data1
.Value
.b
= TRUE
;
3056 case EFI_IFR_ADD_OP
:
3057 case EFI_IFR_SUBTRACT_OP
:
3058 case EFI_IFR_MULTIPLY_OP
:
3059 case EFI_IFR_DIVIDE_OP
:
3060 case EFI_IFR_MODULO_OP
:
3061 case EFI_IFR_BITWISE_AND_OP
:
3062 case EFI_IFR_BITWISE_OR_OP
:
3063 case EFI_IFR_SHIFT_LEFT_OP
:
3064 case EFI_IFR_SHIFT_RIGHT_OP
:
3066 // Pop an expression from the expression stack
3068 Status
= PopExpression (&Data2
);
3069 if (EFI_ERROR (Status
)) {
3074 // Pop another expression from the expression stack
3076 Status
= PopExpression (&Data1
);
3077 if (EFI_ERROR (Status
)) {
3081 if (Data2
.Type
> EFI_IFR_TYPE_DATE
) {
3082 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3087 if (Data1
.Type
> EFI_IFR_TYPE_DATE
) {
3088 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3092 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
3094 switch (OpCode
->Operand
) {
3095 case EFI_IFR_ADD_OP
:
3096 Value
->Value
.u64
= HiiValueToUINT64(&Data1
) + HiiValueToUINT64(&Data2
);
3099 case EFI_IFR_SUBTRACT_OP
:
3100 Value
->Value
.u64
= HiiValueToUINT64(&Data1
) - HiiValueToUINT64(&Data2
);
3103 case EFI_IFR_MULTIPLY_OP
:
3104 Value
->Value
.u64
= MultU64x32 (HiiValueToUINT64(&Data1
), (UINT32
) HiiValueToUINT64(&Data2
));
3107 case EFI_IFR_DIVIDE_OP
:
3108 Value
->Value
.u64
= DivU64x32 (HiiValueToUINT64(&Data1
), (UINT32
) HiiValueToUINT64(&Data2
));
3111 case EFI_IFR_MODULO_OP
:
3112 DivU64x32Remainder (HiiValueToUINT64(&Data1
), (UINT32
) HiiValueToUINT64(&Data2
), &TempValue
);
3113 Value
->Value
.u64
= TempValue
;
3116 case EFI_IFR_BITWISE_AND_OP
:
3117 Value
->Value
.u64
= HiiValueToUINT64(&Data1
) & HiiValueToUINT64(&Data2
);
3120 case EFI_IFR_BITWISE_OR_OP
:
3121 Value
->Value
.u64
= HiiValueToUINT64(&Data1
) | HiiValueToUINT64(&Data2
);
3124 case EFI_IFR_SHIFT_LEFT_OP
:
3125 Value
->Value
.u64
= LShiftU64 (HiiValueToUINT64(&Data1
), (UINTN
) HiiValueToUINT64(&Data2
));
3128 case EFI_IFR_SHIFT_RIGHT_OP
:
3129 Value
->Value
.u64
= RShiftU64 (HiiValueToUINT64(&Data1
), (UINTN
) HiiValueToUINT64(&Data2
));
3137 case EFI_IFR_AND_OP
:
3140 // Two Boolean operator
3142 Status
= PopExpression (&Data2
);
3143 if (EFI_ERROR (Status
)) {
3148 // Pop another expression from the expression stack
3150 Status
= PopExpression (&Data1
);
3151 if (EFI_ERROR (Status
)) {
3155 if (Data2
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
3156 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3160 if (Data1
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
3161 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3165 if (OpCode
->Operand
== EFI_IFR_AND_OP
) {
3166 Value
->Value
.b
= (BOOLEAN
) (Data1
.Value
.b
&& Data2
.Value
.b
);
3168 Value
->Value
.b
= (BOOLEAN
) (Data1
.Value
.b
|| Data2
.Value
.b
);
3172 case EFI_IFR_EQUAL_OP
:
3173 case EFI_IFR_NOT_EQUAL_OP
:
3174 case EFI_IFR_GREATER_EQUAL_OP
:
3175 case EFI_IFR_GREATER_THAN_OP
:
3176 case EFI_IFR_LESS_EQUAL_OP
:
3177 case EFI_IFR_LESS_THAN_OP
:
3179 // Compare two integer, string, boolean or date/time
3181 Status
= PopExpression (&Data2
);
3182 if (EFI_ERROR (Status
)) {
3187 // Pop another expression from the expression stack
3189 Status
= PopExpression (&Data1
);
3190 if (EFI_ERROR (Status
)) {
3194 if (Data2
.Type
> EFI_IFR_TYPE_BOOLEAN
&&
3195 Data2
.Type
!= EFI_IFR_TYPE_STRING
&&
3196 !IsTypeInBuffer(&Data2
)) {
3197 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3201 if (Data1
.Type
> EFI_IFR_TYPE_BOOLEAN
&&
3202 Data1
.Type
!= EFI_IFR_TYPE_STRING
&&
3203 !IsTypeInBuffer(&Data1
)) {
3204 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3208 Status
= CompareHiiValue (&Data1
, &Data2
, &Result
, FormSet
->HiiHandle
);
3209 if (Data1
.Type
== EFI_IFR_TYPE_BUFFER
) {
3210 FreePool (Data1
.Buffer
);
3212 if (Data2
.Type
== EFI_IFR_TYPE_BUFFER
) {
3213 FreePool (Data2
.Buffer
);
3216 if (Status
== EFI_UNSUPPORTED
) {
3217 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3218 Status
= EFI_SUCCESS
;
3222 if (EFI_ERROR (Status
)) {
3226 switch (OpCode
->Operand
) {
3227 case EFI_IFR_EQUAL_OP
:
3228 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
3231 case EFI_IFR_NOT_EQUAL_OP
:
3232 Value
->Value
.b
= (BOOLEAN
) ((Result
!= 0) ? TRUE
: FALSE
);
3235 case EFI_IFR_GREATER_EQUAL_OP
:
3236 Value
->Value
.b
= (BOOLEAN
) ((Result
>= 0) ? TRUE
: FALSE
);
3239 case EFI_IFR_GREATER_THAN_OP
:
3240 Value
->Value
.b
= (BOOLEAN
) ((Result
> 0) ? TRUE
: FALSE
);
3243 case EFI_IFR_LESS_EQUAL_OP
:
3244 Value
->Value
.b
= (BOOLEAN
) ((Result
<= 0) ? TRUE
: FALSE
);
3247 case EFI_IFR_LESS_THAN_OP
:
3248 Value
->Value
.b
= (BOOLEAN
) ((Result
< 0) ? TRUE
: FALSE
);
3256 case EFI_IFR_MATCH_OP
:
3257 Status
= InitializeUnicodeCollationProtocol ();
3258 if (EFI_ERROR (Status
)) {
3262 Status
= IfrMatch (FormSet
, Value
);
3265 case EFI_IFR_CATENATE_OP
:
3266 Status
= IfrCatenate (FormSet
, Value
);
3272 case EFI_IFR_CONDITIONAL_OP
:
3274 // Pop third expression from the expression stack
3276 Status
= PopExpression (&Data3
);
3277 if (EFI_ERROR (Status
)) {
3282 // Pop second expression from the expression stack
3284 Status
= PopExpression (&Data2
);
3285 if (EFI_ERROR (Status
)) {
3290 // Pop first expression from the expression stack
3292 Status
= PopExpression (&Data1
);
3293 if (EFI_ERROR (Status
)) {
3296 if (Data1
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
3297 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3301 if (Data1
.Value
.b
) {
3308 case EFI_IFR_FIND_OP
:
3309 Status
= IfrFind (FormSet
, OpCode
->Format
, Value
);
3312 case EFI_IFR_MID_OP
:
3313 Status
= IfrMid (FormSet
, Value
);
3316 case EFI_IFR_TOKEN_OP
:
3317 Status
= IfrToken (FormSet
, Value
);
3320 case EFI_IFR_SPAN_OP
:
3321 Status
= IfrSpan (FormSet
, OpCode
->Flags
, Value
);
3324 case EFI_IFR_MAP_OP
:
3326 // Pop the check value
3328 Status
= PopExpression (&Data1
);
3329 if (EFI_ERROR (Status
)) {
3333 // Check MapExpression list is valid.
3335 if (OpCode
->MapExpressionList
.ForwardLink
== NULL
) {
3336 Status
= EFI_INVALID_PARAMETER
;
3340 // Go through map expression list.
3342 SubExpressionLink
= GetFirstNode(&OpCode
->MapExpressionList
);
3343 while (!IsNull (&OpCode
->MapExpressionList
, SubExpressionLink
)) {
3344 SubExpression
= FORM_EXPRESSION_FROM_LINK (SubExpressionLink
);
3346 // Evaluate the first expression in this pair.
3348 Status
= EvaluateExpression (FormSet
, Form
, SubExpression
);
3349 if (EFI_ERROR (Status
)) {
3353 // Compare the expression value with current value
3355 if ((CompareHiiValue (&Data1
, &SubExpression
->Result
, &Result
, NULL
) == EFI_SUCCESS
) && (Result
== 0)) {
3357 // Try get the map value.
3359 SubExpressionLink
= GetNextNode (&OpCode
->MapExpressionList
, SubExpressionLink
);
3360 if (IsNull (&OpCode
->MapExpressionList
, SubExpressionLink
)) {
3361 Status
= EFI_INVALID_PARAMETER
;
3364 SubExpression
= FORM_EXPRESSION_FROM_LINK (SubExpressionLink
);
3365 Status
= EvaluateExpression (FormSet
, Form
, SubExpression
);
3366 if (EFI_ERROR (Status
)) {
3369 Value
= &SubExpression
->Result
;
3373 // Skip the second expression on this pair.
3375 SubExpressionLink
= GetNextNode (&OpCode
->MapExpressionList
, SubExpressionLink
);
3376 if (IsNull (&OpCode
->MapExpressionList
, SubExpressionLink
)) {
3377 Status
= EFI_INVALID_PARAMETER
;
3381 // Goto the first expression on next pair.
3383 SubExpressionLink
= GetNextNode (&OpCode
->MapExpressionList
, SubExpressionLink
);
3387 // No map value is found.
3389 if (IsNull (&OpCode
->MapExpressionList
, SubExpressionLink
)) {
3390 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3391 Value
->Value
.u8
= 0;
3398 if (EFI_ERROR (Status
) || Value
->Type
== EFI_IFR_TYPE_UNDEFINED
) {
3402 Status
= PushExpression (Value
);
3403 if (EFI_ERROR (Status
)) {
3409 // Pop the final result from expression stack
3412 Status
= PopExpression (Value
);
3413 if (EFI_ERROR (Status
)) {
3418 // After evaluating an expression, there should be only one value left on the expression stack
3420 if (PopExpression (Value
) != EFI_ACCESS_DENIED
) {
3421 Status
= EFI_INVALID_PARAMETER
;
3425 RestoreExpressionEvaluationStackOffset (StackOffset
);
3426 if (!EFI_ERROR (Status
)) {
3427 CopyMem (&Expression
->Result
, Value
, sizeof (EFI_HII_VALUE
));
3434 Check whether the result is TRUE or FALSE.
3436 For the EFI_HII_VALUE value type is numeric, return TRUE if the
3439 @param Result Input the result data.
3441 @retval TRUE The result is TRUE.
3442 @retval FALSE The result is FALSE.
3447 IN EFI_HII_VALUE
*Result
3450 switch (Result
->Type
) {
3451 case EFI_IFR_TYPE_BOOLEAN
:
3452 return Result
->Value
.b
;
3454 case EFI_IFR_TYPE_NUM_SIZE_8
:
3455 return (BOOLEAN
)(Result
->Value
.u8
!= 0);
3457 case EFI_IFR_TYPE_NUM_SIZE_16
:
3458 return (BOOLEAN
)(Result
->Value
.u16
!= 0);
3460 case EFI_IFR_TYPE_NUM_SIZE_32
:
3461 return (BOOLEAN
)(Result
->Value
.u32
!= 0);
3463 case EFI_IFR_TYPE_NUM_SIZE_64
:
3464 return (BOOLEAN
)(Result
->Value
.u64
!= 0);
3472 Return the result of the expression list. Check the expression list and
3473 return the highest priority express result.
3474 Priority: DisableIf > SuppressIf > GrayOutIf > FALSE
3476 @param ExpList The input expression list.
3477 @param Evaluate Whether need to evaluate the expression first.
3478 @param FormSet FormSet associated with this expression.
3479 @param Form Form associated with this expression.
3481 @retval EXPRESS_RESULT Return the higher priority express result.
3482 DisableIf > SuppressIf > GrayOutIf > FALSE
3486 EvaluateExpressionList (
3487 IN FORM_EXPRESSION_LIST
*ExpList
,
3488 IN BOOLEAN Evaluate
,
3489 IN FORM_BROWSER_FORMSET
*FormSet
, OPTIONAL
3490 IN FORM_BROWSER_FORM
*Form OPTIONAL
3494 EXPRESS_RESULT ReturnVal
;
3495 EXPRESS_RESULT CompareOne
;
3498 if (ExpList
== NULL
) {
3499 return ExpressFalse
;
3502 ASSERT(ExpList
->Signature
== FORM_EXPRESSION_LIST_SIGNATURE
);
3506 // Check whether need to evaluate the expression first.
3509 while (ExpList
->Count
> Index
) {
3510 Status
= EvaluateExpression (FormSet
, Form
, ExpList
->Expression
[Index
++]);
3511 if (EFI_ERROR (Status
)) {
3512 return ExpressFalse
;
3518 // Run the list of expressions.
3520 ReturnVal
= ExpressFalse
;
3521 for (Index
= 0; Index
< ExpList
->Count
; Index
++) {
3522 if (IsTrue (&ExpList
->Expression
[Index
]->Result
)) {
3523 switch (ExpList
->Expression
[Index
]->Type
) {
3524 case EFI_HII_EXPRESSION_SUPPRESS_IF
:
3525 CompareOne
= ExpressSuppress
;
3528 case EFI_HII_EXPRESSION_GRAY_OUT_IF
:
3529 CompareOne
= ExpressGrayOut
;
3532 case EFI_HII_EXPRESSION_DISABLE_IF
:
3533 CompareOne
= ExpressDisable
;
3537 return ExpressFalse
;
3540 ReturnVal
= ReturnVal
< CompareOne
? CompareOne
: ReturnVal
;