| /*++ | |
| Copyright (c) 2006 - 2007, 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 | |
| // | |
| FreePool (mBooleanEvaluationStack); | |
| } | |
| mBooleanEvaluationStack = NewStack; | |
| mBooleanEvaluationStackEnd = NewStack + StackSizeInBoolean; | |
| } | |
| STATIC | |
| 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; | |
| } | |
| STATIC | |
| 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 | |
| // | |
| 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; | |
| } | |
| STATIC | |
| 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); | |
| } | |
| STATIC | |
| 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; | |
| } | |
| STATIC | |
| 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; | |
| } | |
| STATIC | |
| 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[MAXIMUM_VALUE_CHARACTERS]; | |
| 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; | |
| } | |
| FreePool (MapBuffer); | |
| } | |
| if (MapBuffer2 != NULL) { | |
| if (Width == 2) { | |
| MapValue2 = *MapBuffer2; | |
| } else { | |
| MapValue2 = (UINT8) *MapBuffer2; | |
| } | |
| FreePool (MapBuffer2); | |
| } | |
| } | |
| switch ((*PIterator)->Operand) { | |
| case EFI_IFR_EQ_VAR_VAL_OP: | |
| UnicodeValueToString ( | |
| VariableName, | |
| FALSE, | |
| (UINTN) (*PIterator)->QuestionId1, | |
| (sizeof (VariableName) / sizeof (VariableName[0])) - 1 | |
| ); | |
| 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, (BOOLEAN) (!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[MAXIMUM_VALUE_CHARACTERS]; | |
| 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; | |
| } | |
| FreePool (MapBuffer); | |
| } | |
| if (MapBuffer2 != NULL) { | |
| if (Width == 2) { | |
| MapValue2 = *MapBuffer2; | |
| } else { | |
| MapValue2 = (UINT8) *MapBuffer2; | |
| } | |
| 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])) - 1 | |
| ); | |
| 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; | |
| } | |
| FreePool (MapBuffer); | |
| } | |
| if (MapBuffer2 != NULL) { | |
| if (Width == 2) { | |
| MapValue2 = *MapBuffer2; | |
| } else { | |
| MapValue2 = (UINT8) *MapBuffer2; | |
| } | |
| 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])) - 1 | |
| ); | |
| 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; | |
| } | |
| FreePool (MapBuffer); | |
| } | |
| if (MapBuffer2 != NULL) { | |
| if (Width == 2) { | |
| MapValue2 = *MapBuffer2; | |
| } else { | |
| MapValue2 = (UINT8) *MapBuffer2; | |
| } | |
| 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])) - 1 | |
| ); | |
| 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; | |
| } | |
| FreePool (MapBuffer); | |
| } | |
| if (MapBuffer2 != NULL) { | |
| if (Width == 2) { | |
| MapValue2 = *MapBuffer2; | |
| } else { | |
| MapValue2 = (UINT8) *MapBuffer2; | |
| } | |
| 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])) - 1 | |
| ); | |
| 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; | |
| } | |
| goto Done; | |
| } | |
| Iterator++; | |
| } | |
| Done: | |
| return FALSE; | |
| } |