2 Utility functions for expression evaluation.
4 Copyright (c) 2007 - 2009, Intel Corporation
5 All rights reserved. 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
;
29 // Unicode collation protocol interface
31 EFI_UNICODE_COLLATION_PROTOCOL
*mUnicodeCollation
= NULL
;
32 EFI_USER_MANAGER_PROTOCOL
*mUserManager
= NULL
;
35 Grow size of the stack.
37 This is an internal function.
39 @param Stack On input: old stack; On output: new stack
40 @param StackPtr On input: old stack pointer; On output: new stack
42 @param StackEnd On input: old stack end; On output: new stack end
44 @retval EFI_SUCCESS Grow stack success.
45 @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.
50 IN OUT EFI_HII_VALUE
**Stack
,
51 IN OUT EFI_HII_VALUE
**StackPtr
,
52 IN OUT EFI_HII_VALUE
**StackEnd
56 EFI_HII_VALUE
*NewStack
;
58 Size
= EXPRESSION_STACK_SIZE_INCREMENT
;
59 if (*StackPtr
!= NULL
) {
60 Size
= Size
+ (*StackEnd
- *Stack
);
63 NewStack
= AllocatePool (Size
* sizeof (EFI_HII_VALUE
));
64 if (NewStack
== NULL
) {
65 return EFI_OUT_OF_RESOURCES
;
68 if (*StackPtr
!= NULL
) {
70 // Copy from Old Stack to the New Stack
75 (*StackEnd
- *Stack
) * sizeof (EFI_HII_VALUE
)
85 // Make the Stack pointer point to the old data in the new stack
87 *StackPtr
= NewStack
+ (*StackPtr
- *Stack
);
89 *StackEnd
= NewStack
+ Size
;
96 Push an element onto the Boolean Stack.
98 @param Stack On input: old stack; On output: new stack
99 @param StackPtr On input: old stack pointer; On output: new stack
101 @param StackEnd On input: old stack end; On output: new stack end
102 @param Data Data to push.
104 @retval EFI_SUCCESS Push stack success.
109 IN OUT EFI_HII_VALUE
**Stack
,
110 IN OUT EFI_HII_VALUE
**StackPtr
,
111 IN OUT EFI_HII_VALUE
**StackEnd
,
112 IN EFI_HII_VALUE
*Data
118 // Check for a stack overflow condition
120 if (*StackPtr
>= *StackEnd
) {
124 Status
= GrowStack (Stack
, StackPtr
, StackEnd
);
125 if (EFI_ERROR (Status
)) {
131 // Push the item onto the stack
133 CopyMem (*StackPtr
, Data
, sizeof (EFI_HII_VALUE
));
134 *StackPtr
= *StackPtr
+ 1;
141 Pop an element from the stack.
143 @param Stack On input: old stack; On output: new stack
144 @param StackPtr On input: old stack pointer; On output: new stack
146 @param StackEnd On input: old stack end; On output: new stack end
147 @param Data Data to pop.
149 @retval EFI_SUCCESS The value was popped onto the stack.
150 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
155 IN OUT EFI_HII_VALUE
**Stack
,
156 IN OUT EFI_HII_VALUE
**StackPtr
,
157 IN OUT EFI_HII_VALUE
**StackEnd
,
158 OUT EFI_HII_VALUE
*Data
162 // Check for a stack underflow condition
164 if (*StackPtr
== *Stack
) {
165 return EFI_ACCESS_DENIED
;
169 // Pop the item off the stack
171 *StackPtr
= *StackPtr
- 1;
172 CopyMem (Data
, *StackPtr
, sizeof (EFI_HII_VALUE
));
178 Reset stack pointer to begin of the stack.
186 mOpCodeScopeStackPointer
= mOpCodeScopeStack
;
191 Push an Operand onto the Stack
193 @param Operand Operand to push.
195 @retval EFI_SUCCESS The value was pushed onto the stack.
196 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
207 Data
.Type
= EFI_IFR_TYPE_NUM_SIZE_8
;
208 Data
.Value
.u8
= Operand
;
212 &mOpCodeScopeStackPointer
,
213 &mOpCodeScopeStackEnd
,
220 Pop an Operand from the Stack
222 @param Operand Operand to pop.
224 @retval EFI_SUCCESS The value was pushed onto the stack.
225 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
239 &mOpCodeScopeStackPointer
,
240 &mOpCodeScopeStackEnd
,
244 *Operand
= Data
.Value
.u8
;
251 Reset stack pointer to begin of the stack.
255 ResetExpressionStack (
259 mExpressionEvaluationStackPointer
= mExpressionEvaluationStack
;
264 Push an Expression value onto the Stack
266 @param Value Expression value to push.
268 @retval EFI_SUCCESS The value was pushed onto the stack.
269 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
275 IN EFI_HII_VALUE
*Value
279 &mExpressionEvaluationStack
,
280 &mExpressionEvaluationStackPointer
,
281 &mExpressionEvaluationStackEnd
,
288 Pop an Expression value from the stack.
290 @param Value Expression value to pop.
292 @retval EFI_SUCCESS The value was popped onto the stack.
293 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
298 OUT EFI_HII_VALUE
*Value
302 &mExpressionEvaluationStack
,
303 &mExpressionEvaluationStackPointer
,
304 &mExpressionEvaluationStackEnd
,
311 Get Form given its FormId.
313 @param FormSet The formset which contains this form.
314 @param FormId Id of this form.
316 @retval Pointer The form.
317 @retval NULL Specified Form is not found in the formset.
322 IN FORM_BROWSER_FORMSET
*FormSet
,
327 FORM_BROWSER_FORM
*Form
;
329 Link
= GetFirstNode (&FormSet
->FormListHead
);
330 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
331 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
333 if (Form
->FormId
== FormId
) {
337 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
345 Search a Question in Form scope using its QuestionId.
347 @param Form The form which contains this Question.
348 @param QuestionId Id of this Question.
350 @retval Pointer The Question.
351 @retval NULL Specified Question not found in the form.
354 FORM_BROWSER_STATEMENT
*
356 IN FORM_BROWSER_FORM
*Form
,
361 FORM_BROWSER_STATEMENT
*Question
;
363 if (QuestionId
== 0) {
365 // The value of zero is reserved
370 Link
= GetFirstNode (&Form
->StatementListHead
);
371 while (!IsNull (&Form
->StatementListHead
, Link
)) {
372 Question
= FORM_BROWSER_STATEMENT_FROM_LINK (Link
);
374 if (Question
->QuestionId
== QuestionId
) {
378 Link
= GetNextNode (&Form
->StatementListHead
, Link
);
386 Search a Question in Formset scope using its QuestionId.
388 @param FormSet The formset which contains this form.
389 @param Form The form which contains this Question.
390 @param QuestionId Id of this Question.
392 @retval Pointer The Question.
393 @retval NULL Specified Question not found in the form.
396 FORM_BROWSER_STATEMENT
*
398 IN FORM_BROWSER_FORMSET
*FormSet
,
399 IN FORM_BROWSER_FORM
*Form
,
404 FORM_BROWSER_STATEMENT
*Question
;
407 // Search in the form scope first
409 Question
= IdToQuestion2 (Form
, QuestionId
);
410 if (Question
!= NULL
) {
415 // Search in the formset scope
417 Link
= GetFirstNode (&FormSet
->FormListHead
);
418 while (!IsNull (&FormSet
->FormListHead
, Link
)) {
419 Form
= FORM_BROWSER_FORM_FROM_LINK (Link
);
421 Question
= IdToQuestion2 (Form
, QuestionId
);
422 if (Question
!= NULL
) {
424 // EFI variable storage may be updated by Callback() asynchronous,
425 // to keep synchronous, always reload the Question Value.
427 if (Question
->Storage
->Type
== EFI_HII_VARSTORE_EFI_VARIABLE
) {
428 GetQuestionValue (FormSet
, Form
, Question
, FALSE
);
434 Link
= GetNextNode (&FormSet
->FormListHead
, Link
);
442 Get Expression given its RuleId.
444 @param Form The form which contains this Expression.
445 @param RuleId Id of this Expression.
447 @retval Pointer The Expression.
448 @retval NULL Specified Expression not found in the form.
453 IN FORM_BROWSER_FORM
*Form
,
458 FORM_EXPRESSION
*Expression
;
460 Link
= GetFirstNode (&Form
->ExpressionListHead
);
461 while (!IsNull (&Form
->ExpressionListHead
, Link
)) {
462 Expression
= FORM_EXPRESSION_FROM_LINK (Link
);
464 if (Expression
->Type
== EFI_HII_EXPRESSION_RULE
&& Expression
->RuleId
== RuleId
) {
468 Link
= GetNextNode (&Form
->ExpressionListHead
, Link
);
476 Locate the Unicode Collation Protocol interface for later use.
478 @retval EFI_SUCCESS Protocol interface initialize success.
479 @retval Other Protocol interface initialize failed.
483 InitializeUnicodeCollationProtocol (
489 if (mUnicodeCollation
!= NULL
) {
494 // BUGBUG: Proper impelmentation is to locate all Unicode Collation Protocol
495 // instances first and then select one which support English language.
496 // Current implementation just pick the first instance.
498 Status
= gBS
->LocateProtocol (
499 &gEfiUnicodeCollation2ProtocolGuid
,
501 (VOID
**) &mUnicodeCollation
507 Convert the input Unicode character to upper.
509 @param String Th Unicode character to be converted.
517 while (*String
!= 0) {
518 if ((*String
>= 'a') && (*String
<= 'z')) {
519 *String
= (UINT16
) ((*String
) & ((UINT16
) ~0x20));
527 Evaluate opcode EFI_IFR_TO_STRING.
529 @param FormSet Formset which contains this opcode.
530 @param Format String format in EFI_IFR_TO_STRING.
531 @param Result Evaluation result for this opcode.
533 @retval EFI_SUCCESS Opcode evaluation success.
534 @retval Other Opcode evaluation failed.
539 IN FORM_BROWSER_FORMSET
*FormSet
,
541 OUT EFI_HII_VALUE
*Result
548 CHAR16 Buffer
[MAXIMUM_VALUE_CHARACTERS
];
551 Status
= PopExpression (&Value
);
552 if (EFI_ERROR (Status
)) {
556 switch (Value
.Type
) {
557 case EFI_IFR_TYPE_NUM_SIZE_8
:
558 case EFI_IFR_TYPE_NUM_SIZE_16
:
559 case EFI_IFR_TYPE_NUM_SIZE_32
:
560 case EFI_IFR_TYPE_NUM_SIZE_64
:
561 BufferSize
= MAXIMUM_VALUE_CHARACTERS
* sizeof (CHAR16
);
563 case EFI_IFR_STRING_UNSIGNED_DEC
:
564 case EFI_IFR_STRING_SIGNED_DEC
:
565 PrintFormat
= L
"%ld";
568 case EFI_IFR_STRING_LOWERCASE_HEX
:
569 PrintFormat
= L
"%lx";
572 case EFI_IFR_STRING_UPPERCASE_HEX
:
573 PrintFormat
= L
"%lX";
577 return EFI_UNSUPPORTED
;
579 UnicodeSPrint (Buffer
, BufferSize
, PrintFormat
, Value
.Value
.u64
);
583 case EFI_IFR_TYPE_STRING
:
584 CopyMem (Result
, &Value
, sizeof (EFI_HII_VALUE
));
587 case EFI_IFR_TYPE_BOOLEAN
:
588 String
= (Value
.Value
.b
) ? L
"True" : L
"False";
592 return EFI_UNSUPPORTED
;
595 Result
->Type
= EFI_IFR_TYPE_STRING
;
596 Result
->Value
.string
= NewString (String
, FormSet
->HiiHandle
);
602 Evaluate opcode EFI_IFR_TO_UINT.
604 @param FormSet Formset which contains this opcode.
605 @param Result Evaluation result for this opcode.
607 @retval EFI_SUCCESS Opcode evaluation success.
608 @retval Other Opcode evaluation failed.
613 IN FORM_BROWSER_FORMSET
*FormSet
,
614 OUT EFI_HII_VALUE
*Result
622 Status
= PopExpression (&Value
);
623 if (EFI_ERROR (Status
)) {
627 if (Value
.Type
>= EFI_IFR_TYPE_OTHER
) {
628 return EFI_UNSUPPORTED
;
631 Status
= EFI_SUCCESS
;
632 if (Value
.Type
== EFI_IFR_TYPE_STRING
) {
633 String
= GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
634 if (String
== NULL
) {
635 return EFI_NOT_FOUND
;
638 IfrStrToUpper (String
);
639 StringPtr
= StrStr (String
, L
"0X");
640 if (StringPtr
!= NULL
) {
644 Result
->Value
.u64
= StrHexToUint64 (String
);
649 Result
->Value
.u64
= StrDecimalToUint64 (String
);
653 CopyMem (Result
, &Value
, sizeof (EFI_HII_VALUE
));
656 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
662 Evaluate opcode EFI_IFR_CATENATE.
664 @param FormSet Formset which contains this opcode.
665 @param Result Evaluation result for this opcode.
667 @retval EFI_SUCCESS Opcode evaluation success.
668 @retval Other Opcode evaluation failed.
673 IN FORM_BROWSER_FORMSET
*FormSet
,
674 OUT EFI_HII_VALUE
*Result
685 // String[0] - The second string
686 // String[1] - The first string
691 Status
= EFI_SUCCESS
;
693 for (Index
= 0; Index
< 2; Index
++) {
694 Status
= PopExpression (&Value
);
695 if (EFI_ERROR (Status
)) {
699 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
700 Status
= EFI_UNSUPPORTED
;
704 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
705 if (String
[Index
] == NULL
) {
706 Status
= EFI_NOT_FOUND
;
711 Size
= StrSize (String
[0]);
712 StringPtr
= AllocatePool (StrSize (String
[1]) + Size
);
713 ASSERT (StringPtr
!= NULL
);
714 StrCpy (StringPtr
, String
[1]);
715 StrCat (StringPtr
, String
[0]);
717 Result
->Type
= EFI_IFR_TYPE_STRING
;
718 Result
->Value
.string
= NewString (StringPtr
, FormSet
->HiiHandle
);
721 if (String
[0] != NULL
) {
722 FreePool (String
[0]);
724 if (String
[1] != NULL
) {
725 FreePool (String
[1]);
727 if (StringPtr
!= NULL
) {
728 FreePool (StringPtr
);
736 Evaluate opcode EFI_IFR_MATCH.
738 @param FormSet Formset which contains this opcode.
739 @param Result Evaluation result for this opcode.
741 @retval EFI_SUCCESS Opcode evaluation success.
742 @retval Other Opcode evaluation failed.
747 IN FORM_BROWSER_FORMSET
*FormSet
,
748 OUT EFI_HII_VALUE
*Result
757 // String[0] - The string to search
758 // String[1] - pattern
762 Status
= EFI_SUCCESS
;
763 for (Index
= 0; Index
< 2; Index
++) {
764 Status
= PopExpression (&Value
);
765 if (EFI_ERROR (Status
)) {
769 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
770 Status
= EFI_UNSUPPORTED
;
774 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
775 if (String
[Index
] == NULL
) {
776 Status
= EFI_NOT_FOUND
;
781 Result
->Type
= EFI_IFR_TYPE_BOOLEAN
;
782 Result
->Value
.b
= mUnicodeCollation
->MetaiMatch (mUnicodeCollation
, String
[0], String
[1]);
785 if (String
[0] != NULL
) {
786 FreePool (String
[0]);
788 if (String
[1] != NULL
) {
789 FreePool (String
[1]);
797 Evaluate opcode EFI_IFR_FIND.
799 @param FormSet Formset which contains this opcode.
800 @param Format Case sensitive or insensitive.
801 @param Result Evaluation result for this opcode.
803 @retval EFI_SUCCESS Opcode evaluation success.
804 @retval Other Opcode evaluation failed.
809 IN FORM_BROWSER_FORMSET
*FormSet
,
811 OUT EFI_HII_VALUE
*Result
821 if (Format
> EFI_IFR_FF_CASE_INSENSITIVE
) {
822 return EFI_UNSUPPORTED
;
825 Status
= PopExpression (&Value
);
826 if (EFI_ERROR (Status
)) {
829 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
830 return EFI_UNSUPPORTED
;
832 Base
= (UINTN
) Value
.Value
.u64
;
835 // String[0] - sub-string
836 // String[1] - The string to search
840 for (Index
= 0; Index
< 2; Index
++) {
841 Status
= PopExpression (&Value
);
842 if (EFI_ERROR (Status
)) {
846 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
847 Status
= EFI_UNSUPPORTED
;
851 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
852 if (String
[Index
] == NULL
) {
853 Status
= EFI_NOT_FOUND
;
857 if (Format
== EFI_IFR_FF_CASE_INSENSITIVE
) {
859 // Case insensitive, convert both string to upper case
861 IfrStrToUpper (String
[Index
]);
865 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
866 if (Base
>= StrLen (String
[1])) {
867 Result
->Value
.u64
= 0xFFFFFFFFFFFFFFFFULL
;
869 StringPtr
= StrStr (String
[1] + Base
, String
[0]);
870 Result
->Value
.u64
= (StringPtr
== NULL
) ? 0xFFFFFFFFFFFFFFFFULL
: (StringPtr
- String
[1]);
874 if (String
[0] != NULL
) {
875 FreePool (String
[0]);
877 if (String
[1] != NULL
) {
878 FreePool (String
[1]);
886 Evaluate opcode EFI_IFR_MID.
888 @param FormSet Formset which contains this opcode.
889 @param Result Evaluation result for this opcode.
891 @retval EFI_SUCCESS Opcode evaluation success.
892 @retval Other Opcode evaluation failed.
897 IN FORM_BROWSER_FORMSET
*FormSet
,
898 OUT EFI_HII_VALUE
*Result
908 Status
= PopExpression (&Value
);
909 if (EFI_ERROR (Status
)) {
912 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
913 return EFI_UNSUPPORTED
;
915 Length
= (UINTN
) Value
.Value
.u64
;
917 Status
= PopExpression (&Value
);
918 if (EFI_ERROR (Status
)) {
921 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
922 return EFI_UNSUPPORTED
;
924 Base
= (UINTN
) Value
.Value
.u64
;
926 Status
= PopExpression (&Value
);
927 if (EFI_ERROR (Status
)) {
930 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
931 return EFI_UNSUPPORTED
;
933 String
= GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
934 if (String
== NULL
) {
935 return EFI_NOT_FOUND
;
938 if (Length
== 0 || Base
>= StrLen (String
)) {
939 SubString
= gEmptyString
;
941 SubString
= String
+ Base
;
942 if ((Base
+ Length
) < StrLen (String
)) {
943 SubString
[Length
] = L
'\0';
947 Result
->Type
= EFI_IFR_TYPE_STRING
;
948 Result
->Value
.string
= NewString (SubString
, FormSet
->HiiHandle
);
957 Evaluate opcode EFI_IFR_TOKEN.
959 @param FormSet Formset which contains this opcode.
960 @param Result Evaluation result for this opcode.
962 @retval EFI_SUCCESS Opcode evaluation success.
963 @retval Other Opcode evaluation failed.
968 IN FORM_BROWSER_FORMSET
*FormSet
,
969 OUT EFI_HII_VALUE
*Result
981 Status
= PopExpression (&Value
);
982 if (EFI_ERROR (Status
)) {
985 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
986 return EFI_UNSUPPORTED
;
988 Count
= (UINTN
) Value
.Value
.u64
;
991 // String[0] - Delimiter
992 // String[1] - The string to search
996 for (Index
= 0; Index
< 2; Index
++) {
997 Status
= PopExpression (&Value
);
998 if (EFI_ERROR (Status
)) {
1002 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
1003 Status
= EFI_UNSUPPORTED
;
1007 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
1008 if (String
[Index
] == NULL
) {
1009 Status
= EFI_NOT_FOUND
;
1014 Delimiter
= String
[0];
1015 SubString
= String
[1];
1017 SubString
= StrStr (SubString
, Delimiter
);
1018 if (SubString
!= NULL
) {
1020 // Skip over the delimiter
1022 SubString
= SubString
+ StrLen (Delimiter
);
1029 if (SubString
== NULL
) {
1031 // nth delimited sub-string not found, push an empty string
1033 SubString
= gEmptyString
;
1036 // Put a NULL terminator for nth delimited sub-string
1038 StringPtr
= StrStr (SubString
, Delimiter
);
1039 if (StringPtr
!= NULL
) {
1044 Result
->Type
= EFI_IFR_TYPE_STRING
;
1045 Result
->Value
.string
= NewString (SubString
, FormSet
->HiiHandle
);
1048 if (String
[0] != NULL
) {
1049 FreePool (String
[0]);
1051 if (String
[1] != NULL
) {
1052 FreePool (String
[1]);
1060 Evaluate opcode EFI_IFR_SPAN.
1062 @param FormSet Formset which contains this opcode.
1063 @param Flags FIRST_MATCHING or FIRST_NON_MATCHING.
1064 @param Result Evaluation result for this opcode.
1066 @retval EFI_SUCCESS Opcode evaluation success.
1067 @retval Other Opcode evaluation failed.
1072 IN FORM_BROWSER_FORMSET
*FormSet
,
1074 OUT EFI_HII_VALUE
*Result
1078 EFI_HII_VALUE Value
;
1086 Status
= PopExpression (&Value
);
1087 if (EFI_ERROR (Status
)) {
1090 if (Value
.Type
> EFI_IFR_TYPE_NUM_SIZE_64
) {
1091 return EFI_UNSUPPORTED
;
1093 Base
= (UINTN
) Value
.Value
.u64
;
1096 // String[0] - Charset
1097 // String[1] - The string to search
1101 for (Index
= 0; Index
< 2; Index
++) {
1102 Status
= PopExpression (&Value
);
1103 if (EFI_ERROR (Status
)) {
1107 if (Value
.Type
!= EFI_IFR_TYPE_STRING
) {
1108 Status
= EFI_UNSUPPORTED
;
1112 String
[Index
] = GetToken (Value
.Value
.string
, FormSet
->HiiHandle
);
1113 if (String
[Index
] == NULL
) {
1114 Status
= EFI_NOT_FOUND
;
1119 if (Base
>= StrLen (String
[1])) {
1120 Status
= EFI_UNSUPPORTED
;
1125 StringPtr
= String
[1] + Base
;
1126 Charset
= String
[0];
1127 while (*StringPtr
!= 0 && !Found
) {
1129 while (Charset
[Index
] != 0) {
1130 if (*StringPtr
>= Charset
[Index
] && *StringPtr
<= Charset
[Index
+ 1]) {
1131 if (Flags
== EFI_IFR_FLAGS_FIRST_MATCHING
) {
1136 if (Flags
== EFI_IFR_FLAGS_FIRST_NON_MATCHING
) {
1142 // Skip characters pair representing low-end of a range and high-end of a range
1152 Result
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1153 Result
->Value
.u64
= StringPtr
- String
[1];
1156 if (String
[0] != NULL
) {
1157 FreePool (String
[0]);
1159 if (String
[1] != NULL
) {
1160 FreePool (String
[1]);
1168 Zero extend integer/boolean/date/time to UINT64 for comparing.
1170 @param Value HII Value to be converted.
1175 IN EFI_HII_VALUE
*Value
1181 switch (Value
->Type
) {
1182 case EFI_IFR_TYPE_NUM_SIZE_8
:
1183 Temp
= Value
->Value
.u8
;
1186 case EFI_IFR_TYPE_NUM_SIZE_16
:
1187 Temp
= Value
->Value
.u16
;
1190 case EFI_IFR_TYPE_NUM_SIZE_32
:
1191 Temp
= Value
->Value
.u32
;
1194 case EFI_IFR_TYPE_BOOLEAN
:
1195 Temp
= Value
->Value
.b
;
1198 case EFI_IFR_TYPE_TIME
:
1199 Temp
= Value
->Value
.u32
& 0xffffff;
1202 case EFI_IFR_TYPE_DATE
:
1203 Temp
= Value
->Value
.u32
;
1210 Value
->Value
.u64
= Temp
;
1215 Compare two Hii value.
1217 @param Value1 Expression value to compare on left-hand.
1218 @param Value2 Expression value to compare on right-hand.
1219 @param HiiHandle Only required for string compare.
1221 @retval EFI_INVALID_PARAMETER Could not perform comparation on two values.
1222 @retval 0 Two operators equeal.
1223 @return Positive value if Value1 is greater than Value2.
1224 @retval Negative value if Value1 is less than Value2.
1229 IN EFI_HII_VALUE
*Value1
,
1230 IN EFI_HII_VALUE
*Value2
,
1231 IN EFI_HII_HANDLE HiiHandle OPTIONAL
1239 if (Value1
->Type
>= EFI_IFR_TYPE_OTHER
|| Value2
->Type
>= EFI_IFR_TYPE_OTHER
) {
1240 return EFI_INVALID_PARAMETER
;
1243 if (Value1
->Type
== EFI_IFR_TYPE_STRING
|| Value2
->Type
== EFI_IFR_TYPE_STRING
) {
1244 if (Value1
->Type
!= Value2
->Type
) {
1246 // Both Operator should be type of String
1248 return EFI_INVALID_PARAMETER
;
1251 if (Value1
->Value
.string
== 0 || Value2
->Value
.string
== 0) {
1253 // StringId 0 is reserved
1255 return EFI_INVALID_PARAMETER
;
1258 if (Value1
->Value
.string
== Value2
->Value
.string
) {
1262 Str1
= GetToken (Value1
->Value
.string
, HiiHandle
);
1267 return EFI_INVALID_PARAMETER
;
1270 Str2
= GetToken (Value2
->Value
.string
, HiiHandle
);
1273 return EFI_INVALID_PARAMETER
;
1276 Result
= StrCmp (Str1
, Str2
);
1285 // Take remain types(integer, boolean, date/time) as integer
1287 Temp64
= (INT64
) (Value1
->Value
.u64
- Value2
->Value
.u64
);
1290 } else if (Temp64
< 0) {
1300 Check if current user has the privilege specified by the permissions GUID.
1302 @param[in] Guid A GUID specifying setup access permissions.
1304 @retval TRUE Current user has the privilege.
1305 @retval FALSE Current user does not have the privilege.
1308 CheckUserPrivilege (
1313 EFI_USER_PROFILE_HANDLE UserProfileHandle
;
1314 EFI_USER_INFO_HANDLE UserInfoHandle
;
1315 EFI_USER_INFO
*UserInfo
;
1316 EFI_GUID
*UserPermissionsGuid
;
1318 UINTN AccessControlDataSize
;
1319 EFI_USER_INFO_ACCESS_CONTROL
*AccessControl
;
1322 if (mUserManager
== NULL
) {
1323 Status
= gBS
->LocateProtocol (
1324 &gEfiUserManagerProtocolGuid
,
1326 (VOID
**) &mUserManager
1328 if (EFI_ERROR (Status
)) {
1330 /// If the system does not support user management, then it is assumed that
1331 /// all users have admin privilege and evaluation of each EFI_IFR_SECURITY
1332 /// op-code is always TRUE.
1338 Status
= mUserManager
->Current (mUserManager
, &UserProfileHandle
);
1339 ASSERT_EFI_ERROR (Status
);
1342 /// Enumerate all user information of the current user profile
1343 /// to look for any EFI_USER_INFO_ACCESS_SETUP record.
1346 for (UserInfoHandle
= NULL
;;) {
1347 Status
= mUserManager
->GetNextInfo (mUserManager
, UserProfileHandle
, &UserInfoHandle
);
1348 if (EFI_ERROR (Status
)) {
1353 Status
= mUserManager
->GetInfo (mUserManager
, UserProfileHandle
, UserInfoHandle
, NULL
, &UserInfoSize
);
1354 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1358 UserInfo
= (EFI_USER_INFO
*) AllocatePool (UserInfoSize
);
1359 if (UserInfo
== NULL
) {
1363 Status
= mUserManager
->GetInfo (mUserManager
, UserProfileHandle
, UserInfoHandle
, UserInfo
, &UserInfoSize
);
1364 if (EFI_ERROR (Status
) ||
1365 UserInfo
->InfoType
!= EFI_USER_INFO_ACCESS_POLICY_RECORD
||
1366 UserInfo
->InfoSize
<= sizeof (EFI_USER_INFO
)) {
1367 FreePool (UserInfo
);
1371 RemainSize
= UserInfo
->InfoSize
- sizeof (EFI_USER_INFO
);
1372 AccessControl
= (EFI_USER_INFO_ACCESS_CONTROL
*)(UserInfo
+ 1);
1373 while (RemainSize
>= sizeof (EFI_USER_INFO_ACCESS_CONTROL
)) {
1374 if (RemainSize
< AccessControl
->Size
|| AccessControl
->Size
<= sizeof (EFI_USER_INFO_ACCESS_CONTROL
)) {
1377 if (AccessControl
->Type
== EFI_USER_INFO_ACCESS_SETUP
) {
1379 /// Check if current user has the privilege specified by the permissions GUID.
1382 UserPermissionsGuid
= (EFI_GUID
*)(AccessControl
+ 1);
1383 AccessControlDataSize
= AccessControl
->Size
- sizeof (EFI_USER_INFO_ACCESS_CONTROL
);
1384 while (AccessControlDataSize
>= sizeof (EFI_GUID
)) {
1385 if (CompareGuid (Guid
, UserPermissionsGuid
)) {
1386 FreePool (UserInfo
);
1389 UserPermissionsGuid
++;
1390 AccessControlDataSize
-= sizeof (EFI_GUID
);
1393 RemainSize
-= AccessControl
->Size
;
1394 AccessControl
= (EFI_USER_INFO_ACCESS_CONTROL
*)((UINT8
*)AccessControl
+ AccessControl
->Size
);
1397 FreePool (UserInfo
);
1403 Evaluate the result of a HII expression.
1405 If Expression is NULL, then ASSERT.
1407 @param FormSet FormSet associated with this expression.
1408 @param Form Form associated with this expression.
1409 @param Expression Expression to be evaluated.
1411 @retval EFI_SUCCESS The expression evaluated successfuly
1412 @retval EFI_NOT_FOUND The Question which referenced by a QuestionId
1414 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
1416 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
1417 @retval EFI_INVALID_PARAMETER Syntax error with the Expression
1421 EvaluateExpression (
1422 IN FORM_BROWSER_FORMSET
*FormSet
,
1423 IN FORM_BROWSER_FORM
*Form
,
1424 IN OUT FORM_EXPRESSION
*Expression
1429 EXPRESSION_OPCODE
*OpCode
;
1430 FORM_BROWSER_STATEMENT
*Question
;
1431 FORM_BROWSER_STATEMENT
*Question2
;
1433 EFI_HII_VALUE Data1
;
1434 EFI_HII_VALUE Data2
;
1435 EFI_HII_VALUE Data3
;
1436 FORM_EXPRESSION
*RuleExpression
;
1437 EFI_HII_VALUE
*Value
;
1443 // Always reset the stack before evaluating an Expression
1445 ResetExpressionStack ();
1447 ASSERT (Expression
!= NULL
);
1448 Expression
->Result
.Type
= EFI_IFR_TYPE_OTHER
;
1450 Link
= GetFirstNode (&Expression
->OpCodeListHead
);
1451 while (!IsNull (&Expression
->OpCodeListHead
, Link
)) {
1452 OpCode
= EXPRESSION_OPCODE_FROM_LINK (Link
);
1454 Link
= GetNextNode (&Expression
->OpCodeListHead
, Link
);
1456 ZeroMem (&Data1
, sizeof (EFI_HII_VALUE
));
1457 ZeroMem (&Data2
, sizeof (EFI_HII_VALUE
));
1458 ZeroMem (&Data3
, sizeof (EFI_HII_VALUE
));
1461 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
1462 Status
= EFI_SUCCESS
;
1464 switch (OpCode
->Operand
) {
1466 // Built-in functions
1468 case EFI_IFR_EQ_ID_VAL_OP
:
1469 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
1470 if (Question
== NULL
) {
1471 return EFI_NOT_FOUND
;
1474 Result
= CompareHiiValue (&Question
->HiiValue
, &OpCode
->Value
, NULL
);
1475 if (Result
== EFI_INVALID_PARAMETER
) {
1476 return EFI_INVALID_PARAMETER
;
1478 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
1481 case EFI_IFR_EQ_ID_ID_OP
:
1482 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
1483 if (Question
== NULL
) {
1484 return EFI_NOT_FOUND
;
1487 Question2
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId2
);
1488 if (Question2
== NULL
) {
1489 return EFI_NOT_FOUND
;
1492 Result
= CompareHiiValue (&Question
->HiiValue
, &Question2
->HiiValue
, FormSet
->HiiHandle
);
1493 if (Result
== EFI_INVALID_PARAMETER
) {
1494 return EFI_INVALID_PARAMETER
;
1496 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
1499 case EFI_IFR_EQ_ID_LIST_OP
:
1500 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
1501 if (Question
== NULL
) {
1502 return EFI_NOT_FOUND
;
1505 Value
->Value
.b
= FALSE
;
1506 for (Index
=0; Index
< OpCode
->ListLength
; Index
++) {
1507 if (Question
->HiiValue
.Value
.u16
== OpCode
->ValueList
[Index
]) {
1508 Value
->Value
.b
= TRUE
;
1514 case EFI_IFR_DUP_OP
:
1515 Status
= PopExpression (Value
);
1516 if (EFI_ERROR (Status
)) {
1520 Status
= PushExpression (Value
);
1523 case EFI_IFR_QUESTION_REF1_OP
:
1524 case EFI_IFR_THIS_OP
:
1525 Question
= IdToQuestion (FormSet
, Form
, OpCode
->QuestionId
);
1526 if (Question
== NULL
) {
1527 return EFI_NOT_FOUND
;
1530 Value
= &Question
->HiiValue
;
1533 case EFI_IFR_SECURITY_OP
:
1534 Value
->Value
.b
= CheckUserPrivilege (&OpCode
->Guid
);
1537 case EFI_IFR_QUESTION_REF3_OP
:
1538 if (OpCode
->DevicePath
== 0) {
1540 // EFI_IFR_QUESTION_REF3
1541 // Pop an expression from the expression stack
1543 Status
= PopExpression (Value
);
1544 if (EFI_ERROR (Status
)) {
1549 // Validate the expression value
1551 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
1552 return EFI_NOT_FOUND
;
1555 Question
= IdToQuestion (FormSet
, Form
, Value
->Value
.u16
);
1556 if (Question
== NULL
) {
1557 return EFI_NOT_FOUND
;
1561 // push the questions' value on to the expression stack
1563 Value
= &Question
->HiiValue
;
1566 // BUGBUG: push 0 for EFI_IFR_QUESTION_REF3_2 and EFI_IFR_QUESTION_REF3_3,
1567 // since it is impractical to evaluate the value of a Question in another
1568 // Hii Package list.
1570 ZeroMem (Value
, sizeof (EFI_HII_VALUE
));
1574 case EFI_IFR_RULE_REF_OP
:
1576 // Find expression for this rule
1578 RuleExpression
= RuleIdToExpression (Form
, OpCode
->RuleId
);
1579 if (RuleExpression
== NULL
) {
1580 return EFI_NOT_FOUND
;
1584 // Evaluate this rule expression
1586 Status
= EvaluateExpression (FormSet
, Form
, RuleExpression
);
1587 if (EFI_ERROR (Status
)) {
1591 Value
= &RuleExpression
->Result
;
1594 case EFI_IFR_STRING_REF1_OP
:
1595 Value
->Type
= EFI_IFR_TYPE_STRING
;
1596 Value
->Value
.string
= OpCode
->Value
.Value
.string
;
1602 case EFI_IFR_TRUE_OP
:
1603 case EFI_IFR_FALSE_OP
:
1604 case EFI_IFR_ONE_OP
:
1605 case EFI_IFR_ONES_OP
:
1606 case EFI_IFR_UINT8_OP
:
1607 case EFI_IFR_UINT16_OP
:
1608 case EFI_IFR_UINT32_OP
:
1609 case EFI_IFR_UINT64_OP
:
1610 case EFI_IFR_UNDEFINED_OP
:
1611 case EFI_IFR_VERSION_OP
:
1612 case EFI_IFR_ZERO_OP
:
1613 Value
= &OpCode
->Value
;
1619 case EFI_IFR_LENGTH_OP
:
1620 Status
= PopExpression (Value
);
1621 if (EFI_ERROR (Status
)) {
1624 if (Value
->Type
!= EFI_IFR_TYPE_STRING
) {
1625 return EFI_INVALID_PARAMETER
;
1628 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->HiiHandle
);
1629 if (StrPtr
== NULL
) {
1630 return EFI_INVALID_PARAMETER
;
1633 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1634 Value
->Value
.u64
= StrLen (StrPtr
);
1638 case EFI_IFR_NOT_OP
:
1639 Status
= PopExpression (Value
);
1640 if (EFI_ERROR (Status
)) {
1643 if (Value
->Type
!= EFI_IFR_TYPE_BOOLEAN
) {
1644 return EFI_INVALID_PARAMETER
;
1646 Value
->Value
.b
= (BOOLEAN
) (!Value
->Value
.b
);
1649 case EFI_IFR_QUESTION_REF2_OP
:
1651 // Pop an expression from the expression stack
1653 Status
= PopExpression (Value
);
1654 if (EFI_ERROR (Status
)) {
1659 // Validate the expression value
1661 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
1662 return EFI_NOT_FOUND
;
1665 Question
= IdToQuestion (FormSet
, Form
, Value
->Value
.u16
);
1666 if (Question
== NULL
) {
1667 return EFI_NOT_FOUND
;
1670 Value
= &Question
->HiiValue
;
1673 case EFI_IFR_STRING_REF2_OP
:
1675 // Pop an expression from the expression stack
1677 Status
= PopExpression (Value
);
1678 if (EFI_ERROR (Status
)) {
1683 // Validate the expression value
1685 if ((Value
->Type
> EFI_IFR_TYPE_NUM_SIZE_64
) || (Value
->Value
.u64
> 0xffff)) {
1686 return EFI_NOT_FOUND
;
1689 Value
->Type
= EFI_IFR_TYPE_STRING
;
1690 StrPtr
= GetToken (Value
->Value
.u16
, FormSet
->HiiHandle
);
1691 if (StrPtr
== NULL
) {
1693 // If String not exit, push an empty string
1695 Value
->Value
.string
= NewString (gEmptyString
, FormSet
->HiiHandle
);
1697 Index
= (UINT16
) Value
->Value
.u64
;
1698 Value
->Value
.string
= Index
;
1703 case EFI_IFR_TO_BOOLEAN_OP
:
1705 // Pop an expression from the expression stack
1707 Status
= PopExpression (Value
);
1708 if (EFI_ERROR (Status
)) {
1713 // Convert an expression to a Boolean
1715 if (Value
->Type
<= EFI_IFR_TYPE_DATE
) {
1717 // When converting from an unsigned integer, zero will be converted to
1718 // FALSE and any other value will be converted to TRUE.
1720 Value
->Value
.b
= (BOOLEAN
) ((Value
->Value
.u64
) ? TRUE
: FALSE
);
1722 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
1723 } else if (Value
->Type
== EFI_IFR_TYPE_STRING
) {
1725 // When converting from a string, if case-insensitive compare
1726 // with "true" is True, then push True. If a case-insensitive compare
1727 // with "false" is True, then push False.
1729 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->HiiHandle
);
1730 if (StrPtr
== NULL
) {
1731 return EFI_INVALID_PARAMETER
;
1734 if ((StrCmp (StrPtr
, L
"true") == 0) || (StrCmp (StrPtr
, L
"false") == 0)){
1735 Value
->Value
.b
= TRUE
;
1737 Value
->Value
.b
= FALSE
;
1740 Value
->Type
= EFI_IFR_TYPE_BOOLEAN
;
1744 case EFI_IFR_TO_STRING_OP
:
1745 Status
= IfrToString (FormSet
, OpCode
->Format
, Value
);
1748 case EFI_IFR_TO_UINT_OP
:
1749 Status
= IfrToUint (FormSet
, Value
);
1752 case EFI_IFR_TO_LOWER_OP
:
1753 case EFI_IFR_TO_UPPER_OP
:
1754 Status
= InitializeUnicodeCollationProtocol ();
1755 if (EFI_ERROR (Status
)) {
1759 Status
= PopExpression (Value
);
1760 if (EFI_ERROR (Status
)) {
1764 if (Value
->Type
!= EFI_IFR_TYPE_STRING
) {
1765 return EFI_UNSUPPORTED
;
1768 StrPtr
= GetToken (Value
->Value
.string
, FormSet
->HiiHandle
);
1769 if (StrPtr
== NULL
) {
1770 return EFI_NOT_FOUND
;
1773 if (OpCode
->Operand
== EFI_IFR_TO_LOWER_OP
) {
1774 mUnicodeCollation
->StrLwr (mUnicodeCollation
, StrPtr
);
1776 mUnicodeCollation
->StrUpr (mUnicodeCollation
, StrPtr
);
1778 Value
->Value
.string
= NewString (StrPtr
, FormSet
->HiiHandle
);
1782 case EFI_IFR_BITWISE_NOT_OP
:
1784 // Pop an expression from the expression stack
1786 Status
= PopExpression (Value
);
1787 if (EFI_ERROR (Status
)) {
1790 if (Value
->Type
> EFI_IFR_TYPE_DATE
) {
1791 return EFI_INVALID_PARAMETER
;
1794 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1795 Value
->Value
.u64
= ~Value
->Value
.u64
;
1801 case EFI_IFR_ADD_OP
:
1802 case EFI_IFR_SUBTRACT_OP
:
1803 case EFI_IFR_MULTIPLY_OP
:
1804 case EFI_IFR_DIVIDE_OP
:
1805 case EFI_IFR_MODULO_OP
:
1806 case EFI_IFR_BITWISE_AND_OP
:
1807 case EFI_IFR_BITWISE_OR_OP
:
1808 case EFI_IFR_SHIFT_LEFT_OP
:
1809 case EFI_IFR_SHIFT_RIGHT_OP
:
1811 // Pop an expression from the expression stack
1813 Status
= PopExpression (&Data2
);
1814 if (EFI_ERROR (Status
)) {
1817 if (Data2
.Type
> EFI_IFR_TYPE_DATE
) {
1818 return EFI_INVALID_PARAMETER
;
1822 // Pop another expression from the expression stack
1824 Status
= PopExpression (&Data1
);
1825 if (EFI_ERROR (Status
)) {
1828 if (Data1
.Type
> EFI_IFR_TYPE_DATE
) {
1829 return EFI_INVALID_PARAMETER
;
1832 Value
->Type
= EFI_IFR_TYPE_NUM_SIZE_64
;
1834 switch (OpCode
->Operand
) {
1835 case EFI_IFR_ADD_OP
:
1836 Value
->Value
.u64
= Data1
.Value
.u64
+ Data2
.Value
.u64
;
1839 case EFI_IFR_SUBTRACT_OP
:
1840 Value
->Value
.u64
= Data1
.Value
.u64
- Data2
.Value
.u64
;
1843 case EFI_IFR_MULTIPLY_OP
:
1844 Value
->Value
.u64
= MultU64x32 (Data1
.Value
.u64
, (UINT32
) Data2
.Value
.u64
);
1847 case EFI_IFR_DIVIDE_OP
:
1848 Value
->Value
.u64
= DivU64x32 (Data1
.Value
.u64
, (UINT32
) Data2
.Value
.u64
);
1851 case EFI_IFR_MODULO_OP
:
1852 DivU64x32Remainder (Data1
.Value
.u64
, (UINT32
) Data2
.Value
.u64
, &TempValue
);
1853 Value
->Value
.u64
= TempValue
;
1856 case EFI_IFR_BITWISE_AND_OP
:
1857 Value
->Value
.u64
= Data1
.Value
.u64
& Data2
.Value
.u64
;
1860 case EFI_IFR_BITWISE_OR_OP
:
1861 Value
->Value
.u64
= Data1
.Value
.u64
| Data2
.Value
.u64
;
1864 case EFI_IFR_SHIFT_LEFT_OP
:
1865 Value
->Value
.u64
= LShiftU64 (Data1
.Value
.u64
, (UINTN
) Data2
.Value
.u64
);
1868 case EFI_IFR_SHIFT_RIGHT_OP
:
1869 Value
->Value
.u64
= RShiftU64 (Data1
.Value
.u64
, (UINTN
) Data2
.Value
.u64
);
1877 case EFI_IFR_AND_OP
:
1880 // Two Boolean operator
1882 Status
= PopExpression (&Data2
);
1883 if (EFI_ERROR (Status
)) {
1886 if (Data2
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
1887 return EFI_INVALID_PARAMETER
;
1891 // Pop another expression from the expression stack
1893 Status
= PopExpression (&Data1
);
1894 if (EFI_ERROR (Status
)) {
1897 if (Data1
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
1898 return EFI_INVALID_PARAMETER
;
1901 if (OpCode
->Operand
== EFI_IFR_AND_OP
) {
1902 Value
->Value
.b
= (BOOLEAN
) (Data1
.Value
.b
&& Data2
.Value
.b
);
1904 Value
->Value
.b
= (BOOLEAN
) (Data1
.Value
.b
|| Data2
.Value
.b
);
1908 case EFI_IFR_EQUAL_OP
:
1909 case EFI_IFR_NOT_EQUAL_OP
:
1910 case EFI_IFR_GREATER_EQUAL_OP
:
1911 case EFI_IFR_GREATER_THAN_OP
:
1912 case EFI_IFR_LESS_EQUAL_OP
:
1913 case EFI_IFR_LESS_THAN_OP
:
1915 // Compare two integer, string, boolean or date/time
1917 Status
= PopExpression (&Data2
);
1918 if (EFI_ERROR (Status
)) {
1921 if (Data2
.Type
> EFI_IFR_TYPE_BOOLEAN
&& Data2
.Type
!= EFI_IFR_TYPE_STRING
) {
1922 return EFI_INVALID_PARAMETER
;
1926 // Pop another expression from the expression stack
1928 Status
= PopExpression (&Data1
);
1929 if (EFI_ERROR (Status
)) {
1933 Result
= CompareHiiValue (&Data1
, &Data2
, FormSet
->HiiHandle
);
1934 if (Result
== EFI_INVALID_PARAMETER
) {
1935 return EFI_INVALID_PARAMETER
;
1938 switch (OpCode
->Operand
) {
1939 case EFI_IFR_EQUAL_OP
:
1940 Value
->Value
.b
= (BOOLEAN
) ((Result
== 0) ? TRUE
: FALSE
);
1943 case EFI_IFR_NOT_EQUAL_OP
:
1944 Value
->Value
.b
= (BOOLEAN
) ((Result
!= 0) ? TRUE
: FALSE
);
1947 case EFI_IFR_GREATER_EQUAL_OP
:
1948 Value
->Value
.b
= (BOOLEAN
) ((Result
>= 0) ? TRUE
: FALSE
);
1951 case EFI_IFR_GREATER_THAN_OP
:
1952 Value
->Value
.b
= (BOOLEAN
) ((Result
> 0) ? TRUE
: FALSE
);
1955 case EFI_IFR_LESS_EQUAL_OP
:
1956 Value
->Value
.b
= (BOOLEAN
) ((Result
<= 0) ? TRUE
: FALSE
);
1959 case EFI_IFR_LESS_THAN_OP
:
1960 Value
->Value
.b
= (BOOLEAN
) ((Result
< 0) ? TRUE
: FALSE
);
1968 case EFI_IFR_MATCH_OP
:
1969 Status
= IfrMatch (FormSet
, Value
);
1972 case EFI_IFR_CATENATE_OP
:
1973 Status
= IfrCatenate (FormSet
, Value
);
1979 case EFI_IFR_CONDITIONAL_OP
:
1981 // Pop third expression from the expression stack
1983 Status
= PopExpression (&Data3
);
1984 if (EFI_ERROR (Status
)) {
1989 // Pop second expression from the expression stack
1991 Status
= PopExpression (&Data2
);
1992 if (EFI_ERROR (Status
)) {
1997 // Pop first expression from the expression stack
1999 Status
= PopExpression (&Data1
);
2000 if (EFI_ERROR (Status
)) {
2003 if (Data1
.Type
!= EFI_IFR_TYPE_BOOLEAN
) {
2004 return EFI_INVALID_PARAMETER
;
2007 if (Data1
.Value
.b
) {
2014 case EFI_IFR_FIND_OP
:
2015 Status
= IfrFind (FormSet
, OpCode
->Format
, Value
);
2018 case EFI_IFR_MID_OP
:
2019 Status
= IfrMid (FormSet
, Value
);
2022 case EFI_IFR_TOKEN_OP
:
2023 Status
= IfrToken (FormSet
, Value
);
2026 case EFI_IFR_SPAN_OP
:
2027 Status
= IfrSpan (FormSet
, OpCode
->Flags
, Value
);
2033 if (EFI_ERROR (Status
)) {
2037 Status
= PushExpression (Value
);
2038 if (EFI_ERROR (Status
)) {
2044 // Pop the final result from expression stack
2047 Status
= PopExpression (Value
);
2048 if (EFI_ERROR (Status
)) {
2053 // After evaluating an expression, there should be only one value left on the expression stack
2055 if (PopExpression (Value
) != EFI_ACCESS_DENIED
) {
2056 return EFI_INVALID_PARAMETER
;
2059 CopyMem (&Expression
->Result
, Value
, sizeof (EFI_HII_VALUE
));