2 Utility functions for expression evaluation.
4 Copyright (c) 2007 - 2012, 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
;
38 // Unicode collation protocol interface
40 EFI_UNICODE_COLLATION_PROTOCOL
*mUnicodeCollation
= NULL
;
41 EFI_USER_MANAGER_PROTOCOL
*mUserManager
= NULL
;
44 Grow size of the stack.
46 This is an internal function.
48 @param Stack On input: old stack; On output: new stack
49 @param StackPtr On input: old stack pointer; On output: new stack
51 @param StackEnd On input: old stack end; On output: new stack end
53 @retval EFI_SUCCESS Grow stack success.
54 @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.
59 IN OUT EFI_HII_VALUE
**Stack
,
60 IN OUT EFI_HII_VALUE
**StackPtr
,
61 IN OUT EFI_HII_VALUE
**StackEnd
65 EFI_HII_VALUE
*NewStack
;
67 Size
= EXPRESSION_STACK_SIZE_INCREMENT
;
68 if (*StackPtr
!= NULL
) {
69 Size
= Size
+ (*StackEnd
- *Stack
);
72 NewStack
= AllocatePool (Size
* sizeof (EFI_HII_VALUE
));
73 if (NewStack
== NULL
) {
74 return EFI_OUT_OF_RESOURCES
;
77 if (*StackPtr
!= NULL
) {
79 // Copy from Old Stack to the New Stack
84 (*StackEnd
- *Stack
) * sizeof (EFI_HII_VALUE
)
94 // Make the Stack pointer point to the old data in the new stack
96 *StackPtr
= NewStack
+ (*StackPtr
- *Stack
);
98 *StackEnd
= NewStack
+ Size
;
105 Push an element onto the Boolean Stack.
107 @param Stack On input: old stack; On output: new stack
108 @param StackPtr On input: old stack pointer; On output: new stack
110 @param StackEnd On input: old stack end; On output: new stack end
111 @param Data Data to push.
113 @retval EFI_SUCCESS Push stack success.
118 IN OUT EFI_HII_VALUE
**Stack
,
119 IN OUT EFI_HII_VALUE
**StackPtr
,
120 IN OUT EFI_HII_VALUE
**StackEnd
,
121 IN EFI_HII_VALUE
*Data
127 // Check for a stack overflow condition
129 if (*StackPtr
>= *StackEnd
) {
133 Status
= GrowStack (Stack
, StackPtr
, StackEnd
);
134 if (EFI_ERROR (Status
)) {
140 // Push the item onto the stack
142 CopyMem (*StackPtr
, Data
, sizeof (EFI_HII_VALUE
));
143 if (Data
->Type
== EFI_IFR_TYPE_BUFFER
) {
144 (*StackPtr
)->Buffer
= AllocateCopyPool(Data
->BufferLen
, Data
->Buffer
);
145 ASSERT ((*StackPtr
)->Buffer
!= NULL
);
148 *StackPtr
= *StackPtr
+ 1;
155 Pop an element from the stack.
157 @param Stack On input: old stack
158 @param StackPtr On input: old stack pointer; On output: new stack pointer
159 @param Data Data to pop.
161 @retval EFI_SUCCESS The value was popped onto the stack.
162 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
167 IN EFI_HII_VALUE
*Stack
,
168 IN OUT EFI_HII_VALUE
**StackPtr
,
169 OUT EFI_HII_VALUE
*Data
173 // Check for a stack underflow condition
175 if (*StackPtr
== Stack
) {
176 return EFI_ACCESS_DENIED
;
180 // Pop the item off the stack
182 *StackPtr
= *StackPtr
- 1;
183 CopyMem (Data
, *StackPtr
, sizeof (EFI_HII_VALUE
));
189 Reset stack pointer to begin of the stack.
193 ResetCurrentExpressionStack (
197 mCurrentExpressionPointer
= mCurrentExpressionStack
;
202 Push current expression onto the Stack
204 @param Pointer Pointer to current expression.
206 @retval EFI_SUCCESS The value was pushed onto the stack.
207 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
211 PushCurrentExpression (
217 Data
.Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
218 Data
.Value
.u64
= (UINT64
) (UINTN
) Pointer
;
221 &mCurrentExpressionStack
,
222 &mCurrentExpressionPointer
,
223 &mCurrentExpressionEnd
,
230 Pop current expression from the Stack
232 @param Pointer Pointer to current expression to be pop.
234 @retval EFI_SUCCESS The value was pushed onto the stack.
235 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
239 PopCurrentExpression (
247 mCurrentExpressionStack
,
248 &mCurrentExpressionPointer
,
252 *Pointer
= (VOID
*) (UINTN
) Data
.Value
.u64
;
258 Reset stack pointer to begin of the stack.
262 ResetMapExpressionListStack (
266 mMapExpressionListPointer
= mMapExpressionListStack
;
271 Push the list of map expression onto the Stack
273 @param Pointer Pointer to the list of map expression to be pushed.
275 @retval EFI_SUCCESS The value was pushed onto the stack.
276 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
280 PushMapExpressionList (
286 Data
.Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
287 Data
.Value
.u64
= (UINT64
) (UINTN
) Pointer
;
290 &mMapExpressionListStack
,
291 &mMapExpressionListPointer
,
292 &mMapExpressionListEnd
,
299 Pop the list of map expression from the Stack
301 @param Pointer Pointer to the list of map expression to be pop.
303 @retval EFI_SUCCESS The value was pushed onto the stack.
304 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
308 PopMapExpressionList (
316 mMapExpressionListStack
,
317 &mMapExpressionListPointer
,
321 *Pointer
= (VOID
*) (UINTN
) Data
.Value
.u64
;
327 Reset stack pointer to begin of the stack.
335 mOpCodeScopeStackPointer
= mOpCodeScopeStack
;
340 Push an Operand onto the Stack
342 @param Operand Operand to push.
344 @retval EFI_SUCCESS The value was pushed onto the stack.
345 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
356 Data
.Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
357 Data
.Value
.u8
= Operand
;
361 &mOpCodeScopeStackPointer
,
362 &mOpCodeScopeStackEnd
,
369 Pop an Operand from the Stack
371 @param Operand Operand to pop.
373 @retval EFI_SUCCESS The value was pushed onto the stack.
374 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
388 &mOpCodeScopeStackPointer
,
392 *Operand
= Data
.Value
.u8
;
399 Push an Expression value onto the Stack
401 @param Value Expression value to push.
403 @retval EFI_SUCCESS The value was pushed onto the stack.
404 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
410 IN EFI_HII_VALUE
*Value
414 &mExpressionEvaluationStack
,
415 &mExpressionEvaluationStackPointer
,
416 &mExpressionEvaluationStackEnd
,
423 Pop an Expression value from the stack.
425 @param Value Expression value to pop.
427 @retval EFI_SUCCESS The value was popped onto the stack.
428 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
433 OUT EFI_HII_VALUE
*Value
437 mExpressionEvaluationStack
+ mExpressionEvaluationStackOffset
,
438 &mExpressionEvaluationStackPointer
,
444 Get current stack offset from stack start.
446 @return Stack offset to stack start.
449 SaveExpressionEvaluationStackOffset (
452 UINTN TempStackOffset
;
453 TempStackOffset
= mExpressionEvaluationStackOffset
;
454 mExpressionEvaluationStackOffset
= mExpressionEvaluationStackPointer
- mExpressionEvaluationStack
;
455 return TempStackOffset
;
459 Restore stack offset based on input stack offset
461 @param StackOffset Offset to stack start.
465 RestoreExpressionEvaluationStackOffset (
469 mExpressionEvaluationStackOffset
= StackOffset
;
473 Get Form given its FormId.
475 @param FormSet The formset which contains this form.
476 @param FormId Id of this form.
478 @retval Pointer The form.
479 @retval NULL Specified Form is not found in the formset.
484 IN FORM_BROWSER_FORMSET
*FormSet
,
489 FORM_BROWSER_FORM
*Form
;
491 Link
= GetFirstNode (&FormSet
->FormListHead
);
492 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
493 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
495 if (Form
->FormId
== FormId
) {
499 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
507 Search a Question in Form scope using its QuestionId.
509 @param Form The form which contains this Question.
510 @param QuestionId Id of this Question.
512 @retval Pointer The Question.
513 @retval NULL Specified Question not found in the form.
516 FORM_BROWSER_STATEMENT
*
518 IN FORM_BROWSER_FORM
*Form
,
523 FORM_BROWSER_STATEMENT
*Question
;
525 if (QuestionId
== 0 || Form
== NULL
) {
527 // The value of zero is reserved
532 Link
= GetFirstNode (&Form
->StatementListHead
);
533 while (!IsNull (&Form
->StatementListHead
, Link
)) {
534 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
536 if (Question
->QuestionId
== QuestionId
) {
540 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
548 Search a Question in Formset scope using its QuestionId.
550 @param FormSet The formset which contains this form.
551 @param Form The form which contains this Question.
552 @param QuestionId Id of this Question.
554 @retval Pointer The Question.
555 @retval NULL Specified Question not found in the form.
558 FORM_BROWSER_STATEMENT
*
560 IN FORM_BROWSER_FORMSET
*FormSet
,
561 IN FORM_BROWSER_FORM
*Form
,
566 FORM_BROWSER_STATEMENT
*Question
;
569 // Search in the form scope first
571 Question
= IdToQuestion2 (Form
, QuestionId
);
572 if (Question
!= NULL
) {
577 // Search in the formset scope
579 Link
= GetFirstNode (&FormSet
->FormListHead
);
580 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
581 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
583 Question
= IdToQuestion2 (Form
, QuestionId
);
584 if (Question
!= NULL
) {
586 // EFI variable storage may be updated by Callback() asynchronous,
587 // to keep synchronous, always reload the Question Value.
589 if (Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
590 GetQuestionValue (FormSet
, Form
, Question
, FALSE
);
596 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
604 Get Expression given its RuleId.
606 @param Form The form which contains this Expression.
607 @param RuleId Id of this Expression.
609 @retval Pointer The Expression.
610 @retval NULL Specified Expression not found in the form.
615 IN FORM_BROWSER_FORM
*Form
,
620 FORM_EXPRESSION
*Expression
;
622 Link
= GetFirstNode (&Form
->ExpressionListHead
);
623 while (!IsNull (&Form
->ExpressionListHead
, Link
)) {
624 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
626 if (Expression
->Type
== EFI_HII_EXPRESSION_RULE
&& Expression
->RuleId
== RuleId
) {
630 Link
= GetNextNode (&Form
->ExpressionListHead
, Link
);
638 Locate the Unicode Collation Protocol interface for later use.
640 @retval EFI_SUCCESS Protocol interface initialize success.
641 @retval Other Protocol interface initialize failed.
645 InitializeUnicodeCollationProtocol (
651 if (mUnicodeCollation
!= NULL
) {
656 // BUGBUG: Proper impelmentation is to locate all Unicode Collation Protocol
657 // instances first and then select one which support English language.
658 // Current implementation just pick the first instance.
660 Status
= gBS
->LocateProtocol (
661 &gEfiUnicodeCollation2ProtocolGuid
,
663 (VOID
**) &mUnicodeCollation
669 Convert the input Unicode character to upper.
671 @param String Th Unicode character to be converted.
679 while (*String
!= 0) {
680 if ((*String
>= 'a') && (*String
<= 'z')) {
681 *String
= (UINT16
) ((*String
) & ((UINT16
) ~0x20));
689 Evaluate opcode EFI_IFR_TO_STRING.
691 @param FormSet Formset which contains this opcode.
692 @param Format String format in EFI_IFR_TO_STRING.
693 @param Result Evaluation result for this opcode.
695 @retval EFI_SUCCESS Opcode evaluation success.
696 @retval Other Opcode evaluation failed.
701 IN FORM_BROWSER_FORMSET
*FormSet
,
703 OUT EFI_HII_VALUE
*Result
710 CHAR16 Buffer
[MAXIMUM_VALUE_CHARACTERS
];
714 Status
= PopExpression (&Value
);
715 if (EFI_ERROR (Status
)) {
719 switch (Value
.Type
) {
720 case EFI_IFR_TYPE_NUM_SIZE_8
:
721 case EFI_IFR_TYPE_NUM_SIZE_16
:
722 case EFI_IFR_TYPE_NUM_SIZE_32
:
723 case EFI_IFR_TYPE_NUM_SIZE_64
:
724 BufferSize
= MAXIMUM_VALUE_CHARACTERS
* sizeof (CHAR16
);
726 case EFI_IFR_STRING_UNSIGNED_DEC
:
727 case EFI_IFR_STRING_SIGNED_DEC
:
728 PrintFormat
= L
"%ld";
731 case EFI_IFR_STRING_LOWERCASE_HEX
:
732 PrintFormat
= L
"%lx";
735 case EFI_IFR_STRING_UPPERCASE_HEX
:
736 PrintFormat
= L
"%lX";
740 return EFI_UNSUPPORTED
;
742 UnicodeSPrint (Buffer
, BufferSize
, PrintFormat
, Value
.Value
.u64
);
746 case EFI_IFR_TYPE_STRING
:
747 CopyMem (Result
, &Value
, sizeof (EFI_HII_VALUE
));
750 case EFI_IFR_TYPE_BOOLEAN
:
751 String
= (Value
.Value
.b
) ? L
"True" : L
"False";
754 case EFI_IFR_TYPE_BUFFER
:
756 // + 3 is base on the unicode format, the length may be odd number,
757 // so need 1 byte to align, also need 2 bytes for L'\0'.
759 TmpBuf
= AllocateZeroPool (Value
.BufferLen
+ 3);
760 ASSERT (TmpBuf
!= NULL
);
761 if (Format
== EFI_IFR_STRING_ASCII
) {
762 CopyMem (TmpBuf
, Value
.Buffer
, Value
.BufferLen
);
765 // Format == EFI_IFR_STRING_UNICODE
766 CopyMem (TmpBuf
, Value
.Buffer
, Value
.BufferLen
* sizeof (CHAR16
));
769 UnicodeSPrint (Buffer
, MAXIMUM_VALUE_CHARACTERS
, PrintFormat
, Value
.Buffer
);
772 FreePool (Value
.Buffer
);
776 return EFI_UNSUPPORTED
;
779 Result
->Type
= EFI_IFR_TYPE_STRING
;
780 Result
->Value
.string
= NewString (String
, FormSet
->HiiHandle
);
786 Evaluate opcode EFI_IFR_TO_UINT.
788 @param FormSet Formset which contains this opcode.
789 @param Result Evaluation result for this opcode.
791 @retval EFI_SUCCESS Opcode evaluation success.
792 @retval Other Opcode evaluation failed.
797 IN FORM_BROWSER_FORMSET
*FormSet
,
798 OUT EFI_HII_VALUE
*Result
806 Status
= PopExpression (&Value
);
807 if (EFI_ERROR (Status
)) {
811 if (Value
.Type
>= EFI_IFR_TYPE_OTHER
&& Value
.Type
!= EFI_IFR_TYPE_BUFFER
) {
812 return EFI_UNSUPPORTED
;
815 Status
= EFI_SUCCESS
;
816 if (Value
.Type
== EFI_IFR_TYPE_STRING
) {
817 String
= GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
818 if (String
== NULL
) {
819 return EFI_NOT_FOUND
;
822 IfrStrToUpper (String
);
823 StringPtr
= StrStr (String
, L
"0X");
824 if (StringPtr
!= NULL
) {
828 Result
->Value
.u64
= StrHexToUint64 (String
);
833 Result
->Value
.u64
= StrDecimalToUint64 (String
);
836 } else if (Value
.Type
== EFI_IFR_TYPE_BUFFER
) {
837 if (Value
.BufferLen
> 8) {
838 FreePool (Value
.Buffer
);
839 return EFI_UNSUPPORTED
;
841 Result
->Value
.u64
= *(UINT64
*) Value
.Buffer
;
842 FreePool (Value
.Buffer
);
844 CopyMem (Result
, &Value
, sizeof (EFI_HII_VALUE
));
847 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
853 Evaluate opcode EFI_IFR_CATENATE.
855 @param FormSet Formset which contains this opcode.
856 @param Result Evaluation result for this opcode.
858 @retval EFI_SUCCESS Opcode evaluation success.
859 @retval Other Opcode evaluation failed.
864 IN FORM_BROWSER_FORMSET
*FormSet
,
865 OUT EFI_HII_VALUE
*Result
869 EFI_HII_VALUE Value
[2];
876 // String[0] - The second string
877 // String[1] - The first string
882 Status
= EFI_SUCCESS
;
883 ZeroMem (Value
, sizeof (Value
));
885 for (Index
= 0; Index
< 2; Index
++) {
886 Status
= PopExpression (&Value
[Index
]);
887 if (EFI_ERROR (Status
)) {
891 if (Value
[Index
].Type
!= EFI_IFR_TYPE_STRING
&& Value
[Index
].Type
!= EFI_IFR_TYPE_BUFFER
) {
892 Status
= EFI_UNSUPPORTED
;
896 if (Value
[Index
].Type
== EFI_IFR_TYPE_STRING
) {
897 String
[Index
] = GetToken (Value
[Index
].Value
.string
, FormSet
->HiiHandle
);
898 if (String
[Index
] == NULL
) {
899 Status
= EFI_NOT_FOUND
;
905 if (Value
[0].Type
== EFI_IFR_TYPE_STRING
) {
906 Size
= StrSize (String
[0]);
907 StringPtr
= AllocatePool (StrSize (String
[1]) + Size
);
908 ASSERT (StringPtr
!= NULL
);
909 StrCpy (StringPtr
, String
[1]);
910 StrCat (StringPtr
, String
[0]);
912 Result
->Type
= EFI_IFR_TYPE_STRING
;
913 Result
->Value
.string
= NewString (StringPtr
, FormSet
->HiiHandle
);
915 Result
->Type
= EFI_IFR_TYPE_BUFFER
;
916 Result
->BufferLen
= (UINT16
) (Value
[0].BufferLen
+ Value
[1].BufferLen
);
918 Result
->Buffer
= AllocateZeroPool (Result
->BufferLen
);
919 ASSERT (Result
->Buffer
!= NULL
);
921 CopyMem (Result
->Buffer
, Value
[0].Buffer
, Value
[0].BufferLen
);
922 CopyMem (&Result
->Buffer
[Value
[0].BufferLen
], Value
[1].Buffer
, Value
[1].BufferLen
);
925 if (Value
[0].Buffer
!= NULL
) {
926 FreePool (Value
[0].Buffer
);
928 if (Value
[1].Buffer
!= NULL
) {
929 FreePool (Value
[1].Buffer
);
931 if (String
[0] != NULL
) {
932 FreePool (String
[0]);
934 if (String
[1] != NULL
) {
935 FreePool (String
[1]);
937 if (StringPtr
!= NULL
) {
938 FreePool (StringPtr
);
946 Evaluate opcode EFI_IFR_MATCH.
948 @param FormSet Formset which contains this opcode.
949 @param Result Evaluation result for this opcode.
951 @retval EFI_SUCCESS Opcode evaluation success.
952 @retval Other Opcode evaluation failed.
957 IN FORM_BROWSER_FORMSET
*FormSet
,
958 OUT EFI_HII_VALUE
*Result
967 // String[0] - The string to search
968 // String[1] - pattern
972 Status
= EFI_SUCCESS
;
973 for (Index
= 0; Index
< 2; Index
++) {
974 Status
= PopExpression (&Value
);
975 if (EFI_ERROR (Status
)) {
979 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
980 Status
= EFI_UNSUPPORTED
;
984 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
985 if (String
[Index
] == NULL
) {
986 Status
= EFI_NOT_FOUND
;
991 Result
->Type
= EFI_IFR_TYPE_BOOLEAN
;
992 Result
->Value
.b
= mUnicodeCollation
->MetaiMatch (mUnicodeCollation
, String
[0], String
[1]);
995 if (String
[0] != NULL
) {
996 FreePool (String
[0]);
998 if (String
[1] != NULL
) {
999 FreePool (String
[1]);
1007 Evaluate opcode EFI_IFR_FIND.
1009 @param FormSet Formset which contains this opcode.
1010 @param Format Case sensitive or insensitive.
1011 @param Result Evaluation result for this opcode.
1013 @retval EFI_SUCCESS Opcode evaluation success.
1014 @retval Other Opcode evaluation failed.
1019 IN FORM_BROWSER_FORMSET
*FormSet
,
1021 OUT EFI_HII_VALUE
*Result
1025 EFI_HII_VALUE Value
;
1031 if (Format
> EFI_IFR_FF_CASE_INSENSITIVE
) {
1032 return EFI_UNSUPPORTED
;
1035 Status
= PopExpression (&Value
);
1036 if (EFI_ERROR (Status
)) {
1039 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1040 return EFI_UNSUPPORTED
;
1042 Base
= (UINTN
) Value
.Value
.u64
;
1045 // String[0] - sub-string
1046 // String[1] - The string to search
1050 for (Index
= 0; Index
< 2; Index
++) {
1051 Status
= PopExpression (&Value
);
1052 if (EFI_ERROR (Status
)) {
1056 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
1057 Status
= EFI_UNSUPPORTED
;
1061 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
1062 if (String
[Index
] == NULL
) {
1063 Status
= EFI_NOT_FOUND
;
1067 if (Format
== EFI_IFR_FF_CASE_INSENSITIVE
) {
1069 // Case insensitive, convert both string to upper case
1071 IfrStrToUpper (String
[Index
]);
1075 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1076 if (Base
>= StrLen (String
[1])) {
1077 Result
->Value
.u64
= 0xFFFFFFFFFFFFFFFFULL
;
1079 StringPtr
= StrStr (String
[1] + Base
, String
[0]);
1080 Result
->Value
.u64
= (StringPtr
== NULL
) ? 0xFFFFFFFFFFFFFFFFULL
: (StringPtr
- String
[1]);
1084 if (String
[0] != NULL
) {
1085 FreePool (String
[0]);
1087 if (String
[1] != NULL
) {
1088 FreePool (String
[1]);
1096 Evaluate opcode EFI_IFR_MID.
1098 @param FormSet Formset which contains this opcode.
1099 @param Result Evaluation result for this opcode.
1101 @retval EFI_SUCCESS Opcode evaluation success.
1102 @retval Other Opcode evaluation failed.
1107 IN FORM_BROWSER_FORMSET
*FormSet
,
1108 OUT EFI_HII_VALUE
*Result
1112 EFI_HII_VALUE Value
;
1120 Status
= PopExpression (&Value
);
1121 if (EFI_ERROR (Status
)) {
1124 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1125 return EFI_UNSUPPORTED
;
1127 Length
= (UINTN
) Value
.Value
.u64
;
1129 Status
= PopExpression (&Value
);
1130 if (EFI_ERROR (Status
)) {
1133 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1134 return EFI_UNSUPPORTED
;
1136 Base
= (UINTN
) Value
.Value
.u64
;
1138 Status
= PopExpression (&Value
);
1139 if (EFI_ERROR (Status
)) {
1142 if (Value
.Type
!= EFI_IFR_TYPE_STRING
&& Value
.Type
!= EFI_IFR_TYPE_BUFFER
) {
1143 return EFI_UNSUPPORTED
;
1145 if (Value
.Type
== EFI_IFR_TYPE_STRING
) {
1146 String
= GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
1147 if (String
== NULL
) {
1148 return EFI_NOT_FOUND
;
1151 if (Length
== 0 || Base
>= StrLen (String
)) {
1152 SubString
= gEmptyString
;
1154 SubString
= String
+ Base
;
1155 if ((Base
+ Length
) < StrLen (String
)) {
1156 SubString
[Length
] = L
'\0';
1160 Result
->Type
= EFI_IFR_TYPE_STRING
;
1161 Result
->Value
.string
= NewString (SubString
, FormSet
->HiiHandle
);
1165 Buffer
= Value
.Buffer
;
1166 BufferLen
= Value
.BufferLen
;
1168 Result
->Type
= EFI_IFR_TYPE_BUFFER
;
1169 if (Length
== 0 || Base
>= BufferLen
) {
1170 Result
->BufferLen
= 0;
1171 Result
->Buffer
= NULL
;
1173 Result
->BufferLen
= (UINT16
)((BufferLen
- Base
) < Length
? (BufferLen
- Base
) : Length
);
1174 Result
->Buffer
= AllocateZeroPool (Result
->BufferLen
);
1175 ASSERT (Result
->Buffer
!= NULL
);
1176 CopyMem (Result
->Buffer
, &Value
.Buffer
[Base
], Result
->BufferLen
);
1179 FreePool (Value
.Buffer
);
1187 Evaluate opcode EFI_IFR_TOKEN.
1189 @param FormSet Formset which contains this opcode.
1190 @param Result Evaluation result for this opcode.
1192 @retval EFI_SUCCESS Opcode evaluation success.
1193 @retval Other Opcode evaluation failed.
1198 IN FORM_BROWSER_FORMSET
*FormSet
,
1199 OUT EFI_HII_VALUE
*Result
1203 EFI_HII_VALUE Value
;
1211 Status
= PopExpression (&Value
);
1212 if (EFI_ERROR (Status
)) {
1215 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1216 return EFI_UNSUPPORTED
;
1218 Count
= (UINTN
) Value
.Value
.u64
;
1221 // String[0] - Delimiter
1222 // String[1] - The string to search
1226 for (Index
= 0; Index
< 2; Index
++) {
1227 Status
= PopExpression (&Value
);
1228 if (EFI_ERROR (Status
)) {
1232 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
1233 Status
= EFI_UNSUPPORTED
;
1237 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
1238 if (String
[Index
] == NULL
) {
1239 Status
= EFI_NOT_FOUND
;
1244 Delimiter
= String
[0];
1245 SubString
= String
[1];
1247 SubString
= StrStr (SubString
, Delimiter
);
1248 if (SubString
!= NULL
) {
1250 // Skip over the delimiter
1252 SubString
= SubString
+ StrLen (Delimiter
);
1259 if (SubString
== NULL
) {
1261 // nth delimited sub-string not found, push an empty string
1263 SubString
= gEmptyString
;
1266 // Put a NULL terminator for nth delimited sub-string
1268 StringPtr
= StrStr (SubString
, Delimiter
);
1269 if (StringPtr
!= NULL
) {
1274 Result
->Type
= EFI_IFR_TYPE_STRING
;
1275 Result
->Value
.string
= NewString (SubString
, FormSet
->HiiHandle
);
1278 if (String
[0] != NULL
) {
1279 FreePool (String
[0]);
1281 if (String
[1] != NULL
) {
1282 FreePool (String
[1]);
1290 Evaluate opcode EFI_IFR_SPAN.
1292 @param FormSet Formset which contains this opcode.
1293 @param Flags FIRST_MATCHING or FIRST_NON_MATCHING.
1294 @param Result Evaluation result for this opcode.
1296 @retval EFI_SUCCESS Opcode evaluation success.
1297 @retval Other Opcode evaluation failed.
1302 IN FORM_BROWSER_FORMSET
*FormSet
,
1304 OUT EFI_HII_VALUE
*Result
1308 EFI_HII_VALUE Value
;
1316 Status
= PopExpression (&Value
);
1317 if (EFI_ERROR (Status
)) {
1320 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1321 return EFI_UNSUPPORTED
;
1323 Base
= (UINTN
) Value
.Value
.u64
;
1326 // String[0] - Charset
1327 // String[1] - The string to search
1331 for (Index
= 0; Index
< 2; Index
++) {
1332 Status
= PopExpression (&Value
);
1333 if (EFI_ERROR (Status
)) {
1337 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
1338 Status
= EFI_UNSUPPORTED
;
1342 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
1343 if (String
[Index
] == NULL
) {
1344 Status
= EFI_NOT_FOUND
;
1349 if (Base
>= StrLen (String
[1])) {
1350 Status
= EFI_UNSUPPORTED
;
1355 StringPtr
= String
[1] + Base
;
1356 Charset
= String
[0];
1357 while (*StringPtr
!= 0 && !Found
) {
1359 while (Charset
[Index
] != 0) {
1360 if (*StringPtr
>= Charset
[Index
] && *StringPtr
<= Charset
[Index
+ 1]) {
1361 if (Flags
== EFI_IFR_FLAGS_FIRST_MATCHING
) {
1366 if (Flags
== EFI_IFR_FLAGS_FIRST_NON_MATCHING
) {
1372 // Skip characters pair representing low-end of a range and high-end of a range
1382 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1383 Result
->Value
.u64
= StringPtr
- String
[1];
1386 if (String
[0] != NULL
) {
1387 FreePool (String
[0]);
1389 if (String
[1] != NULL
) {
1390 FreePool (String
[1]);
1398 Zero extend integer/boolean/date/time to UINT64 for comparing.
1400 @param Value HII Value to be converted.
1405 IN EFI_HII_VALUE
*Value
1411 switch (Value
->Type
) {
1412 case EFI_IFR_TYPE_NUM_SIZE_8
:
1413 Temp
= Value
->Value
.u8
;
1416 case EFI_IFR_TYPE_NUM_SIZE_16
:
1417 Temp
= Value
->Value
.u16
;
1420 case EFI_IFR_TYPE_NUM_SIZE_32
:
1421 Temp
= Value
->Value
.u32
;
1424 case EFI_IFR_TYPE_BOOLEAN
:
1425 Temp
= Value
->Value
.b
;
1428 case EFI_IFR_TYPE_TIME
:
1429 Temp
= Value
->Value
.u32
& 0xffffff;
1432 case EFI_IFR_TYPE_DATE
:
1433 Temp
= Value
->Value
.u32
;
1440 Value
->Value
.u64
= Temp
;
1445 Compare two Hii value.
1447 @param Value1 Expression value to compare on left-hand.
1448 @param Value2 Expression value to compare on right-hand.
1449 @param HiiHandle Only required for string compare.
1451 @retval EFI_INVALID_PARAMETER Could not perform compare on two values.
1452 @retval 0 Two operators equal.
1453 @return Positive value if Value1 is greater than Value2.
1454 @retval Negative value if Value1 is less than Value2.
1459 IN EFI_HII_VALUE
*Value1
,
1460 IN EFI_HII_VALUE
*Value2
,
1461 IN EFI_HII_HANDLE HiiHandle OPTIONAL
1470 if (Value1
->Type
>= EFI_IFR_TYPE_OTHER
|| Value2
->Type
>= EFI_IFR_TYPE_OTHER
) {
1471 if (Value1
->Type
!= EFI_IFR_TYPE_BUFFER
&& Value2
->Type
!= EFI_IFR_TYPE_BUFFER
) {
1472 return EFI_INVALID_PARAMETER
;
1476 if (Value1
->Type
== EFI_IFR_TYPE_STRING
|| Value2
->Type
== EFI_IFR_TYPE_STRING
) {
1477 if (Value1
->Type
!= Value2
->Type
) {
1479 // Both Operator should be type of String
1481 return EFI_INVALID_PARAMETER
;
1484 if (Value1
->Value
.string
== 0 || Value2
->Value
.string
== 0) {
1486 // StringId 0 is reserved
1488 return EFI_INVALID_PARAMETER
;
1491 if (Value1
->Value
.string
== Value2
->Value
.string
) {
1495 Str1
= GetToken (Value1
->Value
.string
, HiiHandle
);
1500 return EFI_INVALID_PARAMETER
;
1503 Str2
= GetToken (Value2
->Value
.string
, HiiHandle
);
1506 return EFI_INVALID_PARAMETER
;
1509 Result
= StrCmp (Str1
, Str2
);
1517 if (Value1
->Type
== EFI_IFR_TYPE_BUFFER
|| Value2
->Type
== EFI_IFR_TYPE_BUFFER
) {
1518 if (Value1
->Type
!= Value2
->Type
) {
1520 // Both Operator should be type of Buffer.
1522 return EFI_INVALID_PARAMETER
;
1524 Len
= Value1
->BufferLen
> Value2
->BufferLen
? Value2
->BufferLen
: Value1
->BufferLen
;
1525 Result
= CompareMem (Value1
->Buffer
, Value2
->Buffer
, Len
);
1526 if ((Result
== 0) && (Value1
->BufferLen
!= Value2
->BufferLen
))
1529 // In this case, means base on samll number buffer, the data is same
1530 // So which value has more data, which value is bigger.
1532 Result
= Value1
->BufferLen
> Value2
->BufferLen
? 1 : -1;
1538 // Take remain types(integer, boolean, date/time) as integer
1540 Temp64
= (INT64
) (Value1
->Value
.u64
- Value2
->Value
.u64
);
1543 } else if (Temp64
< 0) {
1553 Check if current user has the privilege specified by the permissions GUID.
1555 @param[in] Guid A GUID specifying setup access permissions.
1557 @retval TRUE Current user has the privilege.
1558 @retval FALSE Current user does not have the privilege.
1561 CheckUserPrivilege (
1566 EFI_USER_PROFILE_HANDLE UserProfileHandle
;
1567 EFI_USER_INFO_HANDLE UserInfoHandle
;
1568 EFI_USER_INFO
*UserInfo
;
1569 EFI_GUID
*UserPermissionsGuid
;
1571 UINTN AccessControlDataSize
;
1572 EFI_USER_INFO_ACCESS_CONTROL
*AccessControl
;
1575 if (mUserManager
== NULL
) {
1576 Status
= gBS
->LocateProtocol (
1577 &gEfiUserManagerProtocolGuid
,
1579 (VOID
**) &mUserManager
1581 if (EFI_ERROR (Status
)) {
1583 /// If the system does not support user management, then it is assumed that
1584 /// all users have admin privilege and evaluation of each EFI_IFR_SECURITY
1585 /// op-code is always TRUE.
1591 Status
= mUserManager
->Current (mUserManager
, &UserProfileHandle
);
1592 ASSERT_EFI_ERROR (Status
);
1595 /// Enumerate all user information of the current user profile
1596 /// to look for any EFI_USER_INFO_ACCESS_SETUP record.
1599 for (UserInfoHandle
= NULL
;;) {
1600 Status
= mUserManager
->GetNextInfo (mUserManager
, UserProfileHandle
, &UserInfoHandle
);
1601 if (EFI_ERROR (Status
)) {
1606 Status
= mUserManager
->GetInfo (mUserManager
, UserProfileHandle
, UserInfoHandle
, NULL
, &UserInfoSize
);
1607 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1611 UserInfo
= (EFI_USER_INFO
*) AllocatePool (UserInfoSize
);
1612 if (UserInfo
== NULL
) {
1616 Status
= mUserManager
->GetInfo (mUserManager
, UserProfileHandle
, UserInfoHandle
, UserInfo
, &UserInfoSize
);
1617 if (EFI_ERROR (Status
) ||
1618 UserInfo
->InfoType
!= EFI_USER_INFO_ACCESS_POLICY_RECORD
||
1619 UserInfo
->InfoSize
<= sizeof (EFI_USER_INFO
)) {
1620 FreePool (UserInfo
);
1624 RemainSize
= UserInfo
->InfoSize
- sizeof (EFI_USER_INFO
);
1625 AccessControl
= (EFI_USER_INFO_ACCESS_CONTROL
*)(UserInfo
+ 1);
1626 while (RemainSize
>= sizeof (EFI_USER_INFO_ACCESS_CONTROL
)) {
1627 if (RemainSize
< AccessControl
->Size
|| AccessControl
->Size
< sizeof (EFI_USER_INFO_ACCESS_CONTROL
)) {
1630 if (AccessControl
->Type
== EFI_USER_INFO_ACCESS_SETUP
) {
1632 /// Check if current user has the privilege specified by the permissions GUID.
1635 UserPermissionsGuid
= (EFI_GUID
*)(AccessControl
+ 1);
1636 AccessControlDataSize
= AccessControl
->Size
- sizeof (EFI_USER_INFO_ACCESS_CONTROL
);
1637 while (AccessControlDataSize
>= sizeof (EFI_GUID
)) {
1638 if (CompareGuid (Guid
, UserPermissionsGuid
)) {
1639 FreePool (UserInfo
);
1642 UserPermissionsGuid
++;
1643 AccessControlDataSize
-= sizeof (EFI_GUID
);
1646 RemainSize
-= AccessControl
->Size
;
1647 AccessControl
= (EFI_USER_INFO_ACCESS_CONTROL
*)((UINT8
*)AccessControl
+ AccessControl
->Size
);
1650 FreePool (UserInfo
);
1656 Get question value from the predefined formset.
1658 @param DevicePath The driver's device path which produece the formset data.
1659 @param InputHiiHandle The hii handle associate with the formset data.
1660 @param FormSetGuid The formset guid which include the question.
1661 @param QuestionId The question id which need to get value from.
1662 @param Value The return data about question's value.
1664 @retval TRUE Get the question value success.
1665 @retval FALSE Get the question value failed.
1668 GetQuestionValueFromForm (
1669 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
1670 IN EFI_HII_HANDLE InputHiiHandle
,
1671 IN EFI_GUID
*FormSetGuid
,
1672 IN EFI_QUESTION_ID QuestionId
,
1673 OUT EFI_HII_VALUE
*Value
1677 EFI_HANDLE DriverHandle
;
1679 EFI_HII_HANDLE
*HiiHandles
;
1680 EFI_HII_HANDLE HiiHandle
;
1682 FORM_BROWSER_STATEMENT
*Question
;
1683 FORM_BROWSER_FORMSET
*FormSet
;
1684 FORM_BROWSER_FORM
*Form
;
1689 // The input parameter DevicePath or InputHiiHandle must have one valid input.
1691 ASSERT ((DevicePath
!= NULL
&& InputHiiHandle
== NULL
) ||
1692 (DevicePath
== NULL
&& InputHiiHandle
!= NULL
) );
1695 DriverHandle
= NULL
;
1703 if (DevicePath
!= NULL
) {
1705 // 1. Get Driver handle.
1707 Status
= gBS
->LocateDevicePath (
1708 &gEfiDevicePathProtocolGuid
,
1712 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
1717 // 2. Get Hii handle
1719 HiiHandles
= HiiGetHiiHandles (NULL
);
1720 if (HiiHandles
== NULL
) {
1724 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
1725 Status
= mHiiDatabase
->GetPackageListHandle (
1730 if (!EFI_ERROR (Status
) && (Handle
== DriverHandle
)) {
1731 HiiHandle
= HiiHandles
[Index
];
1735 FreePool (HiiHandles
);
1737 HiiHandle
= InputHiiHandle
;
1739 ASSERT (HiiHandle
!= NULL
);
1742 // Get the formset data include this question.
1744 FormSet
= AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET
));
1745 ASSERT (FormSet
!= NULL
);
1746 Status
= InitializeFormSet(HiiHandle
, FormSetGuid
, FormSet
, FALSE
);
1747 if (EFI_ERROR (Status
)) {
1753 // Base on the Question Id to get the question info.
1755 Question
= IdToQuestion(FormSet
, NULL
, QuestionId
);
1756 if (Question
== NULL
) {
1762 // Search form in the formset scope
1764 Link
= GetFirstNode (&FormSet
->FormListHead
);
1765 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
1766 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
1768 Question
= IdToQuestion2 (Form
, QuestionId
);
1769 if (Question
!= NULL
) {
1773 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
1776 ASSERT (Form
!= NULL
);
1779 // Get the question value.
1781 Status
= GetQuestionValue(FormSet
, Form
, Question
, FALSE
);
1782 if (EFI_ERROR (Status
)) {
1787 CopyMem (Value
, &Question
->HiiValue
, sizeof (EFI_HII_VALUE
));
1791 // Clean the formset structure and restore the global parameter.
1793 if (FormSet
!= NULL
) {
1794 DestroyFormSet (FormSet
);
1801 Evaluate the result of a HII expression.
1803 If Expression is NULL, then ASSERT.
1805 @param FormSet FormSet associated with this expression.
1806 @param Form Form associated with this expression.
1807 @param Expression Expression to be evaluated.
1809 @retval EFI_SUCCESS The expression evaluated successfuly
1810 @retval EFI_NOT_FOUND The Question which referenced by a QuestionId
1812 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
1814 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
1815 @retval EFI_INVALID_PARAMETER Syntax error with the Expression
1819 EvaluateExpression (
1820 IN FORM_BROWSER_FORMSET
*FormSet
,
1821 IN FORM_BROWSER_FORM
*Form
,
1822 IN OUT FORM_EXPRESSION
*Expression
1827 EXPRESSION_OPCODE
*OpCode
;
1828 FORM_BROWSER_STATEMENT
*Question
;
1829 FORM_BROWSER_STATEMENT
*Question2
;
1831 EFI_HII_VALUE Data1
;
1832 EFI_HII_VALUE Data2
;
1833 EFI_HII_VALUE Data3
;
1834 FORM_EXPRESSION
*RuleExpression
;
1835 EFI_HII_VALUE
*Value
;
1840 LIST_ENTRY
*SubExpressionLink
;
1841 FORM_EXPRESSION
*SubExpression
;
1848 EFI_HII_VALUE QuestionVal
;
1851 // Save current stack offset.
1853 StackOffset
= SaveExpressionEvaluationStackOffset ();
1855 ASSERT (Expression
!= NULL
);
1856 Expression
->Result
.Type
= EFI_IFR_TYPE_OTHER
;
1858 Link
= GetFirstNode (&Expression
->OpCodeListHead
);
1859 while (!IsNull (&Expression
->OpCodeListHead
, Link
)) {
1860 OpCode
= EXPRESSION_OPCODE_FROM_LINK (Link
);
1862 Link
= GetNextNode (&Expression
->OpCodeListHead
, Link
);
1864 ZeroMem (&Data1
, sizeof (EFI_HII_VALUE
));
1865 ZeroMem (&Data2
, sizeof (EFI_HII_VALUE
));
1866 ZeroMem (&Data3
, sizeof (EFI_HII_VALUE
));
1869 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
1870 Status
= EFI_SUCCESS
;
1872 switch (OpCode
->Operand
) {
1874 // Built-in functions
1876 case EFI_IFR_EQ_ID_VAL_OP
:
1877 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
1878 if (Question
== NULL
) {
1879 Status
= EFI_NOT_FOUND
;
1883 Result
= CompareHiiValue (&Question
->HiiValue
, &OpCode
->Value
, NULL
);
1884 if (Result
== EFI_INVALID_PARAMETER
) {
1885 Status
= EFI_INVALID_PARAMETER
;
1888 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
1891 case EFI_IFR_EQ_ID_ID_OP
:
1892 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
1893 if (Question
== NULL
) {
1894 Status
= EFI_NOT_FOUND
;
1898 Question2
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId2
);
1899 if (Question2
== NULL
) {
1900 Status
= EFI_NOT_FOUND
;
1904 Result
= CompareHiiValue (&Question
->HiiValue
, &Question2
->HiiValue
, FormSet
->HiiHandle
);
1905 if (Result
== EFI_INVALID_PARAMETER
) {
1906 Status
= EFI_INVALID_PARAMETER
;
1909 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
1912 case EFI_IFR_EQ_ID_VAL_LIST_OP
:
1913 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
1914 if (Question
== NULL
) {
1915 Status
= EFI_NOT_FOUND
;
1919 Value
->Value
.b
= FALSE
;
1920 for (Index
=0; Index
< OpCode
->ListLength
; Index
++) {
1921 if (Question
->HiiValue
.Value
.u16
== OpCode
->ValueList
[Index
]) {
1922 Value
->Value
.b
= TRUE
;
1928 case EFI_IFR_DUP_OP
:
1929 Status
= PopExpression (Value
);
1930 if (EFI_ERROR (Status
)) {
1934 Status
= PushExpression (Value
);
1937 case EFI_IFR_QUESTION_REF1_OP
:
1938 case EFI_IFR_THIS_OP
:
1939 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
1940 if (Question
== NULL
) {
1941 Status
= EFI_NOT_FOUND
;
1945 Value
= &Question
->HiiValue
;
1948 case EFI_IFR_SECURITY_OP
:
1949 Value
->Value
.b
= CheckUserPrivilege (&OpCode
->Guid
);
1952 case EFI_IFR_GET_OP
:
1954 // Get Value from VarStore buffer, EFI VarStore, Name/Value VarStore.
1956 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
1957 Value
->Value
.u8
= 0;
1958 if (OpCode
->VarStorage
!= NULL
) {
1959 switch (OpCode
->VarStorage
->Type
) {
1960 case EFI_HII_VARSTORE_BUFFER
:
1961 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
1963 // Get value from Edit Buffer
1965 Value
->Type
= OpCode
->ValueType
;
1966 CopyMem (&Value
->Value
, OpCode
->VarStorage
->EditBuffer
+ OpCode
->VarStoreInfo
.VarOffset
, OpCode
->ValueWidth
);
1968 case EFI_HII_VARSTORE_NAME_VALUE
:
1969 if (OpCode
->ValueType
!= EFI_IFR_TYPE_STRING
) {
1971 // Get value from string except for STRING value.
1973 Status
= GetValueByName (OpCode
->VarStorage
, OpCode
->ValueName
, &StrPtr
);
1974 if (!EFI_ERROR (Status
)) {
1975 ASSERT (StrPtr
!= NULL
);
1976 TempLength
= StrLen (StrPtr
);
1977 if (OpCode
->ValueWidth
>= ((TempLength
+ 1) / 2)) {
1978 Value
->Type
= OpCode
->ValueType
;
1979 TempBuffer
= (UINT8
*) &Value
->Value
;
1980 ZeroMem (TempStr
, sizeof (TempStr
));
1981 for (Index
= 0; Index
< TempLength
; Index
++) {
1982 TempStr
[0] = StrPtr
[TempLength
- Index
- 1];
1983 DigitUint8
= (UINT8
) StrHexToUint64 (TempStr
);
1984 if ((Index
& 1) == 0) {
1985 TempBuffer
[Index
/2] = DigitUint8
;
1987 TempBuffer
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + TempBuffer
[Index
/2]);
1994 case EFI_HII_VARSTORE_EFI_VARIABLE
:
1996 // Get value from variable.
1998 TempLength
= OpCode
->ValueWidth
;
1999 Value
->Type
= OpCode
->ValueType
;
2000 Status
= gRT
->GetVariable (
2002 &OpCode
->VarStorage
->Guid
,
2007 if (EFI_ERROR (Status
)) {
2008 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2009 Value
->Value
.u8
= 0;
2014 // Not recognize storage.
2016 Status
= EFI_UNSUPPORTED
;
2021 // For Time/Date Data
2023 if (OpCode
->ValueType
!= EFI_IFR_TYPE_DATE
&& OpCode
->ValueType
!= EFI_IFR_TYPE_TIME
) {
2025 // Only support Data/Time data when storage doesn't exist.
2027 Status
= EFI_UNSUPPORTED
;
2030 Status
= gRT
->GetTime (&EfiTime
, NULL
);
2031 if (!EFI_ERROR (Status
)) {
2032 if (OpCode
->ValueType
== EFI_IFR_TYPE_DATE
) {
2033 switch (OpCode
->VarStoreInfo
.VarOffset
) {
2035 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_16
;
2036 Value
->Value
.u16
= EfiTime
.Year
;
2039 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
2040 Value
->Value
.u8
= EfiTime
.Month
;
2043 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
2044 Value
->Value
.u8
= EfiTime
.Day
;
2048 // Invalid Date field.
2050 Status
= EFI_INVALID_PARAMETER
;
2054 switch (OpCode
->VarStoreInfo
.VarOffset
) {
2056 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
2057 Value
->Value
.u8
= EfiTime
.Hour
;
2060 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
2061 Value
->Value
.u8
= EfiTime
.Minute
;
2064 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
2065 Value
->Value
.u8
= EfiTime
.Second
;
2069 // Invalid Time field.
2071 Status
= EFI_INVALID_PARAMETER
;
2080 case EFI_IFR_QUESTION_REF3_OP
:
2082 // EFI_IFR_QUESTION_REF3
2083 // Pop an expression from the expression stack
2085 Status
= PopExpression (Value
);
2086 if (EFI_ERROR (Status
)) {
2091 // Validate the expression value
2093 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
2094 Status
= EFI_NOT_FOUND
;
2098 if (OpCode
->DevicePath
!= 0) {
2099 StrPtr
= GetToken (OpCode
->DevicePath
, FormSet
->HiiHandle
);
2100 if (StrPtr
== NULL
) {
2101 Status
= EFI_NOT_FOUND
;
2105 if (!GetQuestionValueFromForm((EFI_DEVICE_PATH_PROTOCOL
*)StrPtr
, NULL
, &OpCode
->Guid
, Value
->Value
.u16
, &QuestionVal
)){
2106 Status
= EFI_NOT_FOUND
;
2109 Value
= &QuestionVal
;
2110 } else if (CompareGuid (&OpCode
->Guid
, &gZeroGuid
) != 0) {
2111 if (!GetQuestionValueFromForm(NULL
, FormSet
->HiiHandle
, &OpCode
->Guid
, Value
->Value
.u16
, &QuestionVal
)){
2112 Status
= EFI_NOT_FOUND
;
2115 Value
= &QuestionVal
;
2117 Question
= IdToQuestion (FormSet
, Form
, Value
->Value
.u16
);
2118 if (Question
== NULL
) {
2119 Status
= EFI_NOT_FOUND
;
2124 // push the questions' value on to the expression stack
2126 Value
= &Question
->HiiValue
;
2130 case EFI_IFR_RULE_REF_OP
:
2132 // Find expression for this rule
2134 RuleExpression
= RuleIdToExpression (Form
, OpCode
->RuleId
);
2135 if (RuleExpression
== NULL
) {
2136 Status
= EFI_NOT_FOUND
;
2141 // Evaluate this rule expression
2143 Status
= EvaluateExpression (FormSet
, Form
, RuleExpression
);
2144 if (EFI_ERROR (Status
)) {
2148 Value
= &RuleExpression
->Result
;
2151 case EFI_IFR_STRING_REF1_OP
:
2152 Value
->Type
= EFI_IFR_TYPE_STRING
;
2153 Value
->Value
.string
= OpCode
->Value
.Value
.string
;
2159 case EFI_IFR_TRUE_OP
:
2160 case EFI_IFR_FALSE_OP
:
2161 case EFI_IFR_ONE_OP
:
2162 case EFI_IFR_ONES_OP
:
2163 case EFI_IFR_UINT8_OP
:
2164 case EFI_IFR_UINT16_OP
:
2165 case EFI_IFR_UINT32_OP
:
2166 case EFI_IFR_UINT64_OP
:
2167 case EFI_IFR_UNDEFINED_OP
:
2168 case EFI_IFR_VERSION_OP
:
2169 case EFI_IFR_ZERO_OP
:
2170 Value
= &OpCode
->Value
;
2176 case EFI_IFR_LENGTH_OP
:
2177 Status
= PopExpression (Value
);
2178 if (EFI_ERROR (Status
)) {
2181 if (Value
->Type
!= EFI_IFR_TYPE_STRING
&& Value
->Type
!= EFI_IFR_TYPE_BUFFER
) {
2182 Status
= EFI_INVALID_PARAMETER
;
2186 if (Value
->Type
== EFI_IFR_TYPE_STRING
) {
2187 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->HiiHandle
);
2188 if (StrPtr
== NULL
) {
2189 Status
= EFI_INVALID_PARAMETER
;
2193 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
2194 Value
->Value
.u64
= StrLen (StrPtr
);
2197 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
2198 Value
->Value
.u64
= Value
->BufferLen
;
2199 FreePool (Value
->Buffer
);
2203 case EFI_IFR_NOT_OP
:
2204 Status
= PopExpression (Value
);
2205 if (EFI_ERROR (Status
)) {
2208 if (Value
->Type
!= EFI_IFR_TYPE_BOOLEAN
) {
2209 Status
= EFI_INVALID_PARAMETER
;
2212 Value
->Value
.b
= (BOOLEAN
) (!Value
->Value
.b
);
2215 case EFI_IFR_QUESTION_REF2_OP
:
2217 // Pop an expression from the expression stack
2219 Status
= PopExpression (Value
);
2220 if (EFI_ERROR (Status
)) {
2225 // Validate the expression value
2227 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
2228 Status
= EFI_NOT_FOUND
;
2232 Question
= IdToQuestion (FormSet
, Form
, Value
->Value
.u16
);
2233 if (Question
== NULL
) {
2234 Status
= EFI_NOT_FOUND
;
2238 Value
= &Question
->HiiValue
;
2241 case EFI_IFR_STRING_REF2_OP
:
2243 // Pop an expression from the expression stack
2245 Status
= PopExpression (Value
);
2246 if (EFI_ERROR (Status
)) {
2251 // Validate the expression value
2253 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
2254 Status
= EFI_NOT_FOUND
;
2258 Value
->Type
= EFI_IFR_TYPE_STRING
;
2259 StrPtr
= GetToken (Value
->Value
.u16
, FormSet
->HiiHandle
);
2260 if (StrPtr
== NULL
) {
2262 // If String not exit, push an empty string
2264 Value
->Value
.string
= NewString (gEmptyString
, FormSet
->HiiHandle
);
2266 Index
= (UINT16
) Value
->Value
.u64
;
2267 Value
->Value
.string
= Index
;
2272 case EFI_IFR_TO_BOOLEAN_OP
:
2274 // Pop an expression from the expression stack
2276 Status
= PopExpression (Value
);
2277 if (EFI_ERROR (Status
)) {
2282 // Convert an expression to a Boolean
2284 if (Value
->Type
<= EFI_IFR_TYPE_DATE
) {
2286 // When converting from an unsigned integer, zero will be converted to
2287 // FALSE and any other value will be converted to TRUE.
2289 Value
->Value
.b
= (BOOLEAN
) (Value
->Value
.u64
!= 0);
2291 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
2292 } else if (Value
->Type
== EFI_IFR_TYPE_STRING
) {
2294 // When converting from a string, if case-insensitive compare
2295 // with "true" is True, then push True. If a case-insensitive compare
2296 // with "false" is True, then push False. Otherwise, push Undefined.
2298 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->HiiHandle
);
2299 if (StrPtr
== NULL
) {
2300 Status
= EFI_INVALID_PARAMETER
;
2304 IfrStrToUpper (StrPtr
);
2305 if (StrCmp (StrPtr
, L
"TRUE") == 0){
2306 Value
->Value
.b
= TRUE
;
2307 } else if (StrCmp (StrPtr
, L
"FALSE") == 0) {
2308 Value
->Value
.b
= FALSE
;
2310 Status
= EFI_INVALID_PARAMETER
;
2315 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
2316 } else if (Value
->Type
== EFI_IFR_TYPE_BUFFER
) {
2318 // When converting from a buffer, if the buffer is all zeroes,
2319 // then push False. Otherwise push True.
2321 for (Index
=0; Index
< Value
->BufferLen
; Index
++) {
2322 if (Value
->Buffer
[Index
] != 0) {
2327 if (Index
>= Value
->BufferLen
) {
2328 Value
->Value
.b
= FALSE
;
2330 Value
->Value
.b
= TRUE
;
2332 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
2333 FreePool (Value
->Buffer
);
2337 case EFI_IFR_TO_STRING_OP
:
2338 Status
= IfrToString (FormSet
, OpCode
->Format
, Value
);
2341 case EFI_IFR_TO_UINT_OP
:
2342 Status
= IfrToUint (FormSet
, Value
);
2345 case EFI_IFR_TO_LOWER_OP
:
2346 case EFI_IFR_TO_UPPER_OP
:
2347 Status
= InitializeUnicodeCollationProtocol ();
2348 if (EFI_ERROR (Status
)) {
2352 Status
= PopExpression (Value
);
2353 if (EFI_ERROR (Status
)) {
2357 if (Value
->Type
!= EFI_IFR_TYPE_STRING
) {
2358 Status
= EFI_UNSUPPORTED
;
2362 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->HiiHandle
);
2363 if (StrPtr
== NULL
) {
2364 Status
= EFI_NOT_FOUND
;
2368 if (OpCode
->Operand
== EFI_IFR_TO_LOWER_OP
) {
2369 mUnicodeCollation
->StrLwr (mUnicodeCollation
, StrPtr
);
2371 mUnicodeCollation
->StrUpr (mUnicodeCollation
, StrPtr
);
2373 Value
->Value
.string
= NewString (StrPtr
, FormSet
->HiiHandle
);
2377 case EFI_IFR_BITWISE_NOT_OP
:
2379 // Pop an expression from the expression stack
2381 Status
= PopExpression (Value
);
2382 if (EFI_ERROR (Status
)) {
2385 if (Value
->Type
> EFI_IFR_TYPE_DATE
) {
2386 Status
= EFI_INVALID_PARAMETER
;
2390 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
2391 Value
->Value
.u64
= ~Value
->Value
.u64
;
2394 case EFI_IFR_SET_OP
:
2396 // Pop an expression from the expression stack
2398 Status
= PopExpression (Value
);
2399 if (EFI_ERROR (Status
)) {
2402 Data1
.Type
= EFI_IFR_TYPE_BOOLEAN
;
2403 Data1
.Value
.b
= FALSE
;
2405 // Set value to var storage buffer
2407 if (OpCode
->VarStorage
!= NULL
) {
2408 switch (OpCode
->VarStorage
->Type
) {
2409 case EFI_HII_VARSTORE_BUFFER
:
2410 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
:
2411 CopyMem (OpCode
->VarStorage
->EditBuffer
+ OpCode
->VarStoreInfo
.VarOffset
, &Value
->Value
, OpCode
->ValueWidth
);
2412 Data1
.Value
.b
= TRUE
;
2414 case EFI_HII_VARSTORE_NAME_VALUE
:
2415 if (OpCode
->ValueType
!= EFI_IFR_TYPE_STRING
) {
2416 NameValue
= AllocateZeroPool ((OpCode
->ValueWidth
* 2 + 1) * sizeof (CHAR16
));
2417 ASSERT (Value
!= NULL
);
2419 // Convert Buffer to Hex String
2421 TempBuffer
= (UINT8
*) &Value
->Value
+ OpCode
->ValueWidth
- 1;
2423 for (Index
= 0; Index
< OpCode
->ValueWidth
; Index
++, TempBuffer
--) {
2424 StrPtr
+= UnicodeValueToString (StrPtr
, PREFIX_ZERO
| RADIX_HEX
, *TempBuffer
, 2);
2426 Status
= SetValueByName (OpCode
->VarStorage
, OpCode
->ValueName
, NameValue
, TRUE
);
2427 FreePool (NameValue
);
2428 if (!EFI_ERROR (Status
)) {
2429 Data1
.Value
.b
= TRUE
;
2433 case EFI_HII_VARSTORE_EFI_VARIABLE
:
2434 Status
= gRT
->SetVariable (
2436 &OpCode
->VarStorage
->Guid
,
2437 OpCode
->VarStorage
->Attributes
,
2441 if (!EFI_ERROR (Status
)) {
2442 Data1
.Value
.b
= TRUE
;
2447 // Not recognize storage.
2449 Status
= EFI_UNSUPPORTED
;
2455 // For Time/Date Data
2457 if (OpCode
->ValueType
!= EFI_IFR_TYPE_DATE
&& OpCode
->ValueType
!= EFI_IFR_TYPE_TIME
) {
2459 // Only support Data/Time data when storage doesn't exist.
2461 Status
= EFI_UNSUPPORTED
;
2464 Status
= gRT
->GetTime (&EfiTime
, NULL
);
2465 if (!EFI_ERROR (Status
)) {
2466 if (OpCode
->ValueType
== EFI_IFR_TYPE_DATE
) {
2467 switch (OpCode
->VarStoreInfo
.VarOffset
) {
2469 EfiTime
.Year
= Value
->Value
.u16
;
2472 EfiTime
.Month
= Value
->Value
.u8
;
2475 EfiTime
.Day
= Value
->Value
.u8
;
2479 // Invalid Date field.
2481 Status
= EFI_INVALID_PARAMETER
;
2485 switch (OpCode
->VarStoreInfo
.VarOffset
) {
2487 EfiTime
.Hour
= Value
->Value
.u8
;
2490 EfiTime
.Minute
= Value
->Value
.u8
;
2493 EfiTime
.Second
= Value
->Value
.u8
;
2497 // Invalid Time field.
2499 Status
= EFI_INVALID_PARAMETER
;
2503 Status
= gRT
->SetTime (&EfiTime
);
2504 if (!EFI_ERROR (Status
)) {
2505 Data1
.Value
.b
= TRUE
;
2515 case EFI_IFR_ADD_OP
:
2516 case EFI_IFR_SUBTRACT_OP
:
2517 case EFI_IFR_MULTIPLY_OP
:
2518 case EFI_IFR_DIVIDE_OP
:
2519 case EFI_IFR_MODULO_OP
:
2520 case EFI_IFR_BITWISE_AND_OP
:
2521 case EFI_IFR_BITWISE_OR_OP
:
2522 case EFI_IFR_SHIFT_LEFT_OP
:
2523 case EFI_IFR_SHIFT_RIGHT_OP
:
2525 // Pop an expression from the expression stack
2527 Status
= PopExpression (&Data2
);
2528 if (EFI_ERROR (Status
)) {
2531 if (Data2
.Type
> EFI_IFR_TYPE_DATE
) {
2532 Status
= EFI_INVALID_PARAMETER
;
2537 // Pop another expression from the expression stack
2539 Status
= PopExpression (&Data1
);
2540 if (EFI_ERROR (Status
)) {
2543 if (Data1
.Type
> EFI_IFR_TYPE_DATE
) {
2544 Status
= EFI_INVALID_PARAMETER
;
2548 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
2550 switch (OpCode
->Operand
) {
2551 case EFI_IFR_ADD_OP
:
2552 Value
->Value
.u64
= Data1
.Value
.u64
+ Data2
.Value
.u64
;
2555 case EFI_IFR_SUBTRACT_OP
:
2556 Value
->Value
.u64
= Data1
.Value
.u64
- Data2
.Value
.u64
;
2559 case EFI_IFR_MULTIPLY_OP
:
2560 Value
->Value
.u64
= MultU64x32 (Data1
.Value
.u64
, (UINT32
) Data2
.Value
.u64
);
2563 case EFI_IFR_DIVIDE_OP
:
2564 Value
->Value
.u64
= DivU64x32 (Data1
.Value
.u64
, (UINT32
) Data2
.Value
.u64
);
2567 case EFI_IFR_MODULO_OP
:
2568 DivU64x32Remainder (Data1
.Value
.u64
, (UINT32
) Data2
.Value
.u64
, &TempValue
);
2569 Value
->Value
.u64
= TempValue
;
2572 case EFI_IFR_BITWISE_AND_OP
:
2573 Value
->Value
.u64
= Data1
.Value
.u64
& Data2
.Value
.u64
;
2576 case EFI_IFR_BITWISE_OR_OP
:
2577 Value
->Value
.u64
= Data1
.Value
.u64
| Data2
.Value
.u64
;
2580 case EFI_IFR_SHIFT_LEFT_OP
:
2581 Value
->Value
.u64
= LShiftU64 (Data1
.Value
.u64
, (UINTN
) Data2
.Value
.u64
);
2584 case EFI_IFR_SHIFT_RIGHT_OP
:
2585 Value
->Value
.u64
= RShiftU64 (Data1
.Value
.u64
, (UINTN
) Data2
.Value
.u64
);
2593 case EFI_IFR_AND_OP
:
2596 // Two Boolean operator
2598 Status
= PopExpression (&Data2
);
2599 if (EFI_ERROR (Status
)) {
2602 if (Data2
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
2603 Status
= EFI_INVALID_PARAMETER
;
2608 // Pop another expression from the expression stack
2610 Status
= PopExpression (&Data1
);
2611 if (EFI_ERROR (Status
)) {
2614 if (Data1
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
2615 Status
= EFI_INVALID_PARAMETER
;
2619 if (OpCode
->Operand
== EFI_IFR_AND_OP
) {
2620 Value
->Value
.b
= (BOOLEAN
) (Data1
.Value
.b
&& Data2
.Value
.b
);
2622 Value
->Value
.b
= (BOOLEAN
) (Data1
.Value
.b
|| Data2
.Value
.b
);
2626 case EFI_IFR_EQUAL_OP
:
2627 case EFI_IFR_NOT_EQUAL_OP
:
2628 case EFI_IFR_GREATER_EQUAL_OP
:
2629 case EFI_IFR_GREATER_THAN_OP
:
2630 case EFI_IFR_LESS_EQUAL_OP
:
2631 case EFI_IFR_LESS_THAN_OP
:
2633 // Compare two integer, string, boolean or date/time
2635 Status
= PopExpression (&Data2
);
2636 if (EFI_ERROR (Status
)) {
2639 if (Data2
.Type
> EFI_IFR_TYPE_BOOLEAN
&&
2640 Data2
.Type
!= EFI_IFR_TYPE_STRING
&&
2641 Data2
.Type
!= EFI_IFR_TYPE_BUFFER
) {
2642 Status
= EFI_INVALID_PARAMETER
;
2647 // Pop another expression from the expression stack
2649 Status
= PopExpression (&Data1
);
2650 if (EFI_ERROR (Status
)) {
2654 Result
= CompareHiiValue (&Data1
, &Data2
, FormSet
->HiiHandle
);
2655 if (Data1
.Type
== EFI_IFR_TYPE_BUFFER
) {
2656 FreePool (Data1
.Buffer
);
2657 FreePool (Data2
.Buffer
);
2660 if (Result
== EFI_INVALID_PARAMETER
) {
2661 Status
= EFI_INVALID_PARAMETER
;
2665 switch (OpCode
->Operand
) {
2666 case EFI_IFR_EQUAL_OP
:
2667 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
2670 case EFI_IFR_NOT_EQUAL_OP
:
2671 Value
->Value
.b
= (BOOLEAN
) ((Result
!= 0) ? TRUE
: FALSE
);
2674 case EFI_IFR_GREATER_EQUAL_OP
:
2675 Value
->Value
.b
= (BOOLEAN
) ((Result
>= 0) ? TRUE
: FALSE
);
2678 case EFI_IFR_GREATER_THAN_OP
:
2679 Value
->Value
.b
= (BOOLEAN
) ((Result
> 0) ? TRUE
: FALSE
);
2682 case EFI_IFR_LESS_EQUAL_OP
:
2683 Value
->Value
.b
= (BOOLEAN
) ((Result
<= 0) ? TRUE
: FALSE
);
2686 case EFI_IFR_LESS_THAN_OP
:
2687 Value
->Value
.b
= (BOOLEAN
) ((Result
< 0) ? TRUE
: FALSE
);
2695 case EFI_IFR_MATCH_OP
:
2696 Status
= InitializeUnicodeCollationProtocol ();
2697 if (EFI_ERROR (Status
)) {
2701 Status
= IfrMatch (FormSet
, Value
);
2704 case EFI_IFR_CATENATE_OP
:
2705 Status
= IfrCatenate (FormSet
, Value
);
2711 case EFI_IFR_CONDITIONAL_OP
:
2713 // Pop third expression from the expression stack
2715 Status
= PopExpression (&Data3
);
2716 if (EFI_ERROR (Status
)) {
2721 // Pop second expression from the expression stack
2723 Status
= PopExpression (&Data2
);
2724 if (EFI_ERROR (Status
)) {
2729 // Pop first expression from the expression stack
2731 Status
= PopExpression (&Data1
);
2732 if (EFI_ERROR (Status
)) {
2735 if (Data1
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
2736 Status
= EFI_INVALID_PARAMETER
;
2740 if (Data1
.Value
.b
) {
2747 case EFI_IFR_FIND_OP
:
2748 Status
= IfrFind (FormSet
, OpCode
->Format
, Value
);
2751 case EFI_IFR_MID_OP
:
2752 Status
= IfrMid (FormSet
, Value
);
2755 case EFI_IFR_TOKEN_OP
:
2756 Status
= IfrToken (FormSet
, Value
);
2759 case EFI_IFR_SPAN_OP
:
2760 Status
= IfrSpan (FormSet
, OpCode
->Flags
, Value
);
2763 case EFI_IFR_MAP_OP
:
2765 // Pop the check value
2767 Status
= PopExpression (&Data1
);
2768 if (EFI_ERROR (Status
)) {
2772 // Check MapExpression list is valid.
2774 if (OpCode
->MapExpressionList
.ForwardLink
== NULL
) {
2775 Status
= EFI_INVALID_PARAMETER
;
2779 // Go through map expression list.
2781 SubExpressionLink
= GetFirstNode(&OpCode
->MapExpressionList
);
2782 while (!IsNull (&OpCode
->MapExpressionList
, SubExpressionLink
)) {
2783 SubExpression
= FORM_EXPRESSION_FROM_LINK (SubExpressionLink
);
2785 // Evaluate the first expression in this pair.
2787 Status
= EvaluateExpression (FormSet
, Form
, SubExpression
);
2788 if (EFI_ERROR (Status
)) {
2792 // Compare the expression value with current value
2794 if (CompareHiiValue (&Data1
, &SubExpression
->Result
, NULL
) == 0) {
2796 // Try get the map value.
2798 SubExpressionLink
= GetNextNode (&OpCode
->MapExpressionList
, SubExpressionLink
);
2799 if (IsNull (&OpCode
->MapExpressionList
, SubExpressionLink
)) {
2800 Status
= EFI_INVALID_PARAMETER
;
2803 SubExpression
= FORM_EXPRESSION_FROM_LINK (SubExpressionLink
);
2804 Status
= EvaluateExpression (FormSet
, Form
, SubExpression
);
2805 if (EFI_ERROR (Status
)) {
2808 Value
= &SubExpression
->Result
;
2812 // Skip the second expression on this pair.
2814 SubExpressionLink
= GetNextNode (&OpCode
->MapExpressionList
, SubExpressionLink
);
2815 if (IsNull (&OpCode
->MapExpressionList
, SubExpressionLink
)) {
2816 Status
= EFI_INVALID_PARAMETER
;
2820 // Goto the first expression on next pair.
2822 SubExpressionLink
= GetNextNode (&OpCode
->MapExpressionList
, SubExpressionLink
);
2826 // No map value is found.
2828 if (IsNull (&OpCode
->MapExpressionList
, SubExpressionLink
)) {
2829 Value
->Type
= EFI_IFR_TYPE_UNDEFINED
;
2830 Value
->Value
.u8
= 0;
2837 if (EFI_ERROR (Status
)) {
2841 Status
= PushExpression (Value
);
2842 if (EFI_ERROR (Status
)) {
2848 // Pop the final result from expression stack
2851 Status
= PopExpression (Value
);
2852 if (EFI_ERROR (Status
)) {
2857 // After evaluating an expression, there should be only one value left on the expression stack
2859 if (PopExpression (Value
) != EFI_ACCESS_DENIED
) {
2860 Status
= EFI_INVALID_PARAMETER
;
2864 RestoreExpressionEvaluationStackOffset (StackOffset
);
2865 if (!EFI_ERROR (Status
)) {
2866 CopyMem (&Expression
->Result
, Value
, sizeof (EFI_HII_VALUE
));