2 Utility functions for expression evaluation.
4 Copyright (c) 2007 - 2013, 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));
993 Evaluate opcode EFI_IFR_TO_STRING.
995 @param FormSet Formset which contains this opcode.
996 @param Format String format in EFI_IFR_TO_STRING.
997 @param Result Evaluation result for this opcode.
999 @retval EFI_SUCCESS Opcode evaluation success.
1000 @retval Other Opcode evaluation failed.
1005 IN FORM_BROWSER_FORMSET
*FormSet
,
1007 OUT EFI_HII_VALUE
*Result
1011 EFI_HII_VALUE Value
;
1013 CHAR16
*PrintFormat
;
1014 CHAR16 Buffer
[MAXIMUM_VALUE_CHARACTERS
];
1018 Status
= PopExpression (&Value
);
1019 if (EFI_ERROR (Status
)) {
1023 switch (Value
.Type
) {
1024 case EFI_IFR_TYPE_NUM_SIZE_8
:
1025 case EFI_IFR_TYPE_NUM_SIZE_16
:
1026 case EFI_IFR_TYPE_NUM_SIZE_32
:
1027 case EFI_IFR_TYPE_NUM_SIZE_64
:
1028 BufferSize
= MAXIMUM_VALUE_CHARACTERS
* sizeof (CHAR16
);
1030 case EFI_IFR_STRING_UNSIGNED_DEC
:
1031 case EFI_IFR_STRING_SIGNED_DEC
:
1032 PrintFormat
= L
"%ld";
1035 case EFI_IFR_STRING_LOWERCASE_HEX
:
1036 PrintFormat
= L
"%lx";
1039 case EFI_IFR_STRING_UPPERCASE_HEX
:
1040 PrintFormat
= L
"%lX";
1044 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1047 UnicodeSPrint (Buffer
, BufferSize
, PrintFormat
, Value
.Value
.u64
);
1051 case EFI_IFR_TYPE_STRING
:
1052 CopyMem (Result
, &Value
, sizeof (EFI_HII_VALUE
));
1055 case EFI_IFR_TYPE_BOOLEAN
:
1056 String
= (Value
.Value
.b
) ? L
"True" : L
"False";
1059 case EFI_IFR_TYPE_BUFFER
:
1061 // + 3 is base on the unicode format, the length may be odd number,
1062 // so need 1 byte to align, also need 2 bytes for L'\0'.
1064 TmpBuf
= AllocateZeroPool (Value
.BufferLen
+ 3);
1065 ASSERT (TmpBuf
!= NULL
);
1066 if (Format
== EFI_IFR_STRING_ASCII
) {
1067 CopyMem (TmpBuf
, Value
.Buffer
, Value
.BufferLen
);
1068 PrintFormat
= L
"%a";
1070 // Format == EFI_IFR_STRING_UNICODE
1071 CopyMem (TmpBuf
, Value
.Buffer
, Value
.BufferLen
* sizeof (CHAR16
));
1072 PrintFormat
= L
"%s";
1074 UnicodeSPrint (Buffer
, sizeof (Buffer
), PrintFormat
, Value
.Buffer
);
1077 FreePool (Value
.Buffer
);
1081 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1085 Result
->Type
= EFI_IFR_TYPE_STRING
;
1086 Result
->Value
.string
= NewString (String
, FormSet
->HiiHandle
);
1092 Evaluate opcode EFI_IFR_TO_UINT.
1094 @param FormSet Formset which contains this opcode.
1095 @param Result Evaluation result for this opcode.
1097 @retval EFI_SUCCESS Opcode evaluation success.
1098 @retval Other Opcode evaluation failed.
1103 IN FORM_BROWSER_FORMSET
*FormSet
,
1104 OUT EFI_HII_VALUE
*Result
1108 EFI_HII_VALUE Value
;
1112 Status
= PopExpression (&Value
);
1113 if (EFI_ERROR (Status
)) {
1117 if (Value
.Type
>= EFI_IFR_TYPE_OTHER
&& Value
.Type
!= EFI_IFR_TYPE_BUFFER
) {
1118 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1122 Status
= EFI_SUCCESS
;
1123 if (Value
.Type
== EFI_IFR_TYPE_STRING
) {
1124 String
= GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
1125 if (String
== NULL
) {
1126 return EFI_NOT_FOUND
;
1129 IfrStrToUpper (String
);
1130 StringPtr
= StrStr (String
, L
"0X");
1131 if (StringPtr
!= NULL
) {
1135 Result
->Value
.u64
= StrHexToUint64 (String
);
1140 Result
->Value
.u64
= StrDecimalToUint64 (String
);
1143 } else if (Value
.Type
== EFI_IFR_TYPE_BUFFER
) {
1144 if (Value
.BufferLen
> 8) {
1145 FreePool (Value
.Buffer
);
1146 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1149 Result
->Value
.u64
= *(UINT64
*) Value
.Buffer
;
1150 FreePool (Value
.Buffer
);
1152 CopyMem (Result
, &Value
, sizeof (EFI_HII_VALUE
));
1155 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1161 Evaluate opcode EFI_IFR_CATENATE.
1163 @param FormSet Formset which contains this opcode.
1164 @param Result Evaluation result for this opcode.
1166 @retval EFI_SUCCESS Opcode evaluation success.
1167 @retval Other Opcode evaluation failed.
1172 IN FORM_BROWSER_FORMSET
*FormSet
,
1173 OUT EFI_HII_VALUE
*Result
1177 EFI_HII_VALUE Value
[2];
1184 // String[0] - The second string
1185 // String[1] - The first string
1190 Status
= EFI_SUCCESS
;
1191 ZeroMem (Value
, sizeof (Value
));
1193 Status
= PopExpression (&Value
[0]);
1194 if (EFI_ERROR (Status
)) {
1198 Status
= PopExpression (&Value
[1]);
1199 if (EFI_ERROR (Status
)) {
1203 for (Index
= 0; Index
< 2; Index
++) {
1204 if (Value
[Index
].Type
!= EFI_IFR_TYPE_STRING
&& Value
[Index
].Type
!= EFI_IFR_TYPE_BUFFER
) {
1205 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1206 Status
= EFI_SUCCESS
;
1210 if (Value
[Index
].Type
== EFI_IFR_TYPE_STRING
) {
1211 String
[Index
] = GetToken (Value
[Index
].Value
.string
, FormSet
->HiiHandle
);
1212 if (String
[Index
] == NULL
) {
1213 Status
= EFI_NOT_FOUND
;
1219 if (Value
[0].Type
== EFI_IFR_TYPE_STRING
) {
1220 Size
= StrSize (String
[0]);
1221 StringPtr
= AllocatePool (StrSize (String
[1]) + Size
);
1222 ASSERT (StringPtr
!= NULL
);
1223 StrCpy (StringPtr
, String
[1]);
1224 StrCat (StringPtr
, String
[0]);
1226 Result
->Type
= EFI_IFR_TYPE_STRING
;
1227 Result
->Value
.string
= NewString (StringPtr
, FormSet
->HiiHandle
);
1229 Result
->Type
= EFI_IFR_TYPE_BUFFER
;
1230 Result
->BufferLen
= (UINT16
) (Value
[0].BufferLen
+ Value
[1].BufferLen
);
1232 Result
->Buffer
= AllocateZeroPool (Result
->BufferLen
);
1233 ASSERT (Result
->Buffer
!= NULL
);
1235 CopyMem (Result
->Buffer
, Value
[0].Buffer
, Value
[0].BufferLen
);
1236 CopyMem (&Result
->Buffer
[Value
[0].BufferLen
], Value
[1].Buffer
, Value
[1].BufferLen
);
1239 if (Value
[0].Buffer
!= NULL
) {
1240 FreePool (Value
[0].Buffer
);
1242 if (Value
[1].Buffer
!= NULL
) {
1243 FreePool (Value
[1].Buffer
);
1245 if (String
[0] != NULL
) {
1246 FreePool (String
[0]);
1248 if (String
[1] != NULL
) {
1249 FreePool (String
[1]);
1251 if (StringPtr
!= NULL
) {
1252 FreePool (StringPtr
);
1260 Evaluate opcode EFI_IFR_MATCH.
1262 @param FormSet Formset which contains this opcode.
1263 @param Result Evaluation result for this opcode.
1265 @retval EFI_SUCCESS Opcode evaluation success.
1266 @retval Other Opcode evaluation failed.
1271 IN FORM_BROWSER_FORMSET
*FormSet
,
1272 OUT EFI_HII_VALUE
*Result
1276 EFI_HII_VALUE Value
[2];
1281 // String[0] - The string to search
1282 // String[1] - pattern
1286 Status
= EFI_SUCCESS
;
1287 ZeroMem (Value
, sizeof (Value
));
1289 Status
= PopExpression (&Value
[0]);
1290 if (EFI_ERROR (Status
)) {
1294 Status
= PopExpression (&Value
[1]);
1295 if (EFI_ERROR (Status
)) {
1299 for (Index
= 0; Index
< 2; Index
++) {
1300 if (Value
[Index
].Type
!= EFI_IFR_TYPE_STRING
) {
1301 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1302 Status
= EFI_SUCCESS
;
1306 String
[Index
] = GetToken (Value
[Index
].Value
.string
, FormSet
->HiiHandle
);
1307 if (String
[Index
] == NULL
) {
1308 Status
= EFI_NOT_FOUND
;
1313 Result
->Type
= EFI_IFR_TYPE_BOOLEAN
;
1314 Result
->Value
.b
= mUnicodeCollation
->MetaiMatch (mUnicodeCollation
, String
[0], String
[1]);
1317 if (String
[0] != NULL
) {
1318 FreePool (String
[0]);
1320 if (String
[1] != NULL
) {
1321 FreePool (String
[1]);
1329 Evaluate opcode EFI_IFR_FIND.
1331 @param FormSet Formset which contains this opcode.
1332 @param Format Case sensitive or insensitive.
1333 @param Result Evaluation result for this opcode.
1335 @retval EFI_SUCCESS Opcode evaluation success.
1336 @retval Other Opcode evaluation failed.
1341 IN FORM_BROWSER_FORMSET
*FormSet
,
1343 OUT EFI_HII_VALUE
*Result
1347 EFI_HII_VALUE Value
[3];
1353 ZeroMem (Value
, sizeof (Value
));
1355 if (Format
> EFI_IFR_FF_CASE_INSENSITIVE
) {
1356 return EFI_INVALID_PARAMETER
;
1359 Status
= PopExpression (&Value
[0]);
1360 if (EFI_ERROR (Status
)) {
1364 Status
= PopExpression (&Value
[1]);
1365 if (EFI_ERROR (Status
)) {
1369 Status
= PopExpression (&Value
[2]);
1370 if (EFI_ERROR (Status
)) {
1374 if (Value
[0].Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1375 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1378 Base
= (UINTN
) Value
[0].Value
.u64
;
1381 // String[0] - sub-string
1382 // String[1] - The string to search
1386 for (Index
= 0; Index
< 2; Index
++) {
1387 if (Value
[Index
+ 1].Type
!= EFI_IFR_TYPE_STRING
) {
1388 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1389 Status
= EFI_SUCCESS
;
1393 String
[Index
] = GetToken (Value
[Index
+ 1].Value
.string
, FormSet
->HiiHandle
);
1394 if (String
[Index
] == NULL
) {
1395 Status
= EFI_NOT_FOUND
;
1399 if (Format
== EFI_IFR_FF_CASE_INSENSITIVE
) {
1401 // Case insensitive, convert both string to upper case
1403 IfrStrToUpper (String
[Index
]);
1407 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1408 if (Base
>= StrLen (String
[1])) {
1409 Result
->Value
.u64
= 0xFFFFFFFFFFFFFFFFULL
;
1411 StringPtr
= StrStr (String
[1] + Base
, String
[0]);
1412 Result
->Value
.u64
= (StringPtr
== NULL
) ? 0xFFFFFFFFFFFFFFFFULL
: (StringPtr
- String
[1]);
1416 if (String
[0] != NULL
) {
1417 FreePool (String
[0]);
1419 if (String
[1] != NULL
) {
1420 FreePool (String
[1]);
1428 Evaluate opcode EFI_IFR_MID.
1430 @param FormSet Formset which contains this opcode.
1431 @param Result Evaluation result for this opcode.
1433 @retval EFI_SUCCESS Opcode evaluation success.
1434 @retval Other Opcode evaluation failed.
1439 IN FORM_BROWSER_FORMSET
*FormSet
,
1440 OUT EFI_HII_VALUE
*Result
1444 EFI_HII_VALUE Value
[3];
1452 ZeroMem (Value
, sizeof (Value
));
1454 Status
= PopExpression (&Value
[0]);
1455 if (EFI_ERROR (Status
)) {
1459 Status
= PopExpression (&Value
[1]);
1460 if (EFI_ERROR (Status
)) {
1464 Status
= PopExpression (&Value
[2]);
1465 if (EFI_ERROR (Status
)) {
1469 if (Value
[0].Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1470 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1473 Length
= (UINTN
) Value
[0].Value
.u64
;
1475 if (Value
[1].Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1476 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1479 Base
= (UINTN
) Value
[1].Value
.u64
;
1481 if (Value
[2].Type
!= EFI_IFR_TYPE_STRING
&& Value
[2].Type
!= EFI_IFR_TYPE_BUFFER
) {
1482 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1485 if (Value
[2].Type
== EFI_IFR_TYPE_STRING
) {
1486 String
= GetToken (Value
[2].Value
.string
, FormSet
->HiiHandle
);
1487 if (String
== NULL
) {
1488 return EFI_NOT_FOUND
;
1491 if (Length
== 0 || Base
>= StrLen (String
)) {
1492 SubString
= gEmptyString
;
1494 SubString
= String
+ Base
;
1495 if ((Base
+ Length
) < StrLen (String
)) {
1496 SubString
[Length
] = L
'\0';
1500 Result
->Type
= EFI_IFR_TYPE_STRING
;
1501 Result
->Value
.string
= NewString (SubString
, FormSet
->HiiHandle
);
1505 Buffer
= Value
[2].Buffer
;
1506 BufferLen
= Value
[2].BufferLen
;
1508 Result
->Type
= EFI_IFR_TYPE_BUFFER
;
1509 if (Length
== 0 || Base
>= BufferLen
) {
1510 Result
->BufferLen
= 0;
1511 Result
->Buffer
= NULL
;
1513 Result
->BufferLen
= (UINT16
)((BufferLen
- Base
) < Length
? (BufferLen
- Base
) : Length
);
1514 Result
->Buffer
= AllocateZeroPool (Result
->BufferLen
);
1515 ASSERT (Result
->Buffer
!= NULL
);
1516 CopyMem (Result
->Buffer
, &Value
[2].Buffer
[Base
], Result
->BufferLen
);
1519 FreePool (Value
[2].Buffer
);
1527 Evaluate opcode EFI_IFR_TOKEN.
1529 @param FormSet Formset which contains this opcode.
1530 @param Result Evaluation result for this opcode.
1532 @retval EFI_SUCCESS Opcode evaluation success.
1533 @retval Other Opcode evaluation failed.
1538 IN FORM_BROWSER_FORMSET
*FormSet
,
1539 OUT EFI_HII_VALUE
*Result
1543 EFI_HII_VALUE Value
[3];
1551 ZeroMem (Value
, sizeof (Value
));
1553 Status
= PopExpression (&Value
[0]);
1554 if (EFI_ERROR (Status
)) {
1558 Status
= PopExpression (&Value
[1]);
1559 if (EFI_ERROR (Status
)) {
1563 Status
= PopExpression (&Value
[2]);
1564 if (EFI_ERROR (Status
)) {
1568 if (Value
[0].Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1569 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1572 Count
= (UINTN
) Value
[0].Value
.u64
;
1575 // String[0] - Delimiter
1576 // String[1] - The string to search
1580 for (Index
= 0; Index
< 2; Index
++) {
1581 if (Value
[Index
+ 1].Type
!= EFI_IFR_TYPE_STRING
) {
1582 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1583 Status
= EFI_SUCCESS
;
1587 String
[Index
] = GetToken (Value
[Index
+ 1].Value
.string
, FormSet
->HiiHandle
);
1588 if (String
[Index
] == NULL
) {
1589 Status
= EFI_NOT_FOUND
;
1594 Delimiter
= String
[0];
1595 SubString
= String
[1];
1597 SubString
= StrStr (SubString
, Delimiter
);
1598 if (SubString
!= NULL
) {
1600 // Skip over the delimiter
1602 SubString
= SubString
+ StrLen (Delimiter
);
1609 if (SubString
== NULL
) {
1611 // nth delimited sub-string not found, push an empty string
1613 SubString
= gEmptyString
;
1616 // Put a NULL terminator for nth delimited sub-string
1618 StringPtr
= StrStr (SubString
, Delimiter
);
1619 if (StringPtr
!= NULL
) {
1624 Result
->Type
= EFI_IFR_TYPE_STRING
;
1625 Result
->Value
.string
= NewString (SubString
, FormSet
->HiiHandle
);
1628 if (String
[0] != NULL
) {
1629 FreePool (String
[0]);
1631 if (String
[1] != NULL
) {
1632 FreePool (String
[1]);
1640 Evaluate opcode EFI_IFR_SPAN.
1642 @param FormSet Formset which contains this opcode.
1643 @param Flags FIRST_MATCHING or FIRST_NON_MATCHING.
1644 @param Result Evaluation result for this opcode.
1646 @retval EFI_SUCCESS Opcode evaluation success.
1647 @retval Other Opcode evaluation failed.
1652 IN FORM_BROWSER_FORMSET
*FormSet
,
1654 OUT EFI_HII_VALUE
*Result
1658 EFI_HII_VALUE Value
[3];
1666 ZeroMem (Value
, sizeof (Value
));
1668 Status
= PopExpression (&Value
[0]);
1669 if (EFI_ERROR (Status
)) {
1673 Status
= PopExpression (&Value
[1]);
1674 if (EFI_ERROR (Status
)) {
1678 Status
= PopExpression (&Value
[2]);
1679 if (EFI_ERROR (Status
)) {
1683 if (Value
[0].Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1684 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1687 Base
= (UINTN
) Value
[0].Value
.u64
;
1690 // String[0] - Charset
1691 // String[1] - The string to search
1695 for (Index
= 0; Index
< 2; Index
++) {
1696 if (Value
[Index
+ 1].Type
!= EFI_IFR_TYPE_STRING
) {
1697 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1698 Status
= EFI_SUCCESS
;
1702 String
[Index
] = GetToken (Value
[Index
+ 1].Value
.string
, FormSet
->HiiHandle
);
1703 if (String
[Index
] == NULL
) {
1704 Status
= EFI_NOT_FOUND
;
1709 if (Base
>= StrLen (String
[1])) {
1710 Result
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1711 Status
= EFI_SUCCESS
;
1716 StringPtr
= String
[1] + Base
;
1717 Charset
= String
[0];
1718 while (*StringPtr
!= 0 && !Found
) {
1720 while (Charset
[Index
] != 0) {
1721 if (*StringPtr
>= Charset
[Index
] && *StringPtr
<= Charset
[Index
+ 1]) {
1722 if (Flags
== EFI_IFR_FLAGS_FIRST_MATCHING
) {
1727 if (Flags
== EFI_IFR_FLAGS_FIRST_NON_MATCHING
) {
1733 // Skip characters pair representing low-end of a range and high-end of a range
1743 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1744 Result
->Value
.u64
= StringPtr
- String
[1];
1747 if (String
[0] != NULL
) {
1748 FreePool (String
[0]);
1750 if (String
[1] != NULL
) {
1751 FreePool (String
[1]);
1759 Zero extend integer/boolean/date/time to UINT64 for comparing.
1761 @param Value HII Value to be converted.
1766 IN EFI_HII_VALUE
*Value
1772 switch (Value
->Type
) {
1773 case EFI_IFR_TYPE_NUM_SIZE_8
:
1774 Temp
= Value
->Value
.u8
;
1777 case EFI_IFR_TYPE_NUM_SIZE_16
:
1778 Temp
= Value
->Value
.u16
;
1781 case EFI_IFR_TYPE_NUM_SIZE_32
:
1782 Temp
= Value
->Value
.u32
;
1785 case EFI_IFR_TYPE_BOOLEAN
:
1786 Temp
= Value
->Value
.b
;
1789 case EFI_IFR_TYPE_TIME
:
1790 Temp
= Value
->Value
.u32
& 0xffffff;
1793 case EFI_IFR_TYPE_DATE
:
1794 Temp
= Value
->Value
.u32
;
1801 Value
->Value
.u64
= Temp
;
1806 Compare two Hii value.
1808 @param Value1 Expression value to compare on left-hand.
1809 @param Value2 Expression value to compare on right-hand.
1810 @param Result Return value after compare.
1811 retval 0 Two operators equal.
1812 return Positive value if Value1 is greater than Value2.
1813 retval Negative value if Value1 is less than Value2.
1814 @param HiiHandle Only required for string compare.
1816 @retval other Could not perform compare on two values.
1817 @retval EFI_SUCCESS Compare the value success.
1822 IN EFI_HII_VALUE
*Value1
,
1823 IN EFI_HII_VALUE
*Value2
,
1825 IN EFI_HII_HANDLE HiiHandle OPTIONAL
1833 if (Value1
->Type
>= EFI_IFR_TYPE_OTHER
|| Value2
->Type
>= EFI_IFR_TYPE_OTHER
) {
1834 if (Value1
->Type
!= EFI_IFR_TYPE_BUFFER
&& Value2
->Type
!= EFI_IFR_TYPE_BUFFER
) {
1835 return EFI_UNSUPPORTED
;
1839 if (Value1
->Type
== EFI_IFR_TYPE_STRING
|| Value2
->Type
== EFI_IFR_TYPE_STRING
) {
1840 if (Value1
->Type
!= Value2
->Type
) {
1842 // Both Operator should be type of String
1844 return EFI_UNSUPPORTED
;
1847 if (Value1
->Value
.string
== 0 || Value2
->Value
.string
== 0) {
1849 // StringId 0 is reserved
1851 return EFI_INVALID_PARAMETER
;
1854 if (Value1
->Value
.string
== Value2
->Value
.string
) {
1859 Str1
= GetToken (Value1
->Value
.string
, HiiHandle
);
1864 return EFI_NOT_FOUND
;
1867 Str2
= GetToken (Value2
->Value
.string
, HiiHandle
);
1870 return EFI_NOT_FOUND
;
1873 *Result
= StrCmp (Str1
, Str2
);
1881 if (Value1
->Type
== EFI_IFR_TYPE_BUFFER
|| Value2
->Type
== EFI_IFR_TYPE_BUFFER
) {
1882 if (Value1
->Type
!= Value2
->Type
) {
1884 // Both Operator should be type of Buffer.
1886 return EFI_UNSUPPORTED
;
1888 Len
= Value1
->BufferLen
> Value2
->BufferLen
? Value2
->BufferLen
: Value1
->BufferLen
;
1889 *Result
= CompareMem (Value1
->Buffer
, Value2
->Buffer
, Len
);
1890 if ((*Result
== 0) && (Value1
->BufferLen
!= Value2
->BufferLen
))
1893 // In this case, means base on samll number buffer, the data is same
1894 // So which value has more data, which value is bigger.
1896 *Result
= Value1
->BufferLen
> Value2
->BufferLen
? 1 : -1;
1902 // Take remain types(integer, boolean, date/time) as integer
1904 Temp64
= (INT64
) (Value1
->Value
.u64
- Value2
->Value
.u64
);
1907 } else if (Temp64
< 0) {
1917 Check if current user has the privilege specified by the permissions GUID.
1919 @param[in] Guid A GUID specifying setup access permissions.
1921 @retval TRUE Current user has the privilege.
1922 @retval FALSE Current user does not have the privilege.
1925 CheckUserPrivilege (
1930 EFI_USER_PROFILE_HANDLE UserProfileHandle
;
1931 EFI_USER_INFO_HANDLE UserInfoHandle
;
1932 EFI_USER_INFO
*UserInfo
;
1933 EFI_GUID
*UserPermissionsGuid
;
1935 UINTN AccessControlDataSize
;
1936 EFI_USER_INFO_ACCESS_CONTROL
*AccessControl
;
1939 if (mUserManager
== NULL
) {
1940 Status
= gBS
->LocateProtocol (
1941 &gEfiUserManagerProtocolGuid
,
1943 (VOID
**) &mUserManager
1945 if (EFI_ERROR (Status
)) {
1947 /// If the system does not support user management, then it is assumed that
1948 /// all users have admin privilege and evaluation of each EFI_IFR_SECURITY
1949 /// op-code is always TRUE.
1955 Status
= mUserManager
->Current (mUserManager
, &UserProfileHandle
);
1956 ASSERT_EFI_ERROR (Status
);
1959 /// Enumerate all user information of the current user profile
1960 /// to look for any EFI_USER_INFO_ACCESS_SETUP record.
1963 for (UserInfoHandle
= NULL
;;) {
1964 Status
= mUserManager
->GetNextInfo (mUserManager
, UserProfileHandle
, &UserInfoHandle
);
1965 if (EFI_ERROR (Status
)) {
1970 Status
= mUserManager
->GetInfo (mUserManager
, UserProfileHandle
, UserInfoHandle
, NULL
, &UserInfoSize
);
1971 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1975 UserInfo
= (EFI_USER_INFO
*) AllocatePool (UserInfoSize
);
1976 if (UserInfo
== NULL
) {
1980 Status
= mUserManager
->GetInfo (mUserManager
, UserProfileHandle
, UserInfoHandle
, UserInfo
, &UserInfoSize
);
1981 if (EFI_ERROR (Status
) ||
1982 UserInfo
->InfoType
!= EFI_USER_INFO_ACCESS_POLICY_RECORD
||
1983 UserInfo
->InfoSize
<= sizeof (EFI_USER_INFO
)) {
1984 FreePool (UserInfo
);
1988 RemainSize
= UserInfo
->InfoSize
- sizeof (EFI_USER_INFO
);
1989 AccessControl
= (EFI_USER_INFO_ACCESS_CONTROL
*)(UserInfo
+ 1);
1990 while (RemainSize
>= sizeof (EFI_USER_INFO_ACCESS_CONTROL
)) {
1991 if (RemainSize
< AccessControl
->Size
|| AccessControl
->Size
< sizeof (EFI_USER_INFO_ACCESS_CONTROL
)) {
1994 if (AccessControl
->Type
== EFI_USER_INFO_ACCESS_SETUP
) {
1996 /// Check if current user has the privilege specified by the permissions GUID.
1999 UserPermissionsGuid
= (EFI_GUID
*)(AccessControl
+ 1);
2000 AccessControlDataSize
= AccessControl
->Size
- sizeof (EFI_USER_INFO_ACCESS_CONTROL
);
2001 while (AccessControlDataSize
>= sizeof (EFI_GUID
)) {
2002 if (CompareGuid (Guid
, UserPermissionsGuid
)) {
2003 FreePool (UserInfo
);
2006 UserPermissionsGuid
++;
2007 AccessControlDataSize
-= sizeof (EFI_GUID
);
2010 RemainSize
-= AccessControl
->Size
;
2011 AccessControl
= (EFI_USER_INFO_ACCESS_CONTROL
*)((UINT8
*)AccessControl
+ AccessControl
->Size
);
2014 FreePool (UserInfo
);
2020 Get question value from the predefined formset.
2022 @param DevicePath The driver's device path which produece the formset data.
2023 @param InputHiiHandle The hii handle associate with the formset data.
2024 @param FormSetGuid The formset guid which include the question.
2025 @param QuestionId The question id which need to get value from.
2026 @param Value The return data about question's value.
2028 @retval TRUE Get the question value success.
2029 @retval FALSE Get the question value failed.
2032 GetQuestionValueFromForm (
2033 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
2034 IN EFI_HII_HANDLE InputHiiHandle
,
2035 IN EFI_GUID
*FormSetGuid
,
2036 IN EFI_QUESTION_ID QuestionId
,
2037 OUT EFI_HII_VALUE
*Value
2041 EFI_HANDLE DriverHandle
;
2043 EFI_HII_HANDLE
*HiiHandles
;
2044 EFI_HII_HANDLE HiiHandle
;
2046 FORM_BROWSER_STATEMENT
*Question
;
2047 FORM_BROWSER_FORMSET
*FormSet
;
2048 FORM_BROWSER_FORM
*Form
;
2053 // The input parameter DevicePath or InputHiiHandle must have one valid input.
2055 ASSERT ((DevicePath
!= NULL
&& InputHiiHandle
== NULL
) ||
2056 (DevicePath
== NULL
&& InputHiiHandle
!= NULL
) );
2059 DriverHandle
= NULL
;
2067 if (DevicePath
!= NULL
) {
2069 // 1. Get Driver handle.
2071 Status
= gBS
->LocateDevicePath (
2072 &gEfiDevicePathProtocolGuid
,
2076 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
2081 // 2. Get Hii handle
2083 HiiHandles
= HiiGetHiiHandles (NULL
);
2084 if (HiiHandles
== NULL
) {
2088 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
2089 Status
= mHiiDatabase
->GetPackageListHandle (
2094 if (!EFI_ERROR (Status
) && (Handle
== DriverHandle
)) {
2095 HiiHandle
= HiiHandles
[Index
];
2099 FreePool (HiiHandles
);
2101 HiiHandle
= InputHiiHandle
;
2103 ASSERT (HiiHandle
!= NULL
);
2106 // Get the formset data include this question.
2108 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
2109 ASSERT (FormSet
!= NULL
);
2110 Status
= InitializeFormSet(HiiHandle
, FormSetGuid
, FormSet
, FALSE
);
2111 if (EFI_ERROR (Status
)) {
2117 // Base on the Question Id to get the question info.
2119 Question
= IdToQuestion(FormSet
, NULL
, QuestionId
);
2120 if (Question
== NULL
) {
2126 // Search form in the formset scope
2128 Link
= GetFirstNode (&FormSet
->FormListHead
);
2129 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
2130 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
2132 Question
= IdToQuestion2 (Form
, QuestionId
);
2133 if (Question
!= NULL
) {
2137 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
2140 ASSERT (Form
!= NULL
);
2143 // Get the question value.
2145 Status
= GetQuestionValue(FormSet
, Form
, Question
, GetSetValueWithHiiDriver
);
2146 if (EFI_ERROR (Status
)) {
2151 CopyMem (Value
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
2155 // Clean the formset structure and restore the global parameter.
2157 if (FormSet
!= NULL
) {
2158 DestroyFormSet (FormSet
);
2165 Evaluate the result of a HII expression.
2167 If Expression is NULL, then ASSERT.
2169 @param FormSet FormSet associated with this expression.
2170 @param Form Form associated with this expression.
2171 @param Expression Expression to be evaluated.
2173 @retval EFI_SUCCESS The expression evaluated successfuly
2174 @retval EFI_NOT_FOUND The Question which referenced by a QuestionId
2176 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
2178 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
2179 @retval EFI_INVALID_PARAMETER Syntax error with the Expression
2183 EvaluateExpression (
2184 IN FORM_BROWSER_FORMSET
*FormSet
,
2185 IN FORM_BROWSER_FORM
*Form
,
2186 IN OUT FORM_EXPRESSION
*Expression
2191 EXPRESSION_OPCODE
*OpCode
;
2192 FORM_BROWSER_STATEMENT
*Question
;
2193 FORM_BROWSER_STATEMENT
*Question2
;
2195 EFI_HII_VALUE Data1
;
2196 EFI_HII_VALUE Data2
;
2197 EFI_HII_VALUE Data3
;
2198 FORM_EXPRESSION
*RuleExpression
;
2199 EFI_HII_VALUE
*Value
;
2204 LIST_ENTRY
*SubExpressionLink
;
2205 FORM_EXPRESSION
*SubExpression
;
2212 EFI_HII_VALUE QuestionVal
;
2213 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2216 // Save current stack offset.
2218 StackOffset
= SaveExpressionEvaluationStackOffset ();
2220 ASSERT (Expression
!= NULL
);
2221 Expression
->Result
.Type
= EFI_IFR_TYPE_OTHER
;
2223 Link
= GetFirstNode (&Expression
->OpCodeListHead
);
2224 while (!IsNull (&Expression
->OpCodeListHead
, Link
)) {
2225 OpCode
= EXPRESSION_OPCODE_FROM_LINK (Link
);
2227 Link
= GetNextNode (&Expression
->OpCodeListHead
, Link
);
2229 ZeroMem (&Data1
, sizeof (EFI_HII_VALUE
));
2230 ZeroMem (&Data2
, sizeof (EFI_HII_VALUE
));
2231 ZeroMem (&Data3
, sizeof (EFI_HII_VALUE
));
2234 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
2235 Status
= EFI_SUCCESS
;
2237 switch (OpCode
->Operand
) {
2239 // Built-in functions
2241 case EFI_IFR_EQ_ID_VAL_OP
:
2242 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
2243 if (Question
== NULL
) {
2244 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2248 Status
= CompareHiiValue (&Question
->HiiValue
, &OpCode
->Value
, &Result
, NULL
);
2249 if (Status
== EFI_UNSUPPORTED
) {
2250 Status
= EFI_SUCCESS
;
2251 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2255 if (EFI_ERROR (Status
)) {
2258 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
2261 case EFI_IFR_EQ_ID_ID_OP
:
2262 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
2263 if (Question
== NULL
) {
2264 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2268 Question2
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId2
);
2269 if (Question2
== NULL
) {
2270 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2274 Status
= CompareHiiValue (&Question
->HiiValue
, &Question2
->HiiValue
, &Result
, FormSet
->HiiHandle
);
2275 if (Status
== EFI_UNSUPPORTED
) {
2276 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2277 Status
= EFI_SUCCESS
;
2280 if (EFI_ERROR (Status
)) {
2283 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
2286 case EFI_IFR_EQ_ID_VAL_LIST_OP
:
2287 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
2288 if (Question
== NULL
) {
2289 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2293 Value
->Value
.b
= FALSE
;
2294 for (Index
=0; Index
< OpCode
->ListLength
; Index
++) {
2295 if (Question
->HiiValue
.Value
.u16
== OpCode
->ValueList
[Index
]) {
2296 Value
->Value
.b
= TRUE
;
2302 case EFI_IFR_DUP_OP
:
2303 Status
= PopExpression (Value
);
2304 if (EFI_ERROR (Status
)) {
2308 Status
= PushExpression (Value
);
2311 case EFI_IFR_QUESTION_REF1_OP
:
2312 case EFI_IFR_THIS_OP
:
2313 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
2314 if (Question
== NULL
) {
2315 Status
= EFI_NOT_FOUND
;
2319 Value
= &Question
->HiiValue
;
2322 case EFI_IFR_SECURITY_OP
:
2323 Value
->Value
.b
= CheckUserPrivilege (&OpCode
->Guid
);
2326 case EFI_IFR_GET_OP
:
2328 // Get Value from VarStore buffer, EFI VarStore, Name/Value VarStore.
2330 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2331 Value
->Value
.u8
= 0;
2332 if (OpCode
->VarStorage
!= NULL
) {
2333 switch (OpCode
->VarStorage
->Type
) {
2334 case EFI_HII_VARSTORE_BUFFER
:
2335 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
2337 // Get value from Edit Buffer
2339 Value
->Type
= OpCode
->ValueType
;
2340 CopyMem (&Value
->Value
, OpCode
->VarStorage
->EditBuffer
+ OpCode
->VarStoreInfo
.VarOffset
, OpCode
->ValueWidth
);
2342 case EFI_HII_VARSTORE_NAME_VALUE
:
2343 if (OpCode
->ValueType
!= EFI_IFR_TYPE_STRING
) {
2345 // Get value from string except for STRING value.
2347 Status
= GetValueByName (OpCode
->VarStorage
, OpCode
->ValueName
, &StrPtr
, GetSetValueWithEditBuffer
);
2348 if (!EFI_ERROR (Status
)) {
2349 ASSERT (StrPtr
!= NULL
);
2350 TempLength
= StrLen (StrPtr
);
2351 if (OpCode
->ValueWidth
>= ((TempLength
+ 1) / 2)) {
2352 Value
->Type
= OpCode
->ValueType
;
2353 TempBuffer
= (UINT8
*) &Value
->Value
;
2354 ZeroMem (TempStr
, sizeof (TempStr
));
2355 for (Index
= 0; Index
< TempLength
; Index
++) {
2356 TempStr
[0] = StrPtr
[TempLength
- Index
- 1];
2357 DigitUint8
= (UINT8
) StrHexToUint64 (TempStr
);
2358 if ((Index
& 1) == 0) {
2359 TempBuffer
[Index
/2] = DigitUint8
;
2361 TempBuffer
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + TempBuffer
[Index
/2]);
2368 case EFI_HII_VARSTORE_EFI_VARIABLE
:
2370 // Get value from variable.
2372 TempLength
= OpCode
->ValueWidth
;
2373 Value
->Type
= OpCode
->ValueType
;
2374 Status
= gRT
->GetVariable (
2376 &OpCode
->VarStorage
->Guid
,
2381 if (EFI_ERROR (Status
)) {
2382 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2383 Value
->Value
.u8
= 0;
2388 // Not recognize storage.
2390 Status
= EFI_UNSUPPORTED
;
2395 // For Time/Date Data
2397 if (OpCode
->ValueType
!= EFI_IFR_TYPE_DATE
&& OpCode
->ValueType
!= EFI_IFR_TYPE_TIME
) {
2399 // Only support Data/Time data when storage doesn't exist.
2401 Status
= EFI_UNSUPPORTED
;
2404 Status
= gRT
->GetTime (&EfiTime
, NULL
);
2405 if (!EFI_ERROR (Status
)) {
2406 if (OpCode
->ValueType
== EFI_IFR_TYPE_DATE
) {
2407 switch (OpCode
->VarStoreInfo
.VarOffset
) {
2409 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_16
;
2410 Value
->Value
.u16
= EfiTime
.Year
;
2413 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
2414 Value
->Value
.u8
= EfiTime
.Month
;
2417 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
2418 Value
->Value
.u8
= EfiTime
.Day
;
2422 // Invalid Date field.
2424 Status
= EFI_INVALID_PARAMETER
;
2428 switch (OpCode
->VarStoreInfo
.VarOffset
) {
2430 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
2431 Value
->Value
.u8
= EfiTime
.Hour
;
2434 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
2435 Value
->Value
.u8
= EfiTime
.Minute
;
2438 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
2439 Value
->Value
.u8
= EfiTime
.Second
;
2443 // Invalid Time field.
2445 Status
= EFI_INVALID_PARAMETER
;
2454 case EFI_IFR_QUESTION_REF3_OP
:
2456 // EFI_IFR_QUESTION_REF3
2457 // Pop an expression from the expression stack
2459 Status
= PopExpression (Value
);
2460 if (EFI_ERROR (Status
)) {
2465 // Validate the expression value
2467 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
2468 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2472 if (OpCode
->DevicePath
!= 0) {
2473 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2475 StrPtr
= GetToken (OpCode
->DevicePath
, FormSet
->HiiHandle
);
2476 if (StrPtr
!= NULL
&& mPathFromText
!= NULL
) {
2477 DevicePath
= mPathFromText
->ConvertTextToDevicePath(StrPtr
);
2478 if (DevicePath
!= NULL
&& GetQuestionValueFromForm(DevicePath
, NULL
, &OpCode
->Guid
, Value
->Value
.u16
, &QuestionVal
)) {
2479 Value
= &QuestionVal
;
2481 if (DevicePath
!= NULL
) {
2482 FreePool (DevicePath
);
2486 if (StrPtr
!= NULL
) {
2489 } else if (CompareGuid (&OpCode
->Guid
, &gZeroGuid
) != 0) {
2490 if (!GetQuestionValueFromForm(NULL
, FormSet
->HiiHandle
, &OpCode
->Guid
, Value
->Value
.u16
, &QuestionVal
)){
2491 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2494 Value
= &QuestionVal
;
2496 Question
= IdToQuestion (FormSet
, Form
, Value
->Value
.u16
);
2497 if (Question
== NULL
) {
2498 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2503 // push the questions' value on to the expression stack
2505 Value
= &Question
->HiiValue
;
2509 case EFI_IFR_RULE_REF_OP
:
2511 // Find expression for this rule
2513 RuleExpression
= RuleIdToExpression (Form
, OpCode
->RuleId
);
2514 if (RuleExpression
== NULL
) {
2515 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2520 // Evaluate this rule expression
2522 Status
= EvaluateExpression (FormSet
, Form
, RuleExpression
);
2523 if (EFI_ERROR (Status
) || RuleExpression
->Result
.Type
== EFI_IFR_TYPE_UNDEFINED
) {
2524 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2528 Value
= &RuleExpression
->Result
;
2531 case EFI_IFR_STRING_REF1_OP
:
2532 Value
->Type
= EFI_IFR_TYPE_STRING
;
2533 Value
->Value
.string
= OpCode
->Value
.Value
.string
;
2539 case EFI_IFR_TRUE_OP
:
2540 case EFI_IFR_FALSE_OP
:
2541 case EFI_IFR_ONE_OP
:
2542 case EFI_IFR_ONES_OP
:
2543 case EFI_IFR_UINT8_OP
:
2544 case EFI_IFR_UINT16_OP
:
2545 case EFI_IFR_UINT32_OP
:
2546 case EFI_IFR_UINT64_OP
:
2547 case EFI_IFR_UNDEFINED_OP
:
2548 case EFI_IFR_VERSION_OP
:
2549 case EFI_IFR_ZERO_OP
:
2550 Value
= &OpCode
->Value
;
2556 case EFI_IFR_LENGTH_OP
:
2557 Status
= PopExpression (Value
);
2558 if (EFI_ERROR (Status
)) {
2561 if (Value
->Type
!= EFI_IFR_TYPE_STRING
&& Value
->Type
!= EFI_IFR_TYPE_BUFFER
) {
2562 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2566 if (Value
->Type
== EFI_IFR_TYPE_STRING
) {
2567 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->HiiHandle
);
2568 if (StrPtr
== NULL
) {
2569 Status
= EFI_INVALID_PARAMETER
;
2573 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
2574 Value
->Value
.u64
= StrLen (StrPtr
);
2577 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
2578 Value
->Value
.u64
= Value
->BufferLen
;
2579 FreePool (Value
->Buffer
);
2583 case EFI_IFR_NOT_OP
:
2584 Status
= PopExpression (Value
);
2585 if (EFI_ERROR (Status
)) {
2588 if (Value
->Type
!= EFI_IFR_TYPE_BOOLEAN
) {
2589 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2592 Value
->Value
.b
= (BOOLEAN
) (!Value
->Value
.b
);
2595 case EFI_IFR_QUESTION_REF2_OP
:
2597 // Pop an expression from the expression stack
2599 Status
= PopExpression (Value
);
2600 if (EFI_ERROR (Status
)) {
2605 // Validate the expression value
2607 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
2608 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2612 Question
= IdToQuestion (FormSet
, Form
, Value
->Value
.u16
);
2613 if (Question
== NULL
) {
2614 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2618 Value
= &Question
->HiiValue
;
2621 case EFI_IFR_STRING_REF2_OP
:
2623 // Pop an expression from the expression stack
2625 Status
= PopExpression (Value
);
2626 if (EFI_ERROR (Status
)) {
2631 // Validate the expression value
2633 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
2634 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2638 Value
->Type
= EFI_IFR_TYPE_STRING
;
2639 StrPtr
= GetToken (Value
->Value
.u16
, FormSet
->HiiHandle
);
2640 if (StrPtr
== NULL
) {
2642 // If String not exit, push an empty string
2644 Value
->Value
.string
= NewString (gEmptyString
, FormSet
->HiiHandle
);
2646 Index
= (UINT16
) Value
->Value
.u64
;
2647 Value
->Value
.string
= Index
;
2652 case EFI_IFR_TO_BOOLEAN_OP
:
2654 // Pop an expression from the expression stack
2656 Status
= PopExpression (Value
);
2657 if (EFI_ERROR (Status
)) {
2662 // Convert an expression to a Boolean
2664 if (Value
->Type
<= EFI_IFR_TYPE_DATE
) {
2666 // When converting from an unsigned integer, zero will be converted to
2667 // FALSE and any other value will be converted to TRUE.
2669 Value
->Value
.b
= (BOOLEAN
) (Value
->Value
.u64
!= 0);
2671 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
2672 } else if (Value
->Type
== EFI_IFR_TYPE_STRING
) {
2674 // When converting from a string, if case-insensitive compare
2675 // with "true" is True, then push True. If a case-insensitive compare
2676 // with "false" is True, then push False. Otherwise, push Undefined.
2678 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->HiiHandle
);
2679 if (StrPtr
== NULL
) {
2680 Status
= EFI_INVALID_PARAMETER
;
2684 IfrStrToUpper (StrPtr
);
2685 if (StrCmp (StrPtr
, L
"TRUE") == 0){
2686 Value
->Value
.b
= TRUE
;
2687 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
2688 } else if (StrCmp (StrPtr
, L
"FALSE") == 0) {
2689 Value
->Value
.b
= FALSE
;
2690 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
2692 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2695 } else if (Value
->Type
== EFI_IFR_TYPE_BUFFER
) {
2697 // When converting from a buffer, if the buffer is all zeroes,
2698 // then push False. Otherwise push True.
2700 for (Index
=0; Index
< Value
->BufferLen
; Index
++) {
2701 if (Value
->Buffer
[Index
] != 0) {
2706 if (Index
>= Value
->BufferLen
) {
2707 Value
->Value
.b
= FALSE
;
2709 Value
->Value
.b
= TRUE
;
2711 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
2712 FreePool (Value
->Buffer
);
2716 case EFI_IFR_TO_STRING_OP
:
2717 Status
= IfrToString (FormSet
, OpCode
->Format
, Value
);
2720 case EFI_IFR_TO_UINT_OP
:
2721 Status
= IfrToUint (FormSet
, Value
);
2724 case EFI_IFR_TO_LOWER_OP
:
2725 case EFI_IFR_TO_UPPER_OP
:
2726 Status
= InitializeUnicodeCollationProtocol ();
2727 if (EFI_ERROR (Status
)) {
2731 Status
= PopExpression (Value
);
2732 if (EFI_ERROR (Status
)) {
2736 if (Value
->Type
!= EFI_IFR_TYPE_STRING
) {
2737 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2741 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->HiiHandle
);
2742 if (StrPtr
== NULL
) {
2743 Status
= EFI_NOT_FOUND
;
2747 if (OpCode
->Operand
== EFI_IFR_TO_LOWER_OP
) {
2748 mUnicodeCollation
->StrLwr (mUnicodeCollation
, StrPtr
);
2750 mUnicodeCollation
->StrUpr (mUnicodeCollation
, StrPtr
);
2752 Value
->Value
.string
= NewString (StrPtr
, FormSet
->HiiHandle
);
2756 case EFI_IFR_BITWISE_NOT_OP
:
2758 // Pop an expression from the expression stack
2760 Status
= PopExpression (Value
);
2761 if (EFI_ERROR (Status
)) {
2764 if (Value
->Type
> EFI_IFR_TYPE_DATE
) {
2765 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2769 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
2770 Value
->Value
.u64
= ~Value
->Value
.u64
;
2773 case EFI_IFR_SET_OP
:
2775 // Pop an expression from the expression stack
2777 Status
= PopExpression (Value
);
2778 if (EFI_ERROR (Status
)) {
2781 Data1
.Type
= EFI_IFR_TYPE_BOOLEAN
;
2782 Data1
.Value
.b
= FALSE
;
2784 // Set value to var storage buffer
2786 if (OpCode
->VarStorage
!= NULL
) {
2787 switch (OpCode
->VarStorage
->Type
) {
2788 case EFI_HII_VARSTORE_BUFFER
:
2789 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
2790 CopyMem (OpCode
->VarStorage
->EditBuffer
+ OpCode
->VarStoreInfo
.VarOffset
, &Value
->Value
, OpCode
->ValueWidth
);
2791 Data1
.Value
.b
= TRUE
;
2793 case EFI_HII_VARSTORE_NAME_VALUE
:
2794 if (OpCode
->ValueType
!= EFI_IFR_TYPE_STRING
) {
2795 NameValue
= AllocateZeroPool ((OpCode
->ValueWidth
* 2 + 1) * sizeof (CHAR16
));
2796 ASSERT (Value
!= NULL
);
2798 // Convert Buffer to Hex String
2800 TempBuffer
= (UINT8
*) &Value
->Value
+ OpCode
->ValueWidth
- 1;
2802 for (Index
= 0; Index
< OpCode
->ValueWidth
; Index
++, TempBuffer
--) {
2803 StrPtr
+= UnicodeValueToString (StrPtr
, PREFIX_ZERO
| RADIX_HEX
, *TempBuffer
, 2);
2805 Status
= SetValueByName (OpCode
->VarStorage
, OpCode
->ValueName
, NameValue
, GetSetValueWithEditBuffer
);
2806 FreePool (NameValue
);
2807 if (!EFI_ERROR (Status
)) {
2808 Data1
.Value
.b
= TRUE
;
2812 case EFI_HII_VARSTORE_EFI_VARIABLE
:
2813 Status
= gRT
->SetVariable (
2815 &OpCode
->VarStorage
->Guid
,
2816 OpCode
->VarStorage
->Attributes
,
2820 if (!EFI_ERROR (Status
)) {
2821 Data1
.Value
.b
= TRUE
;
2826 // Not recognize storage.
2828 Status
= EFI_UNSUPPORTED
;
2834 // For Time/Date Data
2836 if (OpCode
->ValueType
!= EFI_IFR_TYPE_DATE
&& OpCode
->ValueType
!= EFI_IFR_TYPE_TIME
) {
2838 // Only support Data/Time data when storage doesn't exist.
2840 Status
= EFI_UNSUPPORTED
;
2843 Status
= gRT
->GetTime (&EfiTime
, NULL
);
2844 if (!EFI_ERROR (Status
)) {
2845 if (OpCode
->ValueType
== EFI_IFR_TYPE_DATE
) {
2846 switch (OpCode
->VarStoreInfo
.VarOffset
) {
2848 EfiTime
.Year
= Value
->Value
.u16
;
2851 EfiTime
.Month
= Value
->Value
.u8
;
2854 EfiTime
.Day
= Value
->Value
.u8
;
2858 // Invalid Date field.
2860 Status
= EFI_INVALID_PARAMETER
;
2864 switch (OpCode
->VarStoreInfo
.VarOffset
) {
2866 EfiTime
.Hour
= Value
->Value
.u8
;
2869 EfiTime
.Minute
= Value
->Value
.u8
;
2872 EfiTime
.Second
= Value
->Value
.u8
;
2876 // Invalid Time field.
2878 Status
= EFI_INVALID_PARAMETER
;
2882 Status
= gRT
->SetTime (&EfiTime
);
2883 if (!EFI_ERROR (Status
)) {
2884 Data1
.Value
.b
= TRUE
;
2894 case EFI_IFR_ADD_OP
:
2895 case EFI_IFR_SUBTRACT_OP
:
2896 case EFI_IFR_MULTIPLY_OP
:
2897 case EFI_IFR_DIVIDE_OP
:
2898 case EFI_IFR_MODULO_OP
:
2899 case EFI_IFR_BITWISE_AND_OP
:
2900 case EFI_IFR_BITWISE_OR_OP
:
2901 case EFI_IFR_SHIFT_LEFT_OP
:
2902 case EFI_IFR_SHIFT_RIGHT_OP
:
2904 // Pop an expression from the expression stack
2906 Status
= PopExpression (&Data2
);
2907 if (EFI_ERROR (Status
)) {
2912 // Pop another expression from the expression stack
2914 Status
= PopExpression (&Data1
);
2915 if (EFI_ERROR (Status
)) {
2919 if (Data2
.Type
> EFI_IFR_TYPE_DATE
) {
2920 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2925 if (Data1
.Type
> EFI_IFR_TYPE_DATE
) {
2926 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2930 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
2932 switch (OpCode
->Operand
) {
2933 case EFI_IFR_ADD_OP
:
2934 Value
->Value
.u64
= Data1
.Value
.u64
+ Data2
.Value
.u64
;
2937 case EFI_IFR_SUBTRACT_OP
:
2938 Value
->Value
.u64
= Data1
.Value
.u64
- Data2
.Value
.u64
;
2941 case EFI_IFR_MULTIPLY_OP
:
2942 Value
->Value
.u64
= MultU64x32 (Data1
.Value
.u64
, (UINT32
) Data2
.Value
.u64
);
2945 case EFI_IFR_DIVIDE_OP
:
2946 Value
->Value
.u64
= DivU64x32 (Data1
.Value
.u64
, (UINT32
) Data2
.Value
.u64
);
2949 case EFI_IFR_MODULO_OP
:
2950 DivU64x32Remainder (Data1
.Value
.u64
, (UINT32
) Data2
.Value
.u64
, &TempValue
);
2951 Value
->Value
.u64
= TempValue
;
2954 case EFI_IFR_BITWISE_AND_OP
:
2955 Value
->Value
.u64
= Data1
.Value
.u64
& Data2
.Value
.u64
;
2958 case EFI_IFR_BITWISE_OR_OP
:
2959 Value
->Value
.u64
= Data1
.Value
.u64
| Data2
.Value
.u64
;
2962 case EFI_IFR_SHIFT_LEFT_OP
:
2963 Value
->Value
.u64
= LShiftU64 (Data1
.Value
.u64
, (UINTN
) Data2
.Value
.u64
);
2966 case EFI_IFR_SHIFT_RIGHT_OP
:
2967 Value
->Value
.u64
= RShiftU64 (Data1
.Value
.u64
, (UINTN
) Data2
.Value
.u64
);
2975 case EFI_IFR_AND_OP
:
2978 // Two Boolean operator
2980 Status
= PopExpression (&Data2
);
2981 if (EFI_ERROR (Status
)) {
2986 // Pop another expression from the expression stack
2988 Status
= PopExpression (&Data1
);
2989 if (EFI_ERROR (Status
)) {
2993 if (Data2
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
2994 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2998 if (Data1
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
2999 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3003 if (OpCode
->Operand
== EFI_IFR_AND_OP
) {
3004 Value
->Value
.b
= (BOOLEAN
) (Data1
.Value
.b
&& Data2
.Value
.b
);
3006 Value
->Value
.b
= (BOOLEAN
) (Data1
.Value
.b
|| Data2
.Value
.b
);
3010 case EFI_IFR_EQUAL_OP
:
3011 case EFI_IFR_NOT_EQUAL_OP
:
3012 case EFI_IFR_GREATER_EQUAL_OP
:
3013 case EFI_IFR_GREATER_THAN_OP
:
3014 case EFI_IFR_LESS_EQUAL_OP
:
3015 case EFI_IFR_LESS_THAN_OP
:
3017 // Compare two integer, string, boolean or date/time
3019 Status
= PopExpression (&Data2
);
3020 if (EFI_ERROR (Status
)) {
3025 // Pop another expression from the expression stack
3027 Status
= PopExpression (&Data1
);
3028 if (EFI_ERROR (Status
)) {
3032 if (Data2
.Type
> EFI_IFR_TYPE_BOOLEAN
&&
3033 Data2
.Type
!= EFI_IFR_TYPE_STRING
&&
3034 Data2
.Type
!= EFI_IFR_TYPE_BUFFER
) {
3035 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3039 if (Data1
.Type
> EFI_IFR_TYPE_BOOLEAN
&&
3040 Data1
.Type
!= EFI_IFR_TYPE_STRING
&&
3041 Data1
.Type
!= EFI_IFR_TYPE_BUFFER
) {
3042 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3046 Status
= CompareHiiValue (&Data1
, &Data2
, &Result
, FormSet
->HiiHandle
);
3047 if (Data1
.Type
== EFI_IFR_TYPE_BUFFER
) {
3048 FreePool (Data1
.Buffer
);
3049 FreePool (Data2
.Buffer
);
3052 if (Status
== EFI_UNSUPPORTED
) {
3053 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3054 Status
= EFI_SUCCESS
;
3058 if (EFI_ERROR (Status
)) {
3062 switch (OpCode
->Operand
) {
3063 case EFI_IFR_EQUAL_OP
:
3064 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
3067 case EFI_IFR_NOT_EQUAL_OP
:
3068 Value
->Value
.b
= (BOOLEAN
) ((Result
!= 0) ? TRUE
: FALSE
);
3071 case EFI_IFR_GREATER_EQUAL_OP
:
3072 Value
->Value
.b
= (BOOLEAN
) ((Result
>= 0) ? TRUE
: FALSE
);
3075 case EFI_IFR_GREATER_THAN_OP
:
3076 Value
->Value
.b
= (BOOLEAN
) ((Result
> 0) ? TRUE
: FALSE
);
3079 case EFI_IFR_LESS_EQUAL_OP
:
3080 Value
->Value
.b
= (BOOLEAN
) ((Result
<= 0) ? TRUE
: FALSE
);
3083 case EFI_IFR_LESS_THAN_OP
:
3084 Value
->Value
.b
= (BOOLEAN
) ((Result
< 0) ? TRUE
: FALSE
);
3092 case EFI_IFR_MATCH_OP
:
3093 Status
= InitializeUnicodeCollationProtocol ();
3094 if (EFI_ERROR (Status
)) {
3098 Status
= IfrMatch (FormSet
, Value
);
3101 case EFI_IFR_CATENATE_OP
:
3102 Status
= IfrCatenate (FormSet
, Value
);
3108 case EFI_IFR_CONDITIONAL_OP
:
3110 // Pop third expression from the expression stack
3112 Status
= PopExpression (&Data3
);
3113 if (EFI_ERROR (Status
)) {
3118 // Pop second expression from the expression stack
3120 Status
= PopExpression (&Data2
);
3121 if (EFI_ERROR (Status
)) {
3126 // Pop first expression from the expression stack
3128 Status
= PopExpression (&Data1
);
3129 if (EFI_ERROR (Status
)) {
3132 if (Data1
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
3133 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3137 if (Data1
.Value
.b
) {
3144 case EFI_IFR_FIND_OP
:
3145 Status
= IfrFind (FormSet
, OpCode
->Format
, Value
);
3148 case EFI_IFR_MID_OP
:
3149 Status
= IfrMid (FormSet
, Value
);
3152 case EFI_IFR_TOKEN_OP
:
3153 Status
= IfrToken (FormSet
, Value
);
3156 case EFI_IFR_SPAN_OP
:
3157 Status
= IfrSpan (FormSet
, OpCode
->Flags
, Value
);
3160 case EFI_IFR_MAP_OP
:
3162 // Pop the check value
3164 Status
= PopExpression (&Data1
);
3165 if (EFI_ERROR (Status
)) {
3169 // Check MapExpression list is valid.
3171 if (OpCode
->MapExpressionList
.ForwardLink
== NULL
) {
3172 Status
= EFI_INVALID_PARAMETER
;
3176 // Go through map expression list.
3178 SubExpressionLink
= GetFirstNode(&OpCode
->MapExpressionList
);
3179 while (!IsNull (&OpCode
->MapExpressionList
, SubExpressionLink
)) {
3180 SubExpression
= FORM_EXPRESSION_FROM_LINK (SubExpressionLink
);
3182 // Evaluate the first expression in this pair.
3184 Status
= EvaluateExpression (FormSet
, Form
, SubExpression
);
3185 if (EFI_ERROR (Status
)) {
3189 // Compare the expression value with current value
3191 if ((CompareHiiValue (&Data1
, &SubExpression
->Result
, &Result
, NULL
) == EFI_SUCCESS
) && (Result
== 0)) {
3193 // Try get the map value.
3195 SubExpressionLink
= GetNextNode (&OpCode
->MapExpressionList
, SubExpressionLink
);
3196 if (IsNull (&OpCode
->MapExpressionList
, SubExpressionLink
)) {
3197 Status
= EFI_INVALID_PARAMETER
;
3200 SubExpression
= FORM_EXPRESSION_FROM_LINK (SubExpressionLink
);
3201 Status
= EvaluateExpression (FormSet
, Form
, SubExpression
);
3202 if (EFI_ERROR (Status
)) {
3205 Value
= &SubExpression
->Result
;
3209 // Skip the second expression on this pair.
3211 SubExpressionLink
= GetNextNode (&OpCode
->MapExpressionList
, SubExpressionLink
);
3212 if (IsNull (&OpCode
->MapExpressionList
, SubExpressionLink
)) {
3213 Status
= EFI_INVALID_PARAMETER
;
3217 // Goto the first expression on next pair.
3219 SubExpressionLink
= GetNextNode (&OpCode
->MapExpressionList
, SubExpressionLink
);
3223 // No map value is found.
3225 if (IsNull (&OpCode
->MapExpressionList
, SubExpressionLink
)) {
3226 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
3227 Value
->Value
.u8
= 0;
3234 if (EFI_ERROR (Status
) || Value
->Type
== EFI_IFR_TYPE_UNDEFINED
) {
3238 Status
= PushExpression (Value
);
3239 if (EFI_ERROR (Status
)) {
3245 // Pop the final result from expression stack
3248 Status
= PopExpression (Value
);
3249 if (EFI_ERROR (Status
)) {
3254 // After evaluating an expression, there should be only one value left on the expression stack
3256 if (PopExpression (Value
) != EFI_ACCESS_DENIED
) {
3257 Status
= EFI_INVALID_PARAMETER
;
3261 RestoreExpressionEvaluationStackOffset (StackOffset
);
3262 if (!EFI_ERROR (Status
)) {
3263 CopyMem (&Expression
->Result
, Value
, sizeof (EFI_HII_VALUE
));
3270 Return the result of the expression list. Check the expression list and
3271 return the highest priority express result.
3272 Priority: DisableIf > SuppressIf > GrayOutIf > FALSE
3274 @param ExpList The input expression list.
3275 @param Evaluate Whether need to evaluate the expression first.
3276 @param FormSet FormSet associated with this expression.
3277 @param Form Form associated with this expression.
3279 @retval EXPRESS_RESULT Return the higher priority express result.
3280 DisableIf > SuppressIf > GrayOutIf > FALSE
3284 EvaluateExpressionList (
3285 IN FORM_EXPRESSION_LIST
*ExpList
,
3286 IN BOOLEAN Evaluate
,
3287 IN FORM_BROWSER_FORMSET
*FormSet
, OPTIONAL
3288 IN FORM_BROWSER_FORM
*Form OPTIONAL
3292 EXPRESS_RESULT ReturnVal
;
3293 EXPRESS_RESULT CompareOne
;
3296 if (ExpList
== NULL
) {
3297 return ExpressFalse
;
3300 ASSERT(ExpList
->Signature
== FORM_EXPRESSION_LIST_SIGNATURE
);
3304 // Check whether need to evaluate the expression first.
3307 while (ExpList
->Count
> Index
) {
3308 Status
= EvaluateExpression (FormSet
, Form
, ExpList
->Expression
[Index
++]);
3309 if (EFI_ERROR (Status
)) {
3310 return ExpressFalse
;
3316 // Run the list of expressions.
3318 ReturnVal
= ExpressFalse
;
3319 for (Index
= 0; Index
< ExpList
->Count
; Index
++) {
3320 if (ExpList
->Expression
[Index
]->Result
.Type
== EFI_IFR_TYPE_BOOLEAN
&&
3321 ExpList
->Expression
[Index
]->Result
.Value
.b
) {
3322 switch (ExpList
->Expression
[Index
]->Type
) {
3323 case EFI_HII_EXPRESSION_SUPPRESS_IF
:
3324 CompareOne
= ExpressSuppress
;
3327 case EFI_HII_EXPRESSION_GRAY_OUT_IF
:
3328 CompareOne
= ExpressGrayOut
;
3331 case EFI_HII_EXPRESSION_DISABLE_IF
:
3332 CompareOne
= ExpressDisable
;
3336 return ExpressFalse
;
3339 ReturnVal
= ReturnVal
< CompareOne
? CompareOne
: ReturnVal
;