blob: c7bcb88fb2a5b5aa8518ccf6e1d6c6b0ab10a6a3 [file] [log] [blame]
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
Boolean.c
Abstract:
This routine will evaluate the IFR inconsistency data to determine if
something is a valid entry for a particular expression
--*/
#include "Setup.h"
#include "Ui.h"
//
// Global stack used to evaluate boolean expresions
//
BOOLEAN *mBooleanEvaluationStack = (BOOLEAN) 0;
BOOLEAN *mBooleanEvaluationStackEnd = (BOOLEAN) 0;
STATIC
VOID
GrowBooleanStack (
IN OUT BOOLEAN **Stack,
IN UINTN StackSizeInBoolean
)
/*++
Routine Description:
Grow size of the boolean stack
Arguments:
Stack - Old stack on the way in and new stack on the way out
StackSizeInBoolean - New size of the stack
Returns:
NONE
--*/
{
BOOLEAN *NewStack;
NewStack = AllocatePool (StackSizeInBoolean * sizeof (BOOLEAN));
ASSERT (NewStack != NULL);
if (*Stack != NULL) {
//
// Copy to Old Stack to the New Stack
//
CopyMem (
NewStack,
mBooleanEvaluationStack,
(mBooleanEvaluationStackEnd - mBooleanEvaluationStack) * sizeof (BOOLEAN)
);
//
// Make the Stack pointer point to the old data in the new stack
//
*Stack = NewStack + (*Stack - mBooleanEvaluationStack);
//
// Free The Old Stack
//
gBS->FreePool (mBooleanEvaluationStack);
}
mBooleanEvaluationStack = NewStack;
mBooleanEvaluationStackEnd = NewStack + StackSizeInBoolean;
}
VOID
InitializeBooleanEvaluator (
VOID
)
/*++
Routine Description:
Allocate a global stack for boolean processing.
Arguments:
NONE
Returns:
NONE
--*/
{
BOOLEAN *NullStack;
NullStack = NULL;
GrowBooleanStack (&NullStack, 0x1000);
}
STATIC
VOID
PushBool (
IN OUT BOOLEAN **Stack,
IN BOOLEAN BoolResult
)
/*++
Routine Description:
Push an element onto the Boolean Stack
Arguments:
Stack - Current stack location.
BoolResult - BOOLEAN to push.
Returns:
None.
--*/
{
CopyMem (*Stack, &BoolResult, sizeof (BOOLEAN));
*Stack += 1;
if (*Stack >= mBooleanEvaluationStackEnd) {
//
// If we run out of stack space make a new one that is 2X as big. Copy
// the old data into the new stack and update Stack to point to the old
// data in the new stack.
//
GrowBooleanStack (
Stack,
(mBooleanEvaluationStackEnd - mBooleanEvaluationStack) * sizeof (BOOLEAN) * 2
);
}
}
STATIC
BOOLEAN
PopBool (
IN OUT BOOLEAN **Stack
)
/*++
Routine Description:
Pop an element from the Boolean stack.
Arguments:
Stack - Current stack location
Returns:
Top of the BOOLEAN stack.
--*/
{
BOOLEAN ReturnValue;
*Stack -= 1;
CopyMem (&ReturnValue, *Stack, sizeof (BOOLEAN));
return ReturnValue;
}
EFI_STATUS
GrowBooleanExpression (
IN EFI_INCONSISTENCY_DATA *InconsistentTags,
OUT VOID **BooleanExpression,
IN OUT UINTN *BooleanExpressionLength
)
{
UINT8 *NewExpression;
NewExpression = AllocatePool (*BooleanExpressionLength + sizeof (EFI_INCONSISTENCY_DATA));
ASSERT (NewExpression != NULL);
if (*BooleanExpression != NULL) {
//
// Copy Old buffer to the New buffer
//
CopyMem (NewExpression, *BooleanExpression, *BooleanExpressionLength);
CopyMem (&NewExpression[*BooleanExpressionLength], InconsistentTags, sizeof (EFI_INCONSISTENCY_DATA));
//
// Free The Old buffer
//
gBS->FreePool (*BooleanExpression);
} else {
//
// Copy data into new buffer
//
CopyMem (NewExpression, InconsistentTags, sizeof (EFI_INCONSISTENCY_DATA));
}
*BooleanExpressionLength = *BooleanExpressionLength + sizeof (EFI_INCONSISTENCY_DATA);
*BooleanExpression = (VOID *) NewExpression;
return EFI_SUCCESS;
}
VOID
CreateBooleanExpression (
IN EFI_FILE_FORM_TAGS *FileFormTags,
IN UINT16 Value,
IN UINT16 Id,
IN BOOLEAN Complex,
OUT VOID **BooleanExpression,
OUT UINTN *BooleanExpressionLength
)
/*++
Routine Description:
Arguments:
Returns:
--*/
{
UINTN Count;
EFI_INCONSISTENCY_DATA *InconsistentTags;
EFI_INCONSISTENCY_DATA FakeInconsistentTags;
InconsistentTags = FileFormTags->InconsistentTags;
//
// Did we run into a question that contains the Id we are looking for?
//
for (Count = 0; InconsistentTags->Operand != 0xFF; Count++) {
//
// Reserve INVALID_OFFSET_VALUE - 1 for TURE and FALSE, because we need to treat them as well
// as ideqid etc. but they have no coresponding id, so we reserve this value.
//
if (InconsistentTags->QuestionId1 == Id ||
InconsistentTags->QuestionId1 == INVALID_OFFSET_VALUE - 1) {
//
// If !Complex - means evaluate a single if/endif expression
//
if (!Complex) {
//
// If the ConsistencyId does not match the expression we are looking for
// skip to the next consistency database entry
//
if (InconsistentTags->ConsistencyId != Value) {
goto NextEntry;
}
}
//
// We need to rewind to the beginning of the Inconsistent expression
//
for (;
(InconsistentTags->Operand != EFI_IFR_INCONSISTENT_IF_OP) &&
(InconsistentTags->Operand != EFI_IFR_GRAYOUT_IF_OP) &&
(InconsistentTags->Operand != EFI_IFR_SUPPRESS_IF_OP);
) {
InconsistentTags = InconsistentTags->Previous;
}
//
// Store the consistency check expression, ensure the next for loop starts at the op-code afterwards
//
GrowBooleanExpression (InconsistentTags, BooleanExpression, BooleanExpressionLength);
InconsistentTags = InconsistentTags->Next;
//
// Keep growing until we hit the End expression op-code or we hit the beginning of another
// consistency check like grayout/suppress
//
for (;
InconsistentTags->Operand != EFI_IFR_END_IF_OP &&
InconsistentTags->Operand != EFI_IFR_GRAYOUT_IF_OP &&
InconsistentTags->Operand != EFI_IFR_SUPPRESS_IF_OP;
) {
GrowBooleanExpression (InconsistentTags, BooleanExpression, BooleanExpressionLength);
InconsistentTags = InconsistentTags->Next;
}
//
// Store the EndExpression Op-code
//
GrowBooleanExpression (InconsistentTags, BooleanExpression, BooleanExpressionLength);
}
NextEntry:
if (InconsistentTags->Next != NULL) {
//
// Skip to next entry
//
InconsistentTags = InconsistentTags->Next;
}
}
FakeInconsistentTags.Operand = 0;
//
// Add one last expression which will signify we have definitely hit the end
//
GrowBooleanExpression (&FakeInconsistentTags, BooleanExpression, BooleanExpressionLength);
}
EFI_STATUS
BooleanVariableWorker (
IN CHAR16 *VariableName,
IN EFI_VARIABLE_DEFINITION *VariableDefinition,
IN BOOLEAN *StackPtr,
IN OUT UINTN *SizeOfVariable,
IN OUT VOID **VariableData
)
/*++
Routine Description:
Arguments:
Returns:
--*/
{
EFI_STATUS Status;
Status = gRT->GetVariable (
VariableName,
&VariableDefinition->Guid,
NULL,
SizeOfVariable,
*VariableData
);
if (EFI_ERROR (Status)) {
if (Status == EFI_BUFFER_TOO_SMALL) {
*VariableData = AllocatePool (*SizeOfVariable);
ASSERT (*VariableData != NULL);
Status = gRT->GetVariable (
VariableName,
&VariableDefinition->Guid,
NULL,
SizeOfVariable,
*VariableData
);
}
if (Status == EFI_NOT_FOUND) {
//
// This is a serious flaw, we must have some standard result if a variable
// is not found. Our default behavior must either be return a TRUE or FALSE
// since there is nothing else we can really do. Therefore, my crystal ball
// says I will return a FALSE
//
PushBool (&StackPtr, FALSE);
}
}
return Status;
}
UINT8
PredicateIfrType (
IN EFI_INCONSISTENCY_DATA *Iterator
)
/*++
Routine Description:
This routine is for the purpose of predicate whether the Ifr is generated by a VfrCompiler greater than or equal to 1.88 or
less than 1.88 which is legacy.
Arguments:
Iterator - The pointer to inconsistency tags
Returns:
0x2 - If IFR is not legacy
0x1 - If IFR is legacy
--*/
{
//
// legacy Ifr cover the states:
// Not ...
// Operand Opcode Operand
//
// while Operand means ideqval, TRUE, or other what can be evaluated to True or False,
// and Opcode means AND or OR.
//
if (Iterator->Operand == EFI_IFR_NOT_OP ||
Iterator->Operand == 0) {
return 0x1;
} else if (Iterator->Operand == EFI_IFR_EQ_VAR_VAL_OP ||
Iterator->Operand == EFI_IFR_EQ_ID_VAL_OP ||
Iterator->Operand == EFI_IFR_EQ_ID_ID_OP ||
Iterator->Operand == EFI_IFR_EQ_ID_LIST_OP) {
Iterator++;
if (Iterator->Operand == EFI_IFR_AND_OP ||
Iterator->Operand == EFI_IFR_OR_OP) {
Iterator--;
return 0x1;
}
Iterator--;
}
return 0x2;
}
VOID
PostOrderEvaluate (
IN EFI_FILE_FORM_TAGS *FileFormTags,
IN UINT16 Width,
IN OUT EFI_INCONSISTENCY_DATA **PIterator,
IN OUT BOOLEAN **StackPtr
)
/*++
Routine Description:
PostOrderEvaluate is used for Ifr generated by VfrCompiler greater than or equal to 1.88,
which generate Operand Operand Opcode type Ifr.
PostOrderEvaluete only evaluate boolean expression part, not suppressif/grayoutif. TRUE,
FALSE, >=, >, (, ) are supported.
Arguments:
FileFormTags - The pointer to the tags of the form
Width - Width of Operand, recognized every iteration
PIterator - The pointer to inconsistency tags
StackPtr - The pointer to the evaluation stack
Returns:
TRUE - If value is valid
FALSE - If value is not valid
--*/
{
BOOLEAN Operator;
BOOLEAN Operator2;
UINT16 *MapBuffer;
UINT16 *MapBuffer2;
UINT16 MapValue;
UINT16 MapValue2;
UINTN SizeOfVariable;
CHAR16 VariableName[40];
VOID *VariableData;
EFI_VARIABLE_DEFINITION *VariableDefinition;
EFI_STATUS Status;
UINTN Index;
BOOLEAN PushValue;
Operator = FALSE;
Operator2 = FALSE;
MapBuffer = NULL;
MapBuffer2 = NULL;
MapValue = 0;
MapValue2 = 0;
VariableData = NULL;
while (TRUE) {
if ((*PIterator)->Operand == 0) {
return;
}
Width = (*PIterator)->Width;
//
// Because INVALID_OFFSET_VALUE - 1 is reserved for TRUE or FALSE, omit them.
//
if ((*PIterator)->QuestionId1 != INVALID_OFFSET_VALUE &&
(*PIterator)->QuestionId1 != INVALID_OFFSET_VALUE - 1) {
ExtractNvValue (FileFormTags, (*PIterator)->VariableNumber, Width, (*PIterator)->QuestionId1, (VOID **) &MapBuffer);
ExtractNvValue (FileFormTags, (*PIterator)->VariableNumber2, Width, (*PIterator)->QuestionId2, (VOID **) &MapBuffer2);
if (MapBuffer != NULL) {
if (Width == 2) {
MapValue = *MapBuffer;
} else {
MapValue = (UINT8) *MapBuffer;
}
gBS->FreePool (MapBuffer);
}
if (MapBuffer2 != NULL) {
if (Width == 2) {
MapValue2 = *MapBuffer2;
} else {
MapValue2 = (UINT8) *MapBuffer2;
}
gBS->FreePool (MapBuffer2);
}
}
switch ((*PIterator)->Operand) {
case EFI_IFR_EQ_VAR_VAL_OP:
UnicodeValueToString (
VariableName,
FALSE,
(UINTN) (*PIterator)->QuestionId1,
(sizeof (VariableName) / sizeof (VariableName[0]))
);
SizeOfVariable = 0;
ExtractRequestedNvMap (FileFormTags, (*PIterator)->VariableNumber, &VariableDefinition);
Status = BooleanVariableWorker (
VariableName,
VariableDefinition,
*StackPtr,
&SizeOfVariable,
&VariableData
);
if (!EFI_ERROR (Status)) {
if (SizeOfVariable == 1) {
CopyMem (&MapValue, VariableData, 1);
} else {
CopyMem (&MapValue, VariableData, 2);
}
//
// Do operation after knowing the compare operator.
//
MapValue2 = (*PIterator)->Value;
(*PIterator)++;
if ((*PIterator)->Operand == EFI_IFR_GT_OP) {
PushValue = (BOOLEAN) (MapValue > MapValue2);
} else if ((*PIterator)->Operand == EFI_IFR_GE_OP) {
PushValue = (BOOLEAN) (MapValue >= MapValue2);
} else {
(*PIterator)--;
PushValue = (BOOLEAN) (MapValue == MapValue2);
}
PushBool (StackPtr, PushValue);
}
break;
case EFI_IFR_EQ_ID_VAL_OP:
//
// Do operation after knowing the compare operator.
//
MapValue2 = (*PIterator)->Value;
(*PIterator)++;
if ((*PIterator)->Operand == EFI_IFR_GT_OP) {
PushValue = (BOOLEAN) (MapValue > MapValue2);
} else if ((*PIterator)->Operand == EFI_IFR_GE_OP) {
PushValue = (BOOLEAN) (MapValue >= MapValue2);
} else {
(*PIterator)--;
PushValue = (BOOLEAN) (MapValue == MapValue2);
}
PushBool (StackPtr, PushValue);
break;
case EFI_IFR_EQ_ID_ID_OP:
//
// Do operation after knowing the compare operator.
//
(*PIterator)++;
if ((*PIterator)->Operand == EFI_IFR_GT_OP) {
PushValue = (BOOLEAN) (MapValue > MapValue2);
} else if ((*PIterator)->Operand == EFI_IFR_GE_OP) {
PushValue = (BOOLEAN) (MapValue >= MapValue2);
} else {
(*PIterator)--;
PushValue = (BOOLEAN) (MapValue == MapValue2);
}
PushBool (StackPtr, PushValue);
break;
case EFI_IFR_EQ_ID_LIST_OP:
for (Index = 0; Index < (*PIterator)->ListLength; Index++) {
Operator = (BOOLEAN) (MapValue == (*PIterator)->ValueList[Index]);
if (Operator) {
break;
}
}
PushBool (StackPtr, Operator);
break;
case EFI_IFR_TRUE_OP:
PushBool (StackPtr, TRUE);
break;
case EFI_IFR_FALSE_OP:
PushBool (StackPtr, FALSE);
break;
case EFI_IFR_AND_OP:
Operator = PopBool (StackPtr);
Operator2 = PopBool (StackPtr);
PushBool (StackPtr, (BOOLEAN) (Operator && Operator2));
break;
case EFI_IFR_OR_OP:
Operator = PopBool (StackPtr);
Operator2 = PopBool (StackPtr);
PushBool (StackPtr, (BOOLEAN) (Operator || Operator2));
break;
case EFI_IFR_NOT_OP:
Operator = PopBool (StackPtr);
PushBool (StackPtr, !Operator);
break;
case EFI_IFR_SUPPRESS_IF_OP:
case EFI_IFR_GRAYOUT_IF_OP:
case EFI_IFR_INCONSISTENT_IF_OP:
default:
//
// Return to the previous tag if runs out of boolean expression.
//
(*PIterator)--;
return;
}
(*PIterator)++;
}
}
BOOLEAN
ValueIsNotValid (
IN BOOLEAN Complex,
IN UINT16 Value,
IN EFI_TAG *Tag,
IN EFI_FILE_FORM_TAGS *FileFormTags,
IN STRING_REF *PopUp
)
/*++
Routine Description:
Arguments:
Returns:
TRUE - If value is valid
FALSE - If value is not valid
--*/
{
BOOLEAN *StackPtr;
EFI_INCONSISTENCY_DATA *Iterator;
BOOLEAN Operator;
BOOLEAN Operator2;
UINTN Index;
VOID *BooleanExpression;
UINTN BooleanExpressionLength;
BOOLEAN NotOperator;
BOOLEAN OrOperator;
BOOLEAN AndOperator;
BOOLEAN ArtificialEnd;
UINT16 *MapBuffer;
UINT16 *MapBuffer2;
UINT16 MapValue;
UINT16 MapValue2;
UINTN SizeOfVariable;
CHAR16 VariableName[40];
VOID *VariableData;
EFI_STATUS Status;
UINT16 Id;
UINT16 Width;
EFI_VARIABLE_DEFINITION *VariableDefinition;
BOOLEAN CosmeticConsistency;
UINT8 IsLegacy;
VariableData = NULL;
BooleanExpressionLength = 0;
BooleanExpression = NULL;
Operator = FALSE;
ArtificialEnd = FALSE;
CosmeticConsistency = TRUE;
IsLegacy = 0;
Id = Tag->Id;
if (Tag->StorageWidth == 1) {
Width = 1;
} else {
Width = 2;
}
CreateBooleanExpression (FileFormTags, Value, Id, Complex, &BooleanExpression, &BooleanExpressionLength);
if (mBooleanEvaluationStack == 0) {
InitializeBooleanEvaluator ();
}
if (BooleanExpression == NULL) {
return FALSE;
}
StackPtr = mBooleanEvaluationStack;
Iterator = BooleanExpression;
MapBuffer = NULL;
MapBuffer2 = NULL;
MapValue = 0;
MapValue2 = 0;
while (TRUE) {
NotOperator = FALSE;
OrOperator = FALSE;
AndOperator = FALSE;
if (Iterator->Operand == 0) {
return Operator;
}
//
// Because INVALID_OFFSET_VALUE - 1 is reserved for TRUE or FALSE, omit them.
//
if (Iterator->QuestionId1 != INVALID_OFFSET_VALUE &&
Iterator->QuestionId1 != INVALID_OFFSET_VALUE-1) {
ExtractNvValue (FileFormTags, Iterator->VariableNumber, Width, Iterator->QuestionId1, (VOID **) &MapBuffer);
ExtractNvValue (FileFormTags, Iterator->VariableNumber2, Width, Iterator->QuestionId2, (VOID **) &MapBuffer2);
if (MapBuffer != NULL) {
if (Width == 2) {
MapValue = *MapBuffer;
} else {
MapValue = (UINT8) *MapBuffer;
}
gBS->FreePool (MapBuffer);
}
if (MapBuffer2 != NULL) {
if (Width == 2) {
MapValue2 = *MapBuffer2;
} else {
MapValue2 = (UINT8) *MapBuffer2;
}
gBS->FreePool (MapBuffer2);
}
}
switch (Iterator->Operand) {
case EFI_IFR_SUPPRESS_IF_OP:
//
// Must have hit a suppress followed by a grayout or vice-versa
//
if (ArtificialEnd) {
ArtificialEnd = FALSE;
Operator = PopBool (&StackPtr);
if (Operator) {
Tag->Suppress = TRUE;
}
return Operator;
}
ArtificialEnd = TRUE;
*PopUp = Iterator->Popup;
break;
case EFI_IFR_GRAYOUT_IF_OP:
//
// Must have hit a suppress followed by a grayout or vice-versa
//
if (ArtificialEnd) {
ArtificialEnd = FALSE;
Operator = PopBool (&StackPtr);
if (Operator) {
Tag->GrayOut = TRUE;
}
return Operator;
}
ArtificialEnd = TRUE;
*PopUp = Iterator->Popup;
break;
case EFI_IFR_INCONSISTENT_IF_OP:
CosmeticConsistency = FALSE;
*PopUp = Iterator->Popup;
break;
//
// In the case of external variable values, we must read the variable which is
// named by the human readable version of the OpCode->VariableId and the guid of the formset
//
case EFI_IFR_EQ_VAR_VAL_OP:
//
// To check whether Ifr is legacy. Once every boolean expression.
//
if (IsLegacy == 0) {
IsLegacy = PredicateIfrType (Iterator);
}
if (IsLegacy == 0x2) {
PostOrderEvaluate (FileFormTags, Width, &Iterator, &StackPtr);
break;
}
UnicodeValueToString (
VariableName,
FALSE,
(UINTN) Iterator->QuestionId1,
(sizeof (VariableName) / sizeof (VariableName[0]))
);
SizeOfVariable = 0;
ExtractRequestedNvMap (FileFormTags, Iterator->VariableNumber, &VariableDefinition);
Status = BooleanVariableWorker (
VariableName,
VariableDefinition,
StackPtr,
&SizeOfVariable,
&VariableData
);
if (!EFI_ERROR (Status)) {
if (SizeOfVariable == 1) {
CopyMem (&MapValue, VariableData, 1);
} else {
CopyMem (&MapValue, VariableData, 2);
}
PushBool (&StackPtr, (BOOLEAN) (MapValue == Iterator->Value));
}
break;
case EFI_IFR_EQ_ID_VAL_OP:
//
// To check whether Ifr is legacy. Once every boolean expression.
//
if (IsLegacy == 0) {
IsLegacy = PredicateIfrType (Iterator);
}
if (IsLegacy == 0x2) {
PostOrderEvaluate (FileFormTags, Width, &Iterator, &StackPtr);
break;
}
PushBool (&StackPtr, (BOOLEAN) (MapValue == Iterator->Value));
break;
case EFI_IFR_EQ_ID_ID_OP:
//
// To check whether Ifr is legacy. Once every boolean expression.
//
if (IsLegacy == 0) {
IsLegacy = PredicateIfrType (Iterator);
}
if (IsLegacy == 0x2) {
PostOrderEvaluate (FileFormTags, Width, &Iterator, &StackPtr);
break;
}
PushBool (&StackPtr, (BOOLEAN) (MapValue == MapValue2));
break;
case EFI_IFR_EQ_ID_LIST_OP:
//
// To check whether Ifr is legacy. Once every boolean expression.
//
if (IsLegacy == 0) {
IsLegacy = PredicateIfrType (Iterator);
}
if (IsLegacy == 0x2) {
PostOrderEvaluate (FileFormTags, Width, &Iterator, &StackPtr);
break;
}
for (Index = 0; Index < Iterator->ListLength; Index++) {
Operator = (BOOLEAN) (MapValue == Iterator->ValueList[Index]);
if (Operator) {
break;
}
}
PushBool (&StackPtr, Operator);
break;
case EFI_IFR_AND_OP:
Iterator++;
if (Iterator->Operand == EFI_IFR_NOT_OP) {
NotOperator = TRUE;
Iterator++;
}
if (Iterator->QuestionId1 != INVALID_OFFSET_VALUE) {
ExtractNvValue (FileFormTags, Iterator->VariableNumber, Width, Iterator->QuestionId1, (VOID **) &MapBuffer);
ExtractNvValue (FileFormTags, Iterator->VariableNumber2, Width, Iterator->QuestionId2, (VOID **) &MapBuffer2);
if (MapBuffer != NULL) {
if (Width == 2) {
MapValue = *MapBuffer;
} else {
MapValue = (UINT8) *MapBuffer;
}
gBS->FreePool (MapBuffer);
}
if (MapBuffer2 != NULL) {
if (Width == 2) {
MapValue2 = *MapBuffer2;
} else {
MapValue2 = (UINT8) *MapBuffer2;
}
gBS->FreePool (MapBuffer2);
}
}
switch (Iterator->Operand) {
case EFI_IFR_EQ_ID_VAL_OP:
//
// If Not - flip the results
//
if (NotOperator) {
Operator = (BOOLEAN)!(MapValue == Iterator->Value);
} else {
Operator = (BOOLEAN) (MapValue == Iterator->Value);
}
PushBool (&StackPtr, Operator);
break;
//
// In the case of external variable values, we must read the variable which is
// named by the human readable version of the OpCode->VariableId and the guid of the formset
//
case EFI_IFR_EQ_VAR_VAL_OP:
UnicodeValueToString (
VariableName,
FALSE,
(UINTN) Iterator->QuestionId1,
(sizeof (VariableName) / sizeof (VariableName[0]))
);
SizeOfVariable = 0;
ExtractRequestedNvMap (FileFormTags, Iterator->VariableNumber, &VariableDefinition);
Status = BooleanVariableWorker (
VariableName,
VariableDefinition,
StackPtr,
&SizeOfVariable,
&VariableData
);
if (!EFI_ERROR (Status)) {
if (SizeOfVariable == 1) {
CopyMem (&MapValue, VariableData, 1);
} else {
CopyMem (&MapValue, VariableData, 2);
}
//
// If Not - flip the results
//
if (NotOperator) {
PushBool (&StackPtr, (BOOLEAN)!(MapValue == Iterator->Value));
} else {
PushBool (&StackPtr, (BOOLEAN) (MapValue == Iterator->Value));
}
}
break;
case EFI_IFR_EQ_ID_ID_OP:
//
// If Not - flip the results
//
if (NotOperator) {
Operator = (BOOLEAN)!(MapValue == MapValue2);
} else {
Operator = (BOOLEAN) (MapValue == MapValue2);
}
PushBool (&StackPtr, Operator);
break;
case EFI_IFR_EQ_ID_LIST_OP:
for (Index = 0; Index < Iterator->ListLength; Index++) {
//
// If Not - flip the results
//
if (NotOperator) {
Operator = (BOOLEAN)!(MapValue == Iterator->ValueList[Index]);
} else {
Operator = (BOOLEAN) (MapValue == Iterator->ValueList[Index]);
}
//
// If We are trying to make sure that MapValue != Item[x], keep looking through
// the list to make sure we don't equal any other items
//
if (Operator && NotOperator) {
continue;
}
//
// If MapValue == Item, then we have succeeded (first found is good enough)
//
if (Operator) {
break;
}
}
PushBool (&StackPtr, Operator);
break;
default:
return FALSE;
}
Operator = PopBool (&StackPtr);
Operator2 = PopBool (&StackPtr);
PushBool (&StackPtr, (BOOLEAN) (Operator && Operator2));
break;
case EFI_IFR_OR_OP:
Iterator++;
if (Iterator->Operand == EFI_IFR_NOT_OP) {
NotOperator = TRUE;
Iterator++;
}
if (Iterator->QuestionId1 != INVALID_OFFSET_VALUE) {
ExtractNvValue (FileFormTags, Iterator->VariableNumber, Width, Iterator->QuestionId1, (VOID **) &MapBuffer);
ExtractNvValue (FileFormTags, Iterator->VariableNumber2, Width, Iterator->QuestionId2, (VOID **) &MapBuffer2);
if (MapBuffer != NULL) {
if (Width == 2) {
MapValue = *MapBuffer;
} else {
MapValue = (UINT8) *MapBuffer;
}
gBS->FreePool (MapBuffer);
}
if (MapBuffer2 != NULL) {
if (Width == 2) {
MapValue2 = *MapBuffer2;
} else {
MapValue2 = (UINT8) *MapBuffer2;
}
gBS->FreePool (MapBuffer2);
}
}
switch (Iterator->Operand) {
case EFI_IFR_EQ_ID_VAL_OP:
//
// If Not - flip the results
//
if (NotOperator) {
Operator = (BOOLEAN)!(MapValue == Iterator->Value);
} else {
Operator = (BOOLEAN) (MapValue == Iterator->Value);
}
PushBool (&StackPtr, Operator);
break;
//
// In the case of external variable values, we must read the variable which is
// named by the human readable version of the OpCode->VariableId and the guid of the formset
//
case EFI_IFR_EQ_VAR_VAL_OP:
UnicodeValueToString (
VariableName,
FALSE,
(UINTN) Iterator->QuestionId1,
(sizeof (VariableName) / sizeof (VariableName[0]))
);
SizeOfVariable = 0;
ExtractRequestedNvMap (FileFormTags, Iterator->VariableNumber, &VariableDefinition);
Status = BooleanVariableWorker (
VariableName,
VariableDefinition,
StackPtr,
&SizeOfVariable,
&VariableData
);
if (!EFI_ERROR (Status)) {
if (SizeOfVariable == 1) {
CopyMem (&MapValue, VariableData, 1);
} else {
CopyMem (&MapValue, VariableData, 2);
}
//
// If Not - flip the results
//
if (NotOperator) {
PushBool (&StackPtr, (BOOLEAN)!(MapValue == Iterator->Value));
} else {
PushBool (&StackPtr, (BOOLEAN) (MapValue == Iterator->Value));
}
}
break;
case EFI_IFR_EQ_ID_ID_OP:
//
// If Not - flip the results
//
if (NotOperator) {
Operator = (BOOLEAN)!(MapValue == MapValue2);
} else {
Operator = (BOOLEAN) (MapValue == MapValue2);
}
PushBool (&StackPtr, Operator);
break;
case EFI_IFR_EQ_ID_LIST_OP:
for (Index = 0; Index < Iterator->ListLength; Index++) {
//
// If Not - flip the results
//
if (NotOperator) {
Operator = (BOOLEAN)!(MapValue == Iterator->ValueList[Index]);
} else {
Operator = (BOOLEAN) (MapValue == Iterator->ValueList[Index]);
}
//
// If We are trying to make sure that MapValue != Item[x], keep looking through
// the list to make sure we don't equal any other items
//
if (Operator && NotOperator) {
continue;
}
//
// If MapValue == Item, then we have succeeded (first found is good enough)
//
if (Operator) {
break;
}
}
PushBool (&StackPtr, Operator);
break;
default:
return FALSE;
}
Operator = PopBool (&StackPtr);
Operator2 = PopBool (&StackPtr);
PushBool (&StackPtr, (BOOLEAN) (Operator || Operator2));
break;
case EFI_IFR_NOT_OP:
//
// To check whether Ifr is legacy. Once every boolean expression.
//
if (IsLegacy == 0) {
IsLegacy = PredicateIfrType (Iterator);
}
if (IsLegacy == 0x2) {
PostOrderEvaluate (FileFormTags, Width, &Iterator, &StackPtr);
break;
}
//
// I don't need to set the NotOperator (I know that I have to NOT this in this case
//
Iterator++;
if (Iterator->Operand == EFI_IFR_OR_OP) {
OrOperator = TRUE;
Iterator++;
}
if (Iterator->Operand == EFI_IFR_AND_OP) {
AndOperator = TRUE;
Iterator++;
}
if (Iterator->QuestionId1 != INVALID_OFFSET_VALUE) {
ExtractNvValue (FileFormTags, Iterator->VariableNumber, Width, Iterator->QuestionId1, (VOID **) &MapBuffer);
ExtractNvValue (FileFormTags, Iterator->VariableNumber2, Width, Iterator->QuestionId2, (VOID **) &MapBuffer2);
if (MapBuffer != NULL) {
if (Width == 2) {
MapValue = *MapBuffer;
} else {
MapValue = (UINT8) *MapBuffer;
}
gBS->FreePool (MapBuffer);
}
if (MapBuffer2 != NULL) {
if (Width == 2) {
MapValue2 = *MapBuffer2;
} else {
MapValue2 = (UINT8) *MapBuffer2;
}
gBS->FreePool (MapBuffer2);
}
}
switch (Iterator->Operand) {
case EFI_IFR_EQ_ID_VAL_OP:
Operator = (BOOLEAN)!(MapValue == Iterator->Value);
PushBool (&StackPtr, Operator);
break;
//
// In the case of external variable values, we must read the variable which is
// named by the human readable version of the OpCode->VariableId and the guid of the formset
//
case EFI_IFR_EQ_VAR_VAL_OP:
UnicodeValueToString (
VariableName,
FALSE,
(UINTN) Iterator->QuestionId1,
(sizeof (VariableName) / sizeof (VariableName[0]))
);
SizeOfVariable = 0;
ExtractRequestedNvMap (FileFormTags, Iterator->VariableNumber, &VariableDefinition);
Status = BooleanVariableWorker (
VariableName,
VariableDefinition,
StackPtr,
&SizeOfVariable,
&VariableData
);
if (!EFI_ERROR (Status)) {
if (SizeOfVariable == 1) {
CopyMem (&MapValue, VariableData, 1);
} else {
CopyMem (&MapValue, VariableData, 2);
}
PushBool (&StackPtr, (BOOLEAN)!(MapValue == Iterator->Value));
}
break;
case EFI_IFR_EQ_ID_ID_OP:
Operator = (BOOLEAN)!(MapValue == MapValue2);
PushBool (&StackPtr, Operator);
break;
case EFI_IFR_EQ_ID_LIST_OP:
for (Index = 0; Index < Iterator->ListLength; Index++) {
Operator = (BOOLEAN)!(MapValue == Iterator->ValueList[Index]);
if (Operator) {
continue;
}
}
PushBool (&StackPtr, Operator);
break;
default:
return FALSE;
}
Operator = PopBool (&StackPtr);
Operator2 = PopBool (&StackPtr);
if (OrOperator) {
PushBool (&StackPtr, (BOOLEAN) (Operator || Operator2));
}
if (AndOperator) {
PushBool (&StackPtr, (BOOLEAN) (Operator && Operator2));
}
if (!OrOperator && !AndOperator) {
PushBool (&StackPtr, Operator);
}
break;
case EFI_IFR_TRUE_OP:
//
// To check whether Ifr is legacy. Once every boolean expression.
//
if (IsLegacy == 0) {
IsLegacy = PredicateIfrType (Iterator);
}
if (IsLegacy == 0x2) {
PostOrderEvaluate (FileFormTags, Width, &Iterator, &StackPtr);
break;
}
break;
case EFI_IFR_FALSE_OP:
//
// To check whether Ifr is legacy. Once every boolean expression.
//
if (IsLegacy == 0) {
IsLegacy = PredicateIfrType (Iterator);
}
if (IsLegacy == 0x2) {
PostOrderEvaluate (FileFormTags, Width, &Iterator, &StackPtr);
break;
}
break;
case EFI_IFR_END_IF_OP:
Operator = PopBool (&StackPtr);
//
// If there is an error, return, otherwise keep looking - there might
// be another test that causes an error
//
if (Operator) {
if (Complex && CosmeticConsistency) {
return EFI_SUCCESS;
} else {
return Operator;
}
} else {
//
// If not doing a global consistency check, the endif is the REAL terminator of this operation
// This is used for grayout/suppress operations. InconsistentIf is a global operation so the EndIf is
// not the end-all be-all of terminators.
//
if (!Complex) {
return Operator;
}
break;
}
default:
//
// Must have hit a non-consistency related op-code after a suppress/grayout
//
if (ArtificialEnd) {
ArtificialEnd = FALSE;
Operator = PopBool (&StackPtr);
return Operator;
}
return FALSE;
}
Iterator++;
}
return FALSE;
}