From 31bb486c913795c8b67d1c4dbaae2bdec4943fc9 Mon Sep 17 00:00:00 2001 From: raywu Date: Thu, 13 Sep 2018 16:11:56 +0800 Subject: SLP1.0 / SLP2.0 / Default Password / Logo / Fix Boot Order --- EDK/MiniSetup/uefi2.1/Expression.c | 2861 ++++++++++++++++++++++++++++++++++++ 1 file changed, 2861 insertions(+) create mode 100644 EDK/MiniSetup/uefi2.1/Expression.c (limited to 'EDK/MiniSetup/uefi2.1/Expression.c') diff --git a/EDK/MiniSetup/uefi2.1/Expression.c b/EDK/MiniSetup/uefi2.1/Expression.c new file mode 100644 index 0000000..f45de77 --- /dev/null +++ b/EDK/MiniSetup/uefi2.1/Expression.c @@ -0,0 +1,2861 @@ +//*****************************************************************// +//*****************************************************************// +//*****************************************************************// +//** **// +//** (C)Copyright 2011, American Megatrends, Inc. **// +//** **// +//** All Rights Reserved. **// +//** **// +//** 5555 Oakbrook Pkwy, Building 200,Norcross, Georgia 30093 **// +//** **// +//** Phone (770)-246-8600 **// +//** **// +//*****************************************************************// +//*****************************************************************// +//*****************************************************************// +// $Archive: /Alaska/SOURCE/Modules/AMITSE2_0/AMITSE/Uefi2.1/Expression.c $ +// +// $Author: Arunsb $ +// +// $Revision: 18 $ +// +// $Date: 6/10/13 12:06p $ +// +//*****************************************************************// +//*****************************************************************// +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/AMITSE2_0/AMITSE/Uefi2.1/Expression.c $ +// +// 18 6/10/13 12:06p Arunsb +// EIP122907. Support for pushthis condition in inconsistent and +// nosubmitif +// +// 17 4/17/13 12:29p Arunsb +// [TAG] EIP111063 +// [Category] Improvement +// [Description] Support for EFI_IFR_QUESTION_REF3_2 and +// EFI_IFR_QUESTION_REF3_3 opcodes +// [Files] Expression.c +// +// 16 4/02/13 8:05a Arunsb +// [TAG] EIP113919, EIP114842 +// [Category] Improvement +// [Description] Provide support for EFI_IFR_WRITE, EFI_IFR_READ, +// EFI_IFR_GET, EFI_IFR_SET and EFI_IFR_MAP_OP. +// [Files] Setupdata.h, ctrlcond.c, expression.c, hii.c and parse.c +// +// 15 10/18/12 6:04a Arunsb +// Updated for 2.16.1235 QA submission +// +// 12 10/10/12 12:41p Arunsb +// Synched the source for v2.16.1232, backup with Aptio +// +// 14 5/29/12 4:44a Arunsb +// [TAG] EIP91109 +// [Category] Improvement +// [Description] Sync the Aptio IV source for AptioV +// +// 13 12/01/11 1:35a Premkumara +// [TAG] EIP73236 +// [Category] Improvement +// [Description] Large amounts of allocated memory are not freed +// [Files] Expression.c, PopupEdit.c, Popup.c, MessageBox.c, Menu.c, +// Memo.c, +// +// 12 11/28/11 2:08a Premkumara +// [TAG] EIP75384 +// [Category] Improvement +// [Description] Suppress the warnings from static code analyzer +// [Files] UefiWapper.c, Hii.c, Expression.c, CtrlCond.c, PopupSel.c, +// Minisetupext.c, Menu.c, Date.c, Ezport\Stylecommon.c, +// EzportPlus\StyleCommon.c, +// +// 11 6/20/11 10:36a Rajashakerg +// [TAG] EIP56355 +// [Category] Improvement +// [Description] TSE: Support for EFI_IFR_VERSION opcode +// [Files] Expression.c +// +// 10 3/18/11 9:41a Rajashakerg +// [TAG] EIP56355 +// [Category] Improvement +// [Description] TSE: Support for EFI_IFR_VERSION opcode +// [Files] Expression.c +// +// 9 2/03/11 8:19p Madhans +// [TAG] - EIP 50956 +// [Category]- defect +// [Severity]- Mordarate +// [Symptom]- If we leave the Setup page for 2 or more days. The system +// may hang/Crash. +// [Rootcause] - Memory leaks +// [Solution]- Memeory freed. +// [Files] - ctrlcond.c, memo.c and expression.c +// +// 8 12/02/10 2:38p Madhans +// [TAG] - EIP 48169 +// [Category]- Enhancement +// [Severity]- Mordarate +// [Symptom]- Code Cleanup and Compiler Warning need to resolved. +// [Rootcause] Warnings reported when we build AMI higher Warning level. +// [Solution]- 1. Fix the warnings and do the code cleanup. +// 2. Introduce proper checks. +// 3. change the popupSel.c to not change the Option/variable +// cache to default or first option +// when the variable cache is not matching with any of +// option. +// [Files] - commonoem.c bbs.c boot.c hiistring.c resource.c +// popuppassword.c popupsel.c +// expression.c hii.c parse.c +// +// 8 8/18/10 5:58p Mallikarjunanv +// EIP-42300: Handled dataWidth to solve the hanging issue with respect to +// password updates +// +// 7 7/07/10 7:45p Madhans +// Changes to Support Adding Conditions to Suppress or Grayout the Special +// controls. +// +// 6 3/11/10 5:41p Madhans +// Coding Standards Update +// +//************************************************************************* +// +// +// Name: Expression.C +// +// Description: Expression evaluation. +// +// +//************************************************************************* + +//--------------------------------------------------------------------------- +#include "Minisetup.h" +#include "TseUefiHii.h" + +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// +// In Aptio UnicodeCollation2 protocol is supported in the same file as +// UnicodeCollation Protocol depending on EFI_SPECIFICATION_VERSION +// +#ifndef TSE_FOR_APTIO_4_50 +#include EFI_PROTOCOL_DEFINITION(UnicodeCollation2) +#else +#if TSE_USE_EDK_LIBRARY +#include EFI_PROTOCOL_DEFINITION(UnicodeCollation2) +#else +#include EFI_PROTOCOL_DEFINITION(UnicodeCollation) +#endif +#endif +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +#define EXPRESSION_STACK_SIZE_INCREMENT 100 +#define NewString(a, b) HiiAddString(b, a) +#define GetToken(a,b) HiiGetString(b, a) +//--------------------------------------------------------------------------- + +// +// Global stack used to evaluate boolean expresions +// +EFI_HII_VALUE *mOpCodeScopeStack = NULL; +EFI_HII_VALUE *mOpCodeScopeStackEnd = NULL; +EFI_HII_VALUE *mOpCodeScopeStackPointer = NULL; + +EFI_HII_VALUE *mExpressionEvaluationStack = NULL; +EFI_HII_VALUE *mExpressionEvaluationStackEnd = NULL; +EFI_HII_VALUE *mExpressionEvaluationStackPointer = NULL; + +CHAR16 *gEmptyString = L""; +VOID *gInconsistCondPtr = NULL; +// +// Unicode collation protocol interface +// +EFI_UNICODE_COLLATION2_PROTOCOL *mUnicodeCollation = NULL; + +extern EFI_STATUS GetStringFromDevPath(EFI_DEVICE_PATH_PROTOCOL *DevPath, CHAR16 **DevPathStr); +extern EFI_STATUS GetDevPathFromHandle(EFI_HII_HANDLE HiiHandle, EFI_DEVICE_PATH_PROTOCOL **DevicePath); + +// +//---------------------------------------------------------------------------- +// Procedure: GrowStack +// +// Description: Grow size of the stack +// +// Parameter: Stack - On input: old stack; On output: new stack +// StackPtr - On input: old stack pointer; On output: new stack pointer +// StackPtr - On input: old stack end; On output: new stack end +// +// Return value: EFI_SUCCESS - Grow stack success. +// EFI_OUT_OF_RESOURCES - No enough memory for stack space. +//---------------------------------------------------------------------------- +// + +STATIC +EFI_STATUS +GrowStack ( + IN OUT EFI_HII_VALUE **Stack, + IN OUT EFI_HII_VALUE **StackPtr, + IN OUT EFI_HII_VALUE **StackEnd + ) +{ + UINTN Size; + EFI_HII_VALUE *NewStack; + + Size = EXPRESSION_STACK_SIZE_INCREMENT; + if (*StackPtr != NULL) { + Size = Size + (*StackEnd - *Stack); + } + + NewStack = EfiLibAllocatePool (Size * sizeof (EFI_HII_VALUE)); + if (NewStack == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + if (*StackPtr != NULL) { + // + // Copy from Old Stack to the New Stack + // + EfiCopyMem ( + NewStack, + *Stack, + (*StackEnd - *Stack) * sizeof (EFI_HII_VALUE) + ); + + // + // Free The Old Stack + // + gBS->FreePool (*Stack); + } + + // + // Make the Stack pointer point to the old data in the new stack + // + *StackPtr = NewStack + (*StackPtr - *Stack); + *Stack = NewStack; + *StackEnd = NewStack + Size; + + return EFI_SUCCESS; +} + +// +//---------------------------------------------------------------------------- +// Procedure: PushStack +// +// Description: Push an element onto the Boolean Stack +// +// Parameter: Stack - On input: old stack; On output: new stack +// StackPtr - On input: old stack pointer; On output: new stack pointer +// StackPtr - On input: old stack end; On output: new stack end +// Data - Data to push. +// +// Return value: EFI_SUCCESS - Push stack success. +//---------------------------------------------------------------------------- +// +EFI_STATUS +PushStack ( + IN OUT EFI_HII_VALUE **Stack, + IN OUT EFI_HII_VALUE **StackPtr, + IN OUT EFI_HII_VALUE **StackEnd, + IN EFI_HII_VALUE *Data + ) +{ + EFI_STATUS Status; + + // + // Check for a stack overflow condition + // + if (*StackPtr >= *StackEnd) { + // + // Grow the stack + // + Status = GrowStack (Stack, StackPtr, StackEnd); + if (EFI_ERROR (Status)) { + return Status; + } + } + + // + // Push the item onto the stack + // + EfiCopyMem (*StackPtr, Data, sizeof (EFI_HII_VALUE)); + *StackPtr = *StackPtr + 1; + + return EFI_SUCCESS; +} + +// +//---------------------------------------------------------------------------- +// Procedure: PopStack +// +// Description: Pop an element from the stack. +// +// Parameter: Stack - On input: old stack; On output: new stack +// StackPtr - On input: old stack pointer; On output: new stack pointer +// StackPtr - On input: old stack end; On output: new stack end +// Data - Data to pop. +// +// Return value: EFI_SUCCESS - The value was popped onto the stack. +// EFI_ACCESS_DENIED - The pop operation underflowed the stack +//---------------------------------------------------------------------------- +// +EFI_STATUS +PopStack ( + IN OUT EFI_HII_VALUE **Stack, + IN OUT EFI_HII_VALUE **StackPtr, + IN OUT EFI_HII_VALUE **StackEnd, + OUT EFI_HII_VALUE *Data + ) +{ + // + // Check for a stack underflow condition + // + if (*StackPtr == *Stack) { + return EFI_ACCESS_DENIED; + } + + // + // Pop the item off the stack + // + *StackPtr = *StackPtr - 1; + EfiCopyMem (Data, *StackPtr, sizeof (EFI_HII_VALUE)); + return EFI_SUCCESS; +} + +// +//---------------------------------------------------------------------------- +// Procedure: ResetScopeStack +// +// Description: Reset stack pointer to begin of the stack. +// +// Parameter: None. +// +// Return value: None. +//---------------------------------------------------------------------------- +// +VOID +ResetScopeStack ( + VOID + ) +{ + mOpCodeScopeStackPointer = mOpCodeScopeStack; +} + +// +//---------------------------------------------------------------------------- +// Procedure: PushScope +// +// Description: Push an Operand onto the Stack +// +// Parameter: Operand to push. +// +// Return value: EFI_SUCCESS - The value was pushed onto the stack. +// EFI_OUT_OF_RESOURCES - There is not enough system memory to grow the stack. +// +//---------------------------------------------------------------------------- +// +EFI_STATUS +PushScope ( + IN UINT8 Operand + ) +{ + EFI_HII_VALUE Data; + + Data.Type = EFI_IFR_TYPE_NUM_SIZE_8; + Data.Value.u8 = Operand; + + return PushStack ( + &mOpCodeScopeStack, + &mOpCodeScopeStackPointer, + &mOpCodeScopeStackEnd, + &Data + ); +} + +// +//---------------------------------------------------------------------------- +// Procedure: PopScope +// +// Description: Pop an Operand from the Stack +// +// Parameter: Operand to pop. +// +// Return value: EFI_SUCCESS - The value was pushed onto the stack. +// EFI_OUT_OF_RESOURCES - There is not enough system memory to +// grow the stack. +// +//---------------------------------------------------------------------------- +// +EFI_STATUS +PopScope ( + OUT UINT8 *Operand + ) +{ + EFI_STATUS Status; + EFI_HII_VALUE Data; + + Status = PopStack ( + &mOpCodeScopeStack, + &mOpCodeScopeStackPointer, + &mOpCodeScopeStackEnd, + &Data + ); + + *Operand = Data.Value.u8; + + return Status; +} + +// +//---------------------------------------------------------------------------- +// Procedure: ResetExpressionStack +// +// Description: Reset stack pointer to begin of the stack. +// +// Parameter: None. +// +// Return value: None +// +//---------------------------------------------------------------------------- +// +VOID +ResetExpressionStack ( + VOID + ) +{ + mExpressionEvaluationStackPointer = mExpressionEvaluationStack; +} + +// +//---------------------------------------------------------------------------- +// Procedure: PushExpression +// +// Description: Push an Expression value onto the Stack +// +// Parameter: Value - Expression value to push. +// +// Return value: EFI_SUCCESS - The value was pushed onto the stack. +// EFI_OUT_OF_RESOURCES - There is not enough system memory to grow the stack. +// +//---------------------------------------------------------------------------- +// +EFI_STATUS +PushExpression ( + IN EFI_HII_VALUE *Value + ) +{ + return PushStack ( + &mExpressionEvaluationStack, + &mExpressionEvaluationStackPointer, + &mExpressionEvaluationStackEnd, + Value + ); +} + +// +//---------------------------------------------------------------------------- +// Procedure: PopExpression +// +// Description: Pop an Expression value from the Stack +// +// Parameter: Value - Expression value to pop. +// +// Return value: EFI_SUCCESS - The value was popped onto the stack. +// EFI_OUT_OF_RESOURCES - The pop operation underflowed the stack +// +//---------------------------------------------------------------------------- +// +EFI_STATUS +PopExpression ( + OUT EFI_HII_VALUE *Value + ) +{ + return PopStack ( + &mExpressionEvaluationStack, + &mExpressionEvaluationStackPointer, + &mExpressionEvaluationStackEnd, + Value + ); +} + +/* +FORM_BROWSER_FORM * +IdToForm ( + IN FORM_BROWSER_FORMSET *FormSet, + IN UINT16 FormId +) +/*++ + +Routine Description: + Get Form given its FormId. + +Arguments: + FormSet - The formset which contains this form. + FormId - Id of this form. + +Returns: + Pointer - The form. + NULL - Specified Form is not found in the formset. + +--* / +{ + EFI_LIST_ENTRY *Link; + FORM_BROWSER_FORM *Form; + + Link = GetFirstNode (&FormSet->FormListHead); + while (!IsNull (&FormSet->FormListHead, Link)) { + Form = FORM_BROWSER_FORM_FROM_LINK (Link); + + if (Form->FormId == FormId) { + return Form; + } + + Link = GetNextNode (&FormSet->FormListHead, Link); + } + + return NULL; +} + +FORM_BROWSER_STATEMENT * +IdToQuestion2 ( + IN FORM_BROWSER_FORM *Form, + IN UINT16 QuestionId + ) +/*++ + +Routine Description: + Search a Question in Form scope using its QuestionId. + +Arguments: + Form - The form which contains this Question. + QuestionId - Id of this Question. + +Returns: + Pointer - The Question. + NULL - Specified Question not found in the form. + +--* / +{ + EFI_LIST_ENTRY *Link; + FORM_BROWSER_STATEMENT *Question; + + if (QuestionId == 0) { + // + // The value of zero is reserved + // + return NULL; + } + + Link = GetFirstNode (&Form->StatementListHead); + while (!IsNull (&Form->StatementListHead, Link)) { + Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link); + + if (Question->QuestionId == QuestionId) { + return Question; + } + + Link = GetNextNode (&Form->StatementListHead, Link); + } + + return NULL; +} + +FORM_BROWSER_STATEMENT * +IdToQuestion ( + IN FORM_BROWSER_FORMSET *FormSet, + IN FORM_BROWSER_FORM *Form, + IN UINT16 QuestionId + ) +/*++ + +Routine Description: + Search a Question in Formset scope using its QuestionId. + +Arguments: + FormSet - The formset which contains this form. + Form - The form which contains this Question. + QuestionId - Id of this Question. + +Returns: + Pointer - The Question. + NULL - Specified Question not found in the form. + +--* / +{ + EFI_LIST_ENTRY *Link; + FORM_BROWSER_STATEMENT *Question; + + // + // Search in the form scope first + // + Question = IdToQuestion2 (Form, QuestionId); + if (Question != NULL) { + return Question; + } + + // + // Search in the formset scope + // + Link = GetFirstNode (&FormSet->FormListHead); + while (!IsNull (&FormSet->FormListHead, Link)) { + Form = FORM_BROWSER_FORM_FROM_LINK (Link); + + Question = IdToQuestion2 (Form, QuestionId); + if (Question != NULL) { + return Question; + } + + Link = GetNextNode (&FormSet->FormListHead, Link); + } + + return NULL; +} + +FORM_EXPRESSION * +RuleIdToExpression ( + IN FORM_BROWSER_FORM *Form, + IN UINT8 RuleId + ) +/*++ + +Routine Description: + Get Expression given its RuleId. + +Arguments: + Form - The form which contains this Expression. + RuleId - Id of this Expression. + +Returns: + Pointer - The Expression. + NULL - Specified Expression not found in the form. + +--* / +{ + EFI_LIST_ENTRY *Link; + FORM_EXPRESSION *Expression; + + Link = GetFirstNode (&Form->ExpressionListHead); + while (!IsNull (&Form->ExpressionListHead, Link)) { + Expression = FORM_EXPRESSION_FROM_LINK (Link); + + if (Expression->Type == EFI_HII_EXPRESSION_RULE && Expression->RuleId == RuleId) { + return Expression; + } + + Link = GetNextNode (&Form->ExpressionListHead, Link); + } + + return NULL; +} +*/ + +// +//---------------------------------------------------------------------------- +// Procedure: InitializeUnicodeCollationProtocol +// +// Description: Locate the Unicode Collation Protocol interface for later use. +// +// Parameter: None +// +// Return value: EFI_SUCCESS - Protocol interface initialize success. +// Other - Protocol interface initialize failed. +// +//---------------------------------------------------------------------------- +// + +EFI_STATUS +InitializeUnicodeCollationProtocol ( + VOID + ) +{ + EFI_STATUS Status; + + if (mUnicodeCollation != NULL) { + return EFI_SUCCESS; + } + + // + // BUGBUG: Proper impelmentation is to locate all Unicode Collation Protocol + // instances first and then select one which support English language. + // Current implementation just pick the first instance. + // + Status = gBS->LocateProtocol ( + &gEfiUnicodeCollation2ProtocolGuid, + NULL, + &mUnicodeCollation + ); + return Status; +} + +// +//---------------------------------------------------------------------------- +// Procedure: IfrStrToUpper +// +// Description:function to conver the lower case string to upper +// +// Parameter: +// +// Return value: None +// +//---------------------------------------------------------------------------- +// +VOID +IfrStrToUpper ( + CHAR16 *String + ) +{ + while (*String != 0) { + if ((*String >= 'a') && (*String <= 'z')) { + *String = (*String) & ((UINT16) ~0x20); + } + String++; + } +} + +// +//---------------------------------------------------------------------------- +// Procedure: IfrToString +// +// Description: Evaluate opcode EFI_IFR_TO_STRING. +// +// Parameter: FormSet - Formset which contains this opcode. +// Format - String format in EFI_IFR_TO_STRING. +// Result - Evaluation result for this opcode. +// +// Return value: EFI_SUCCESS - Opcode evaluation success. +// Other - Opcode evaluation failed. +//---------------------------------------------------------------------------- +// +EFI_STATUS +IfrToString ( + IN EFI_HII_HANDLE *HiiHandle, + IN UINT8 Format, + OUT EFI_HII_VALUE *Result + ) +{ + EFI_STATUS Status; + EFI_HII_VALUE Value; + CHAR16 *String; + CHAR16 *PrintFormat; + CHAR16 Buffer[CHARACTER_NUMBER_FOR_VALUE]; + UINTN BufferSize; + + Status = PopExpression (&Value); + if (EFI_ERROR (Status)) { + return Status; + } + + switch (Value.Type) { + case EFI_IFR_TYPE_NUM_SIZE_8: + case EFI_IFR_TYPE_NUM_SIZE_16: + case EFI_IFR_TYPE_NUM_SIZE_32: + case EFI_IFR_TYPE_NUM_SIZE_64: + BufferSize = CHARACTER_NUMBER_FOR_VALUE * sizeof (CHAR16); + switch (Format) { + case EFI_IFR_STRING_UNSIGNED_DEC: + case EFI_IFR_STRING_SIGNED_DEC: + PrintFormat = L"%ld"; + break; + + case EFI_IFR_STRING_LOWERCASE_HEX: + PrintFormat = L"%lx"; + break; + + case EFI_IFR_STRING_UPPERCASE_HEX: + PrintFormat = L"%lX"; + break; + + default: + return EFI_UNSUPPORTED; + } + SPrint (Buffer, BufferSize, PrintFormat, Value.Value.u64); + String = Buffer; + break; + + case EFI_IFR_TYPE_STRING: + EfiCopyMem (Result, &Value, sizeof (EFI_HII_VALUE)); + return EFI_SUCCESS; + + case EFI_IFR_TYPE_BOOLEAN: + String = (Value.Value.b) ? L"True" : L"False"; + break; + + default: + return EFI_UNSUPPORTED; + } + + Result->Type = EFI_IFR_TYPE_STRING; + Result->Value.string = NewString (String, HiiHandle); + return EFI_SUCCESS; +} + +// +//---------------------------------------------------------------------------- +// Procedure: IfrToUint +// +// Description: Evaluate opcode EFI_IFR_TO_UINT. +// +// Parameter: FormSet - Formset which contains this opcode. +// Result - Evaluation result for this opcode. +// +// Return value: EFI_SUCCESS - Opcode evaluation success. +// Other - Opcode evaluation failed. +//---------------------------------------------------------------------------- +// +EFI_STATUS +IfrToUint ( + IN EFI_HII_HANDLE *HiiHandle, + OUT EFI_HII_VALUE *Result + ) +{ + EFI_STATUS Status; + EFI_HII_VALUE Value; + CHAR16 *String; + CHAR16 *StringPtr; + UINTN BufferSize; + + Status = PopExpression (&Value); + if (EFI_ERROR (Status)) { + return Status; + } + + if (Value.Type >= EFI_IFR_TYPE_OTHER) { + return EFI_UNSUPPORTED; + } + + Status = EFI_SUCCESS; + if (Value.Type == EFI_IFR_TYPE_STRING) { + String = GetToken (Value.Value.string, HiiHandle); + if (String == NULL) { + return EFI_NOT_FOUND; + } + + IfrStrToUpper (String); + StringPtr = EfiStrStr (String, L"0X"); + if (StringPtr != NULL) { + // + // Hex string + // + BufferSize = sizeof (UINT64); + Status = HexStringToBuf ((UINT8 *) &Result->Value.u64, &BufferSize, StringPtr + 2, NULL); + } else { + // + // BUGBUG: Need handle decimal string + // + } + gBS->FreePool (String); + } else { + EfiCopyMem (Result, &Value, sizeof (EFI_HII_VALUE)); + } + + Result->Type = EFI_IFR_TYPE_NUM_SIZE_64; + return Status; +} + +// +//---------------------------------------------------------------------------- +// Procedure: IfrCatenate +// +// Description: Evaluate opcode EFI_IFR_TO_UINT. +// +// Parameter: FormSet - Formset which contains this opcode. +// Result - Evaluation result for this opcode. +// +// Return value: EFI_SUCCESS - Opcode evaluation success. +// Other - Opcode evaluation failed. +//---------------------------------------------------------------------------- +// +EFI_STATUS +IfrCatenate ( + IN EFI_HII_HANDLE *HiiHandle, + OUT EFI_HII_VALUE *Result + ) +{ + EFI_STATUS Status; + EFI_HII_VALUE Value; + CHAR16 *String[2]; + UINTN Index; + CHAR16 *StringPtr; + + // + // String[0] - The second string + // String[1] - The first string + // + String[0] = NULL; + String[1] = NULL; + StringPtr = NULL; + Status = EFI_SUCCESS; + + for (Index = 0; Index < 2; Index++) { + Status = PopExpression (&Value); + if (EFI_ERROR (Status)) { + goto Done; + } + + if (Value.Type != EFI_IFR_TYPE_STRING) { + Status = EFI_UNSUPPORTED; + goto Done; + } + + String[Index] = GetToken (Value.Value.string, HiiHandle); + if (String== NULL) { + Status = EFI_NOT_FOUND; + goto Done; + } + } + + StringPtr= EfiLibAllocatePool (EfiStrSize (String[1]) + EfiStrSize (String[0])); + ASSERT (StringPtr != NULL); + EfiStrCpy (StringPtr, String[1]); + EfiStrCat (StringPtr, String[0]); + + Result->Type = EFI_IFR_TYPE_STRING; + Result->Value.string = NewString (StringPtr, HiiHandle); + +Done: + EfiLibSafeFreePool (String[0]); + EfiLibSafeFreePool (String[1]); + EfiLibSafeFreePool (StringPtr); + + return Status; +} + +// +//---------------------------------------------------------------------------- +// Procedure: IfrMatch +// +// Description: Evaluate opcode EFI_IFR_MATCH. +// +// Parameter: FormSet - Formset which contains this opcode. +// Result - Evaluation result for this opcode. +// +// Return value: EFI_SUCCESS - Opcode evaluation success. +// Other - Opcode evaluation failed. +//---------------------------------------------------------------------------- +// +EFI_STATUS +IfrMatch ( + IN EFI_HII_HANDLE *HiiHandle, + OUT EFI_HII_VALUE *Result + ) +{ + EFI_STATUS Status; + EFI_HII_VALUE Value; + CHAR16 *String[2]; + UINTN Index; + + // + // String[0] - The string to search + // String[1] - pattern + // + String[0] = NULL; + String[1] = NULL; + Status = EFI_SUCCESS; + for (Index = 0; Index < 2; Index++) { + Status = PopExpression (&Value); + if (EFI_ERROR (Status)) { + goto Done; + } + + if (Value.Type != EFI_IFR_TYPE_STRING) { + Status = EFI_UNSUPPORTED; + goto Done; + } + + String[Index] = GetToken (Value.Value.string, HiiHandle); + if (String== NULL) { + Status = EFI_NOT_FOUND; + goto Done; + } + } + + Result->Type = EFI_IFR_TYPE_BOOLEAN; + Result->Value.b = mUnicodeCollation->MetaiMatch (mUnicodeCollation, String[0], String[1]); + +Done: + EfiLibSafeFreePool (String[0]); + EfiLibSafeFreePool (String[1]); + + return Status; +} + +// +//---------------------------------------------------------------------------- +// Procedure: IfrFind +// +// Description: Evaluate opcode EFI_IFR_FIND. +// +// Parameter: FormSet - Formset which contains this opcode. +// Format - Case sensitive or insensitive. +// Result - Evaluation result for this opcode. +// +// Return value: EFI_SUCCESS - Opcode evaluation success. +// Other - Opcode evaluation failed. +//---------------------------------------------------------------------------- +// +EFI_STATUS +IfrFind ( + IN EFI_HII_HANDLE *HiiHandle, + IN UINT8 Format, + OUT EFI_HII_VALUE *Result + ) +{ + EFI_STATUS Status; + EFI_HII_VALUE Value; + CHAR16 *String[2]; + UINTN Base; + CHAR16 *StringPtr; + UINTN Index; + + if (Format > EFI_IFR_FF_CASE_INSENSITIVE) { + return EFI_UNSUPPORTED; + } + + Status = PopExpression (&Value); + if (EFI_ERROR (Status)) { + return Status; + } + if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) { + return EFI_UNSUPPORTED; + } + Base = (UINTN) Value.Value.u64; + + // + // String[0] - sub-string + // String[1] - The string to search + // + String[0] = NULL; + String[1] = NULL; + for (Index = 0; Index < 2; Index++) { + Status = PopExpression (&Value); + if (EFI_ERROR (Status)) { + goto Done; + } + + if (Value.Type != EFI_IFR_TYPE_STRING) { + Status = EFI_UNSUPPORTED; + goto Done; + } + + String[Index] = GetToken (Value.Value.string, HiiHandle); + if (String== NULL) { + Status = EFI_NOT_FOUND; + goto Done; + } + + if (Format == EFI_IFR_FF_CASE_INSENSITIVE) { + // + // Case insensitive, convert both string to upper case + // + IfrStrToUpper (String[Index]); + } + } + + Result->Type = EFI_IFR_TYPE_NUM_SIZE_64; + if (Base >= EfiStrLen (String[1])) { + Result->Value.u64 = 0xFFFFFFFFFFFFFFFF; + } else { + StringPtr = EfiStrStr (String[1] + Base, String[0]); + Result->Value.u64 = (StringPtr == NULL) ? 0xFFFFFFFFFFFFFFFF : (StringPtr - String[1]); + } + +Done: + EfiLibSafeFreePool (String[0]); + EfiLibSafeFreePool (String[1]); + + return Status; +} + +// +//---------------------------------------------------------------------------- +// Procedure: IfrMid +// +// Description: Evaluate opcode EFI_IFR_MID. +// +// Parameter: FormSet - Formset which contains this opcode. +// Result - Evaluation result for this opcode. +// +// Return value: EFI_SUCCESS - Opcode evaluation success. +// Other - Opcode evaluation failed. +//---------------------------------------------------------------------------- +// +EFI_STATUS +IfrMid ( + IN EFI_HII_HANDLE *HiiHandle, + OUT EFI_HII_VALUE *Result + ) +{ + EFI_STATUS Status; + EFI_HII_VALUE Value; + CHAR16 *String; + UINTN Base; + UINTN Length; + CHAR16 *SubString; + + Status = PopExpression (&Value); + if (EFI_ERROR (Status)) { + return Status; + } + if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) { + return EFI_UNSUPPORTED; + } + Length = (UINTN) Value.Value.u64; + + Status = PopExpression (&Value); + if (EFI_ERROR (Status)) { + return Status; + } + if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) { + return EFI_UNSUPPORTED; + } + Base = (UINTN) Value.Value.u64; + + Status = PopExpression (&Value); + if (EFI_ERROR (Status)) { + return Status; + } + if (Value.Type != EFI_IFR_TYPE_STRING) { + return EFI_UNSUPPORTED; + } + String = GetToken (Value.Value.string, HiiHandle); + if (String == NULL) { + return EFI_NOT_FOUND; + } + + if (Length == 0 || Base >= EfiStrLen (String)) { + SubString = gEmptyString; + } else { + SubString = String + Base; + if ((Base + Length) < EfiStrLen (String)) { + SubString[Length] = L'\0'; + } + } + + Result->Type = EFI_IFR_TYPE_STRING; + Result->Value.string = NewString (SubString, HiiHandle); + + gBS->FreePool (String); + + return Status; +} + +// +//---------------------------------------------------------------------------- +// Procedure: IfrToken +// +// Description: Evaluate opcode EFI_IFR_TOKEN. +// +// Parameter: FormSet - Formset which contains this opcode. +// Result - Evaluation result for this opcode. +// +// Return value: EFI_SUCCESS - Opcode evaluation success. +// Other - Opcode evaluation failed. +//---------------------------------------------------------------------------- +// +EFI_STATUS +IfrToken ( + IN EFI_HII_HANDLE *HiiHandle, + OUT EFI_HII_VALUE *Result + ) +{ + EFI_STATUS Status; + EFI_HII_VALUE Value; + CHAR16 *String[2]; + UINTN Count; + CHAR16 *Delimiter; + CHAR16 *SubString; + CHAR16 *StringPtr; + UINTN Index; + + Status = PopExpression (&Value); + if (EFI_ERROR (Status)) { + return Status; + } + if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) { + return EFI_UNSUPPORTED; + } + Count = (UINTN) Value.Value.u64; + + // + // String[0] - Delimiter + // String[1] - The string to search + // + String[0] = NULL; + String[1] = NULL; + for (Index = 0; Index < 2; Index++) { + Status = PopExpression (&Value); + if (EFI_ERROR (Status)) { + goto Done; + } + + if (Value.Type != EFI_IFR_TYPE_STRING) { + Status = EFI_UNSUPPORTED; + goto Done; + } + + String[Index] = GetToken (Value.Value.string, HiiHandle); + if (String== NULL) { + Status = EFI_NOT_FOUND; + goto Done; + } + } + + Delimiter = String[0]; + SubString = String[1]; + while (Count > 0) { + SubString = EfiStrStr (SubString, Delimiter); + if (SubString != NULL) { + // + // Skip over the delimiter + // + SubString = SubString + EfiStrLen (Delimiter); + } else { + break; + } + Count--; + } + + if (SubString == NULL) { + // + // nth delimited sub-string not found, push an empty string + // + SubString = gEmptyString; + } else { + // + // Put a NULL terminator for nth delimited sub-string + // + StringPtr = EfiStrStr (SubString, Delimiter); + if (StringPtr != NULL) { + *StringPtr = L'\0'; + } + } + + Result->Type = EFI_IFR_TYPE_STRING; + Result->Value.string = NewString (SubString, HiiHandle); + +Done: + EfiLibSafeFreePool (String[0]); + EfiLibSafeFreePool (String[1]); + + return Status; +} + +// +//---------------------------------------------------------------------------- +// Procedure: IfrSpan +// +// Description: Evaluate opcode EFI_IFR_SPAN. +// +// Parameter: FormSet - Formset which contains this opcode. +// Flags - FIRST_MATCHING or FIRST_NON_MATCHING. +// Result - Evaluation result for this opcode. +// +// Return value: EFI_SUCCESS - Opcode evaluation success. +// Other - Opcode evaluation failed. +//---------------------------------------------------------------------------- +// +EFI_STATUS +IfrSpan ( + IN EFI_HII_HANDLE *HiiHandle, + IN UINT8 Flags, + OUT EFI_HII_VALUE *Result + ) +{ + EFI_STATUS Status; + EFI_HII_VALUE Value; + CHAR16 *String[2]; + CHAR16 *Charset; + UINTN Base; + UINTN Index; + CHAR16 *StringPtr; + BOOLEAN Found; + + Status = PopExpression (&Value); + if (EFI_ERROR (Status)) { + return Status; + } + if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) { + return EFI_UNSUPPORTED; + } + Base = (UINTN) Value.Value.u64; + + // + // String[0] - Charset + // String[1] - The string to search + // + String[0] = NULL; + String[1] = NULL; + for (Index = 0; Index < 2; Index++) { + Status = PopExpression (&Value); + if (EFI_ERROR (Status)) { + goto Done; + } + + if (Value.Type != EFI_IFR_TYPE_STRING) { + Status = EFI_UNSUPPORTED; + goto Done; + } + + String[Index] = GetToken (Value.Value.string, HiiHandle); + if (String== NULL) { + Status = EFI_NOT_FOUND; + goto Done; + } + } + + if (Base >= EfiStrLen (String[1])) { + Status = EFI_UNSUPPORTED; + goto Done; + } + + Found = FALSE; + StringPtr = String[1] + Base; + Charset = String[0]; + while (*StringPtr != 0 && !Found) { + Index = 0; + while (Charset[Index] != 0) { + if (*StringPtr >= Charset[Index] && *StringPtr <= Charset[Index + 1]) { + if (Flags == EFI_IFR_FLAGS_FIRST_MATCHING) { + Found = TRUE; + break; + } + } else { + if (Flags == EFI_IFR_FLAGS_FIRST_NON_MATCHING) { + Found = TRUE; + break; + } + } + // + // Skip characters pair representing low-end of a range and high-end of a range + // + Index += 2; + } + + if (!Found) { + StringPtr++; + } + } + + Result->Type = EFI_IFR_TYPE_NUM_SIZE_64; + Result->Value.u64 = StringPtr - String[1]; + +Done: + EfiLibSafeFreePool (String[0]); + EfiLibSafeFreePool (String[1]); + + return Status; +} + + +// +//---------------------------------------------------------------------------- +// Procedure: ExtendValueToU64 +// +// Description: Zero extend integer/boolean/date/time to UINT64 for comparing. +// +// Parameter: Value - HII Value to be converted. +// +// Return value: None. +//---------------------------------------------------------------------------- +// +VOID +ExtendValueToU64 ( + IN EFI_HII_VALUE *Value + ) +{ + UINT64 Temp; + + Temp = 0; + switch (Value->Type) { + case EFI_IFR_TYPE_NUM_SIZE_8: + Temp = Value->Value.u8; + break; + + case EFI_IFR_TYPE_NUM_SIZE_16: + Temp = Value->Value.u16; + break; + + case EFI_IFR_TYPE_NUM_SIZE_32: + Temp = Value->Value.u32; + break; + + case EFI_IFR_TYPE_BOOLEAN: + Temp = Value->Value.b; + break; + + case EFI_IFR_TYPE_TIME: + Temp = Value->Value.u32 & 0xffffff; + break; + + case EFI_IFR_TYPE_DATE: + Temp = Value->Value.u32; + break; + + default: + return; + } + + Value->Value.u64 = Temp; +} + +// +//---------------------------------------------------------------------------- +// Procedure: CompareHiiValue +// +// Description: Compare two Hii Value +// +// Parameter: Value1 - Expression value to compare on left-hand +// Value2 - Expression value to compare on right-hand +// HiiHandle - Only required for string compare +// +// Return value: EFI_INVALID_PARAMETER - Could not perform comparation on two values +// 0 - Two operators equeal +// < 0 - Value1 is greater than Value2 +// > 0 - Value1 is less than Value2 +//---------------------------------------------------------------------------- +// +INTN +CompareHiiValue ( + IN EFI_HII_VALUE *Value1, + IN EFI_HII_VALUE *Value2, + IN EFI_HII_HANDLE HiiHandle OPTIONAL + ) +{ + INTN Result; + INT64 Temp64; + CHAR16 *Str1; + CHAR16 *Str2; + + if (Value1->Type >= EFI_IFR_TYPE_OTHER || Value2->Type >= EFI_IFR_TYPE_OTHER ) { + return EFI_INVALID_PARAMETER; + } + + if (Value1->Type == EFI_IFR_TYPE_STRING || Value2->Type == EFI_IFR_TYPE_STRING ) { + if (Value1->Type != Value2->Type) { + // + // Both Operator should be type of String + // + return EFI_INVALID_PARAMETER; + } + + if (Value1->Value.string == 0 || Value2->Value.string == 0) { + // + // StringId 0 is reserved + // + return EFI_INVALID_PARAMETER; + } + + if (Value1->Value.string == Value2->Value.string) { + return 0; + } + + Str1 = GetToken (Value1->Value.string, HiiHandle); + if (Str1 == NULL) { + // + // String not found + // + return EFI_INVALID_PARAMETER; + } + + Str2 = GetToken (Value2->Value.string, HiiHandle); + if (Str2 == NULL) { + gBS->FreePool (Str1); + return EFI_INVALID_PARAMETER; + } + + Result = EfiStrCmp (Str1, Str2); + + gBS->FreePool (Str1); + gBS->FreePool (Str2); + + return Result; + } + + // + // Take remain types(integer, boolean, date/time) as integer + // + Temp64 = (INT64) (Value1->Value.u64 - Value2->Value.u64); + if (Temp64 > 0) { + Result = 1; + } else if (Temp64 < 0) { + Result = -1; + } else { + Result = 0; + } + + return Result; +} + +// +//---------------------------------------------------------------------------- +// +// Procedure: _GetRuleControlfromId +// +// Description: +// +// Parameter: UINT8 *IFRData, CONTROL_INFO **RuleControl +// +// Return value: EFI_STATUS +//---------------------------------------------------------------------------- +// +EFI_STATUS _GetRuleControlfromId(UINT16 RuleId, UINT16 PageId, CONTROL_INFO **RuleControl) +{ + EFI_STATUS Status = EFI_SUCCESS; + CONTROL_INFO *controlInfo = NULL; + BOOLEAN found = FALSE; + UINTN control = 0; + + PAGE_INFO *pageInfo = (PAGE_INFO *)((UINTN)gApplicationData + gPages->PageList[PageId]); + if(pageInfo->PageHandle ==0) + { + Status = EFI_NOT_FOUND; + goto DONE; + } + + for(control= 0; (control < pageInfo->PageControls.ControlCount) && (found == FALSE); control++) + { + controlInfo = (CONTROL_INFO*)((UINTN)gControlInfo + pageInfo->PageControls.ControlList[control]); + + + if(RuleId == controlInfo->ControlKey) + { + found = TRUE; + } + } + + if(found) + { + *RuleControl = controlInfo; + } + +DONE: + return Status; +} + +// +//---------------------------------------------------------------------------- +// +// Procedure: checkforpushthispresence +// +// Description: Checks the condition has EFI_IFR_THIS_OP +// +// Parameter: UINT8 * +// +// Return value: TRUE if EFI_IFR_THIS_OP presents else FALSE +//---------------------------------------------------------------------------- +// +BOOLEAN checkforpushthispresence (UINT8 *ControlConditionalPtr) +{ + EFI_IFR_OP_HEADER *opHeader = (EFI_IFR_OP_HEADER*)ControlConditionalPtr; + UINTN inScope = 0; + UINTN i = 0; + + if (opHeader->Scope) + { + do + { + switch (opHeader->OpCode) + { + case EFI_IFR_THIS_OP: + return TRUE; + case EFI_IFR_END_OP: + inScope--; + break; + default: + if(opHeader->Scope) + { + inScope++; + } + } + i += opHeader->Length; + opHeader = (EFI_IFR_OP_HEADER*)(ControlConditionalPtr + i); + }while(inScope); + } + return FALSE; +} + +// +//---------------------------------------------------------------------------------------- +// +// Procedure: GetValueFromParentControl +// +// Description: Gets the value for inconsistent/submitif from its parent control +// +// Parameter: UINT16, UINT16, EFI_HII_VALUE **, PAGE_INFO *, VOID * +// +// Return value: EFI_SUCCESS if value retrieved successfully else some other EFI Status +//----------------------------------------------------------------------------------------- +// +EFI_STATUS _GetValueFromQuestionId (UINT16 QuestionId, UINT16 PageId, EFI_HII_VALUE **Value); +EFI_STATUS GetValueFromParentControl (UINT16 QuestionId, UINT16 PageId, EFI_HII_VALUE **Value, PAGE_INFO *pageInfo, VOID *CtrlCondPtr) +{ + UINT32 Count = 1; + UINTN control = 0; + EFI_STATUS Status = EFI_UNSUPPORTED; + EFI_IFR_OP_HEADER *OpHeader; + EFI_IFR_QUESTION_HEADER *questionHdr = NULL; + CHAR16 *questionValue; + EFI_STRING_ID StrToken = 0; + CONTROL_INFO *controlInfo; + + for (control= 0; control < pageInfo->PageControls.ControlCount; control++) + { + controlInfo = (CONTROL_INFO *)((UINTN)gControlInfo + pageInfo->PageControls.ControlList[control]); //If two submit if present then questionid may be same so comparing conditionalptr also + if ((QuestionId == controlInfo->ControlKey) && ((CONTROL_TYPE_MSGBOX == controlInfo->ControlType) || (NO_SUBMIT_IF == controlInfo->ControlType)) && (CtrlCondPtr == controlInfo->ControlConditionalPtr)) + { + if (checkforpushthispresence (controlInfo->ControlConditionalPtr)) + { + do //Find the parent control. Inconsistent/submit only present inside question + { + controlInfo = (CONTROL_INFO*)((UINT8 *)(gControlInfo) + pageInfo->PageControls.ControlList [control-Count]); + Count ++; + }while ((CONTROL_TYPE_MSGBOX == controlInfo->ControlType) || (NO_SUBMIT_IF == controlInfo->ControlType)); //find parent suppress all the inconsistent/submit present in the control + OpHeader=(EFI_IFR_OP_HEADER *)controlInfo->ControlPtr; + if (EFI_IFR_STRING_OP != OpHeader->OpCode) + { + Status = _GetValueFromQuestionId (controlInfo->ControlKey, PageId, Value); + } + else + { + UINTN dataWidth = UefiGetWidth (controlInfo->ControlPtr); + questionHdr = (EFI_IFR_QUESTION_HEADER*)((UINT8 *)controlInfo->ControlPtr + sizeof(EFI_IFR_OP_HEADER)); + questionValue = EfiLibAllocateZeroPool (dataWidth + sizeof (CHAR16)); //sizeof (CHAR16) is for NULL if maximum characters used. + if (NULL == questionValue) + { + return EFI_OUT_OF_RESOURCES; + } + + // EIP-42300: Updated the dataWidth in comparison to the maximum supported + Status = VarGetValue (controlInfo->ControlVariable, questionHdr->VarStoreInfo.VarOffset, dataWidth, (VOID *)questionValue); + if (!EFI_ERROR(Status)) + { + if (*questionValue != 0) + { + StrToken = HiiAddString (controlInfo->ControlHandle, questionValue); + (*Value)->Value.string = StrToken; + (*Value)->Type = EFI_IFR_TYPE_STRING; + } + else + { + Status = EFI_NOT_STARTED; //If null string then dont compare + } + } + } + } + break; + } + } + return Status; +} + +// +//---------------------------------------------------------------------------- +// +// Procedure: _GetValueFromQuestionId +// +// Description: +// +// Parameter: UINT16 QuestionId, UINT16 PageId, UINT64 *Value +// +// Return value: EFI_STATUS +//---------------------------------------------------------------------------- +// +EFI_STATUS _GetValueFromQuestionId(UINT16 QuestionId, UINT16 PageId, EFI_HII_VALUE **Value) +{ + EFI_STATUS Status = EFI_SUCCESS; + EFI_IFR_QUESTION_HEADER *questionHdr = NULL; + BOOLEAN found = FALSE; + UINT32 varId = 0; + UINTN control = 0; + UINT64 questionValue = 0; + + CONTROL_INFO *controlInfo = NULL; + + PAGE_INFO *pageInfo = (PAGE_INFO *)((UINTN)gApplicationData + gPages->PageList[PageId]); + + if(pageInfo->PageHandle ==0) + { + Status = EFI_NOT_FOUND; + goto DONE; + } + + for ( control= 0; (control < pageInfo->PageControls.ControlCount) && (found == FALSE); control++ ) + { + controlInfo = (CONTROL_INFO *)((UINTN)gControlInfo + pageInfo->PageControls.ControlList[control]); + + if(QuestionId == controlInfo->ControlKey) + { + if ((CONTROL_TYPE_MSGBOX == controlInfo->ControlType) || (NO_SUBMIT_IF == controlInfo->ControlType) || gInconsistCondPtr) + { + if (gInconsistCondPtr == controlInfo->ControlConditionalPtr) //All inconsistentif will have 0 as question id so adding more check + { + varId = controlInfo->ControlVariable; + found = TRUE; + } + } + else + { + varId = controlInfo->ControlVariable; + found = TRUE; + } + } + } + + if(!found) + { + // Control Definition not in this Page. Look within the formset + EFI_HII_HANDLE pgHandle = pageInfo->PageHandle; + UINT32 page = 0; + + for(;page < gPages->PageCount && (found == FALSE); page++) + { +/* + if(page == PageId) + { + continue; + } +*/ + pageInfo = (PAGE_INFO *)((UINTN)gApplicationData + gPages->PageList[page]); + if(pageInfo->PageHandle != pgHandle) + { + continue; + } + + for(control = 0; control < pageInfo->PageControls.ControlCount && (found == FALSE); control++) + { + controlInfo = (CONTROL_INFO *)((UINTN)gControlInfo + pageInfo->PageControls.ControlList[control]); + + if(QuestionId == controlInfo->ControlKey) + { + varId = controlInfo->ControlVariable; + found = TRUE; + } + } + } + } + + if(found) + { + if (NULL != controlInfo->ControlPtr) //For inconsistent and nosubmitif controlptr will be NULL + { + UINTN dataWidth = UefiGetWidth(controlInfo->ControlPtr); + questionHdr = (EFI_IFR_QUESTION_HEADER*)((UINT8 *)controlInfo->ControlPtr + sizeof(EFI_IFR_OP_HEADER)); + + // EIP-42300: Updated the dataWidth in comparision to the maximum supported + Status = VarGetValue(varId, questionHdr->VarStoreInfo.VarOffset, (( dataWidth > sizeof(UINT64))? sizeof(UINT64) : dataWidth ), &questionValue); + if(EFI_ERROR(Status)) + { + goto DONE; + } + (*Value)->Value.u64 = questionValue; + } + else if ((CONTROL_TYPE_MSGBOX == controlInfo->ControlType) || (NO_SUBMIT_IF == controlInfo->ControlType)) //Check for inconistent control + { + Status = GetValueFromParentControl (QuestionId, PageId, Value, pageInfo, controlInfo->ControlConditionalPtr); + } + } +DONE: + return Status; +} +// +//---------------------------------------------------------------------------- +// +// Procedure: _SetValueFromQuestionId +// +// Description: +// +// Parameter: UINT16 QuestionId, UINT16 PageId, UINT64 *Value +// +// Return value: EFI_STATUS +//---------------------------------------------------------------------------- +// +EFI_STATUS _SetValueFromQuestionId(UINT16 QuestionId, UINT16 PageId, EFI_HII_VALUE *Value) +{ + EFI_STATUS Status = EFI_SUCCESS; + EFI_IFR_QUESTION_HEADER *questionHdr = NULL; + BOOLEAN found = FALSE; + UINT32 varId = 0; + UINTN control = 0; + UINT64 questionValue = Value->Value.u64; + + CONTROL_INFO *controlInfo = NULL; + + PAGE_INFO *pageInfo = (PAGE_INFO *)((UINTN)gApplicationData + gPages->PageList[PageId]); + + if(pageInfo->PageHandle ==0) + { + Status = EFI_NOT_FOUND; + goto DONE; + } + + for ( control= 0; (control < pageInfo->PageControls.ControlCount) && (found == FALSE); control++ ) + { + controlInfo = (CONTROL_INFO *)((UINTN)gControlInfo + pageInfo->PageControls.ControlList[control]); + + if(QuestionId == controlInfo->ControlKey) + { + varId = controlInfo->ControlVariable; + found = TRUE; + } + } + + if(!found) + { + // Control Definition not in this Page. Look within the formset + EFI_HII_HANDLE pgHandle = pageInfo->PageHandle; + UINT32 page = 0; + + for(;page < gPages->PageCount && (found == FALSE); page++) + { + + pageInfo = (PAGE_INFO *)((UINTN)gApplicationData + gPages->PageList[page]); + if(pageInfo->PageHandle != pgHandle) + { + continue; + } + + for(control = 0; control < pageInfo->PageControls.ControlCount && (found == FALSE); control++) + { + controlInfo = (CONTROL_INFO *)((UINTN)gControlInfo + pageInfo->PageControls.ControlList[control]); + + if(QuestionId == controlInfo->ControlKey) + { + varId = controlInfo->ControlVariable; + found = TRUE; + } + } + } + } + + if(found) + { + UINTN dataWidth = UefiGetWidth(controlInfo->ControlPtr); + questionHdr = (EFI_IFR_QUESTION_HEADER*)((UINT8 *)controlInfo->ControlPtr + sizeof(EFI_IFR_OP_HEADER)); + + // EIP-42300: Updated the dataWidth in comparision to the maximum supported + Status = VarSetValue(varId, questionHdr->VarStoreInfo.VarOffset, (( dataWidth > sizeof(UINT64))? sizeof(UINT64) : dataWidth ), &questionValue); + + } + +DONE: + return Status; +} + +// +//---------------------------------------------------------------------------- +// +// Procedure: IsScopeStackEmpty +// +// Description: +// +// Parameter: VOID +// +// Return value: BOOLEAN +//---------------------------------------------------------------------------- +// +BOOLEAN IsScopeStackEmpty() +{ + UINT8 opCode = 0; + EFI_STATUS status = EFI_SUCCESS; + + status = PopScope(&opCode); + if(status == EFI_ACCESS_DENIED) + { + return TRUE; + } + + status = PushScope(opCode); + + return FALSE; +} + +// +//--------------------------------------------------------------------------- +// Procedure: GetPageIdFromGuid +// +// Description: Finds the page ID with matching Guid from the page list +// +// Input: EFI_GUID *FormSetGuid +// UINT16 *PageID +// +// Output: EFI_STATUS status - EFI_SUCCESS, if successful, +// EFI_INVALID_PARAMETER, if invalid values found +//--------------------------------------------------------------------------- +// +EFI_STATUS GetpageIdFromGuid(EFI_GUID *FormGuid, UINT16 *PageID) +{ + EFI_STATUS status = EFI_INVALID_PARAMETER; + UINT32 pgIndex = 0; + PAGE_INFO *pgInfo = (PAGE_INFO *)NULL; + PAGE_ID_INFO *pageIdInfo = (PAGE_ID_INFO*)NULL; + + + if(gPages && gApplicationData && gPageIdList) + { + for(pgIndex = 0; pgIndex < gPages->PageCount; pgIndex++) + { + pgInfo = (PAGE_INFO*)((UINTN)gApplicationData + gPages->PageList[pgIndex]); + if(pgInfo){ + pageIdInfo = (PAGE_ID_INFO *)(((UINT8 *) gPageIdList) + gPageIdList->PageIdList[pgInfo->PageIdIndex]); + if(pageIdInfo && (EfiCompareGuid(FormGuid, &(pageIdInfo->PageGuid)) == TRUE))//Compare Guid + { + *PageID = pgInfo->PageID; + status = EFI_SUCCESS; + goto DONE; + } + } + } + } + +DONE: + return status; +} + +// +//---------------------------------------------------------------------------- +// +// Procedure: EvaluateExpression +// +// Description: Evaluate the result of a HII expression +// +// Parameter: IN CONTROL_INFO *ControlInfo, +// IN OUT BOOLEAN *ExpressionResult, +// OUT UINTN *Offset +// +// Return value: EFI_SUCCESS - The expression evaluated successfuly +// EFI_NOT_FOUND - The Question which referenced by a +// QuestionId could not be found. +// EFI_OUT_OF_RESOURCES - There is not enough system memory to +// grow the stack. +// EFI_ACCESS_DENIED - The pop operation underflowed the stack +// EFI_INVALID_PARAMETER - Syntax error with the Expression +//---------------------------------------------------------------------------- +// +EFI_STATUS +EvaluateExpression ( + IN CONTROL_INFO *ControlInfo, + IN OUT EFI_HII_VALUE *ExpressionResult, + OUT UINTN *Offset + ) +{ + EFI_IFR_OP_HEADER *ifrData = NULL; + CONTROL_INFO *ruleControl = NULL; + EFI_STATUS Status; + UINT16 Index; + EFI_HII_VALUE Data1; + EFI_HII_VALUE Data2; + EFI_HII_VALUE Data3; + EFI_HII_VALUE *questionValue = NULL; + EFI_HII_VALUE *questionValue2 = NULL; + EFI_HII_VALUE *Value = NULL; + EFI_QUESTION_ID questionId = 0; + INTN Result; + CHAR16 *StrPtr = NULL; + UINTN i = 0; + UINT8 opCode = 0; + BOOLEAN IsDevicePathFound = FALSE ,GUIDFound = FALSE; + EFI_GUID formSetGuid = {0}, zeroFormSetGuid = {0}; + UINTN count = 0,tempcount = 0; + CHAR16 *devPathStr = (CHAR16 *)NULL, *tempDevPathStr = (CHAR16 *)NULL; + EFI_DEVICE_PATH_PROTOCOL *tempDevPath = (EFI_DEVICE_PATH_PROTOCOL *)NULL; + UINT16 DevicePath = 0; + // + // Always reset the stack before evaluating an Expression + // + ResetExpressionStack (); + + ExpressionResult->Type = EFI_IFR_TYPE_OTHER; + + opCode = ((EFI_IFR_OP_HEADER*)ControlInfo->ControlConditionalPtr)->OpCode; + if(opCode != EFI_IFR_SUPPRESS_IF_OP && opCode != EFI_IFR_NO_SUBMIT_IF_OP && + opCode != EFI_IFR_INCONSISTENT_IF_OP && opCode != EFI_IFR_GRAY_OUT_IF_OP && + opCode != EFI_IFR_DISABLE_IF_OP && opCode != EFI_IFR_VALUE_OP) + { + Status = EFI_SUCCESS; + goto DONE; + } + + questionValue = (EFI_HII_VALUE*)EfiLibAllocateZeroPool(sizeof(EFI_HII_VALUE)); + if(questionValue == NULL) + { + Status = EFI_OUT_OF_RESOURCES; + goto DONE; + } + + questionValue2 = (EFI_HII_VALUE*)EfiLibAllocateZeroPool(sizeof(EFI_HII_VALUE)); + if(questionValue2 == NULL) + { + Status = EFI_OUT_OF_RESOURCES; + goto DONE; + } + + if(((EFI_IFR_OP_HEADER*)ControlInfo->ControlConditionalPtr)->OpCode == EFI_IFR_RULE_OP) + { + PushScope(EFI_IFR_RULE_OP); + }else + { + PushScope(((EFI_IFR_OP_HEADER*)ControlInfo->ControlConditionalPtr)->OpCode); + if ( + ( ( (EFI_IFR_OP_HEADER*)ControlInfo->ControlConditionalPtr)->OpCode == EFI_IFR_INCONSISTENT_IF_OP) || + ( ( (EFI_IFR_OP_HEADER*)ControlInfo->ControlConditionalPtr)->OpCode == EFI_IFR_NO_SUBMIT_IF_OP) + ) + { + gInconsistCondPtr = ControlInfo->ControlConditionalPtr; + } + } + + i += ((EFI_IFR_OP_HEADER*)ControlInfo->ControlConditionalPtr)->Length; + + while (IsScopeStackEmpty() == FALSE) + { + ifrData = (EFI_IFR_OP_HEADER*)((UINT8 *)ControlInfo->ControlConditionalPtr + i); + + EfiZeroMem (&Data1, sizeof (EFI_HII_VALUE)); + EfiZeroMem (&Data2, sizeof (EFI_HII_VALUE)); + EfiZeroMem (&Data3, sizeof (EFI_HII_VALUE)); + EfiZeroMem (questionValue, sizeof(EFI_HII_VALUE)); + EfiZeroMem (questionValue2, sizeof(EFI_HII_VALUE)); + + Value = &Data3; + Value->Type = EFI_IFR_TYPE_BOOLEAN; + Status = EFI_SUCCESS; + + questionValue->Type = EFI_IFR_TYPE_NUM_SIZE_64; + + switch (ifrData->OpCode) + { + // + // Built-in functions + // + case EFI_IFR_EQ_ID_VAL_OP: + questionId = ((EFI_IFR_EQ_ID_VAL*)ifrData)->QuestionId; + Status = _GetValueFromQuestionId(questionId, ControlInfo->ControlPageID, &questionValue); + if(EFI_ERROR(Status)) + { + goto DONE; + } + + questionValue2->Type = EFI_IFR_TYPE_NUM_SIZE_64; + questionValue2->Value.u64 = ((EFI_IFR_EQ_ID_VAL*)ifrData)->Value; + + Result = CompareHiiValue (questionValue, questionValue2, NULL); + if (Result == EFI_INVALID_PARAMETER) + { + Status = EFI_INVALID_PARAMETER; + goto DONE; + } + Value->Value.b = (Result == 0) ? TRUE : FALSE; + break; + + case EFI_IFR_EQ_ID_ID_OP: + questionId = ((EFI_IFR_EQ_ID_ID*)ifrData)->QuestionId1; + Status = _GetValueFromQuestionId(questionId, ControlInfo->ControlPageID, &questionValue); + if(EFI_ERROR(Status)) + { + goto DONE; + } + questionId = ((EFI_IFR_EQ_ID_ID*)ifrData)->QuestionId2; + Status = _GetValueFromQuestionId(questionId, ControlInfo->ControlPageID, &questionValue2); + if(EFI_ERROR(Status)) + { + goto DONE; + } + + Result = CompareHiiValue (questionValue, questionValue2, ControlInfo->ControlHandle); + if (Result == EFI_INVALID_PARAMETER) + { + Status = EFI_INVALID_PARAMETER; + goto DONE; + } + Value->Value.b = (Result == 0) ? TRUE : FALSE; + break; + + case EFI_IFR_EQ_ID_LIST_OP: + questionId = ((EFI_IFR_EQ_ID_LIST*)ifrData)->QuestionId; + Status = _GetValueFromQuestionId(questionId, ControlInfo->ControlPageID, &questionValue); + if(EFI_ERROR(Status)) + { + goto DONE; + } + + Value->Value.b = FALSE; + for (Index =0; Index < ((EFI_IFR_EQ_ID_LIST*)ifrData)->ListLength; Index++) + { + if (questionValue->Value.u16 == ((EFI_IFR_EQ_ID_LIST*)ifrData)->ValueList[Index]) + { + Value->Value.b = TRUE; + break; + } + } + break; + + case EFI_IFR_DUP_OP: + Status = PopExpression (Value); + if (EFI_ERROR (Status)) + { + goto DONE; + } + + Status = PushExpression (Value); + break; + + case EFI_IFR_QUESTION_REF1_OP: + case EFI_IFR_THIS_OP: + if(ifrData->OpCode == EFI_IFR_THIS_OP) + { + questionId = ControlInfo->ControlKey; + }else + { + questionId = ((EFI_IFR_QUESTION_REF1*)ifrData)->QuestionId; + } + Status = _GetValueFromQuestionId(questionId, ControlInfo->ControlPageID, &questionValue); + if(EFI_ERROR(Status)) + { + goto DONE; + } + + Value = questionValue; + break; + + + case EFI_IFR_QUESTION_REF3_OP: + + // + // EFI_IFR_QUESTION_REF3 + // Pop an expression from the expression stack + // + Status = PopExpression (Value); + if (EFI_ERROR (Status)) + { + goto DONE; + } + + // + // Validate the expression value + // + + if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) + { + Status = EFI_NOT_FOUND; + goto DONE; + } + + if(ifrData->Length > sizeof(EFI_IFR_QUESTION_REF3)) + { + if(ifrData->Length > sizeof(EFI_IFR_QUESTION_REF3_2)) + { + MemCopy(&formSetGuid,&((EFI_IFR_QUESTION_REF3_3*)ifrData)->Guid, sizeof (EFI_GUID)); + if(EfiCompareGuid(&formSetGuid, &zeroFormSetGuid) == FALSE) + { + UINT16 PageID; + Status = GetpageIdFromGuid(&formSetGuid,&PageID); + if(Status == 0) + { + GUIDFound = TRUE; + Status = _GetValueFromQuestionId(Value->Value.u16,PageID, &questionValue); + if(EFI_ERROR(Status)) + { + goto DONE; + } + } + } + } + DevicePath = ifrData->Length < sizeof(EFI_IFR_QUESTION_REF3_3) ? ((EFI_IFR_QUESTION_REF3_2*)ifrData)->DevicePath : ((EFI_IFR_QUESTION_REF3_3*)ifrData)->DevicePath; + if(DevicePath != 0 && !GUIDFound) + { + PAGE_INFO *tempPageInfo1 = NULL; + devPathStr = GetToken (DevicePath,ControlInfo->ControlHandle); + + if(devPathStr == NULL){ + goto DONE; + } + + for(count = 0; count < gPages->PageCount; count++) + { + PAGE_INFO *tempPageInfo = (PAGE_INFO*)((UINTN)gApplicationData + gPages->PageList[count]); + if(tempPageInfo == NULL) + { + continue; + } + Status = GetDevPathFromHandle(tempPageInfo->PageHandle, &tempDevPath); + if((Status == EFI_SUCCESS) && (tempDevPath != NULL) && tempPageInfo->PageParentID == 0) + { + GetStringFromDevPath(tempDevPath, &tempDevPathStr); + if(EfiStrCmp(devPathStr, tempDevPathStr) == 0) + { + tempcount++; + tempPageInfo1=tempPageInfo; + } + MemFreePointer( (VOID **)&tempDevPathStr ); + } + } + MemFreePointer( (VOID **)&devPathStr ); + + if(tempcount == 1){ + IsDevicePathFound = TRUE; + Status = _GetValueFromQuestionId(Value->Value.u16, tempPageInfo1->PageID, &questionValue); + if(EFI_ERROR(Status)) + { + goto DONE; + } + } + if(tempcount > 1){ + goto DONE; + } + } + } + if(!IsDevicePathFound && !GUIDFound && !tempcount) + { + Status = _GetValueFromQuestionId(Value->Value.u16, ControlInfo->ControlPageID, &questionValue); + if(EFI_ERROR(Status)) + { + goto DONE; + } + } + Value = questionValue; + break; + + case EFI_IFR_RULE_REF_OP: + questionId = ((EFI_IFR_RULE_REF*)ifrData)->RuleId; + + Status = _GetRuleControlfromId(questionId, ControlInfo->ControlPageID, &ruleControl); + + /* This Section Needs to be modified + // + // Find expression for this rule + // + RuleExpression = RuleIdToExpression (Form, OpCode->RuleId); + if (RuleExpression == NULL) { + return EFI_NOT_FOUND; + }*/ + + // + // Evaluate this rule expression + // + Status = EvaluateExpression (ruleControl, ExpressionResult, Offset); + if (EFI_ERROR (Status)) + { + goto DONE; + } + + Value = ExpressionResult; + break; + + case EFI_IFR_STRING_REF1_OP: + Value->Type = EFI_IFR_TYPE_STRING; + Value->Value.string = ((EFI_IFR_STRING_REF1*)ifrData)->StringId; + break; + + // + // Constant + // + case EFI_IFR_TRUE_OP: + Value->Value.b = TRUE; + break; + case EFI_IFR_FALSE_OP: + Value->Value.b = FALSE; + break; + case EFI_IFR_ONE_OP: +#define ONE 1 + Value->Type = EFI_IFR_TYPE_NUM_SIZE_8; + Value->Value.u8 = ONE; + break; + case EFI_IFR_ONES_OP: +#define ONES 0xFFFFFFFFFFFFFFFF + Value->Type = EFI_IFR_TYPE_NUM_SIZE_64; + Value->Value.u64 = ONES; + break; + case EFI_IFR_UINT8_OP: + Value->Type = EFI_IFR_TYPE_NUM_SIZE_8; + Value->Value.u8 = ((EFI_IFR_UINT8*)ifrData)->Value; + break; + case EFI_IFR_UINT16_OP: + Value->Type = EFI_IFR_TYPE_NUM_SIZE_16; + Value->Value.u16 = ((EFI_IFR_UINT16*)ifrData)->Value; + break; + case EFI_IFR_UINT32_OP: + Value->Type = EFI_IFR_TYPE_NUM_SIZE_32; + Value->Value.u32 = ((EFI_IFR_UINT32*)ifrData)->Value; + break; + case EFI_IFR_UINT64_OP: + Value->Type = EFI_IFR_TYPE_NUM_SIZE_64; + Value->Value.u64 = ((EFI_IFR_UINT64*)ifrData)->Value; + break; + case EFI_IFR_UNDEFINED_OP: + Value->Type = EFI_IFR_TYPE_OTHER; + break; + case EFI_IFR_VERSION_OP: +#define VERSION (UINT16)(2<<8)|((3<<4) | 0x1) //EIP:56355 Updated the Version to 2.3.1 + Value->Type = EFI_IFR_TYPE_NUM_SIZE_16; + Value->Value.u16 = VERSION; + break; + case EFI_IFR_ZERO_OP: +#define ZERO 0 + Value->Type = EFI_IFR_TYPE_NUM_SIZE_8; + Value->Value.u8 = ZERO; + break; + + // + // unary-op + // + case EFI_IFR_LENGTH_OP: + Status = PopExpression (Value); + if (EFI_ERROR (Status)) { + goto DONE; + } + if (Value->Type != EFI_IFR_TYPE_STRING) { + Status = EFI_INVALID_PARAMETER; + goto DONE; + } + + StrPtr = GetToken (Value->Value.string, ControlInfo->ControlHandle); + if (StrPtr == NULL) { + Status = EFI_INVALID_PARAMETER; + goto DONE; + } + + Value->Type = EFI_IFR_TYPE_NUM_SIZE_64; + Value->Value.u64 = EfiStrLen (StrPtr); + gBS->FreePool (StrPtr); + break; + + case EFI_IFR_NOT_OP: + Status = PopExpression (Value); + if (EFI_ERROR (Status)) { + goto DONE; + } + if (Value->Type != EFI_IFR_TYPE_BOOLEAN) { + Status = EFI_INVALID_PARAMETER; + goto DONE; + } + Value->Value.b = !Value->Value.b; + break; + + case EFI_IFR_QUESTION_REF2_OP: + // + // Pop an expression from the expression stack + // + Status = PopExpression (Value); + if (EFI_ERROR (Status)) { + goto DONE; + } + + // + // Validate the expression value + // + if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) { + Status = EFI_NOT_FOUND; + goto DONE; + } + + Status = _GetValueFromQuestionId(Value->Value.u16, ControlInfo->ControlPageID, &questionValue); + if(EFI_ERROR(Status)) + { + goto DONE; + } + + Value = questionValue; + break; + + case EFI_IFR_STRING_REF2_OP: + // + // Pop an expression from the expression stack + // + Status = PopExpression (Value); + if (EFI_ERROR (Status)) { + goto DONE; + } + + // + // Validate the expression value + // + if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) { + Status = EFI_NOT_FOUND; + goto DONE; + } + + Value->Type = EFI_IFR_TYPE_STRING; + StrPtr = GetToken (Value->Value.u16, ControlInfo->ControlHandle); + if (StrPtr == NULL) { + // + // If String not exit, push an empty string + // + Value->Value.string = NewString (gEmptyString, ControlInfo->ControlHandle); + } else { + Index = (UINT16) Value->Value.u64; + Value->Value.string = Index; + gBS->FreePool (StrPtr); + } + break; + + case EFI_IFR_TO_BOOLEAN_OP: + // + // Pop an expression from the expression stack + // + Status = PopExpression (Value); + if (EFI_ERROR (Status)) { + goto DONE; + } + + // + // Convert an expression to a Boolean + // + if (Value->Type <= EFI_IFR_TYPE_DATE) { + // + // When converting from an unsigned integer, zero will be converted to + // FALSE and any other value will be converted to TRUE. + // + Value->Value.b = (Value->Value.u64) ? TRUE : FALSE; + + Value->Type = EFI_IFR_TYPE_BOOLEAN; + } else if (Value->Type == EFI_IFR_TYPE_STRING) { + // + // When converting from a string, if case-insensitive compare + // with "true" is True, then push True. If a case-insensitive compare + // with "false" is True, then push False. + // + StrPtr = GetToken (Value->Value.string, ControlInfo->ControlHandle); + if (StrPtr == NULL) { + Status = EFI_INVALID_PARAMETER; + goto DONE; + } + + if ((EfiStrCmp (StrPtr, L"true") == 0)) + { + Value->Value.b = TRUE; + } else if(EfiStrCmp (StrPtr, L"false") == 0) + { + Value->Value.b = FALSE; + } else + { + Value->Type = EFI_IFR_TYPE_OTHER; + } + gBS->FreePool (StrPtr); + Value->Type = EFI_IFR_TYPE_BOOLEAN; + } + break; + + case EFI_IFR_TO_STRING_OP: + Status = IfrToString (ControlInfo->ControlHandle, ((EFI_IFR_TO_STRING*)ifrData)->Format, Value); + break; + + case EFI_IFR_TO_UINT_OP: + Status = IfrToUint (ControlInfo->ControlHandle, Value); + break; + + case EFI_IFR_TO_LOWER_OP: + case EFI_IFR_TO_UPPER_OP: + Status = InitializeUnicodeCollationProtocol (); + if (EFI_ERROR (Status)) { + goto DONE; + } + + Status = PopExpression (Value); + if (EFI_ERROR (Status)) { + goto DONE; + } + + if (Value->Type != EFI_IFR_TYPE_STRING) { + Status = EFI_UNSUPPORTED; + goto DONE; + } + + StrPtr = GetToken (Value->Value.string, ControlInfo->ControlHandle); + if (StrPtr == NULL) { + Status = EFI_NOT_FOUND; + goto DONE; + } + + if (ifrData->OpCode == EFI_IFR_TO_LOWER_OP) { + mUnicodeCollation->StrLwr (mUnicodeCollation, StrPtr); + } else { + mUnicodeCollation->StrUpr (mUnicodeCollation, StrPtr); + } + Value->Value.string = NewString (StrPtr, ControlInfo->ControlHandle); + gBS->FreePool (StrPtr); + break; + + case EFI_IFR_BITWISE_NOT_OP: + // + // Pop an expression from the expression stack + // + Status = PopExpression (Value); + if (EFI_ERROR (Status)) { + goto DONE; + } + if (Value->Type > EFI_IFR_TYPE_DATE) { + Status = EFI_INVALID_PARAMETER; + goto DONE; + } + + Value->Type = EFI_IFR_TYPE_NUM_SIZE_64; + Value->Value.u64 = ~Value->Value.u64; + break; + + // + // binary-op + // + case EFI_IFR_ADD_OP: + case EFI_IFR_SUBTRACT_OP: + case EFI_IFR_MULTIPLY_OP: + case EFI_IFR_DIVIDE_OP: + case EFI_IFR_MODULO_OP: + case EFI_IFR_BITWISE_AND_OP: + case EFI_IFR_BITWISE_OR_OP: + case EFI_IFR_SHIFT_LEFT_OP: + case EFI_IFR_SHIFT_RIGHT_OP: + // + // Pop an expression from the expression stack + // + Status = PopExpression (&Data2); + if (EFI_ERROR (Status)) { + goto DONE; + } + if (Data2.Type > EFI_IFR_TYPE_DATE) { + Status = EFI_INVALID_PARAMETER; + goto DONE; + } + + // + // Pop another expression from the expression stack + // + Status = PopExpression (&Data1); + if (EFI_ERROR (Status)) { + goto DONE; + } + if (Data1.Type > EFI_IFR_TYPE_DATE) { + Status = EFI_INVALID_PARAMETER; + goto DONE; + } + + Value->Type = EFI_IFR_TYPE_NUM_SIZE_64; + + switch (ifrData->OpCode) { + case EFI_IFR_ADD_OP: + Value->Value.u64 = Data1.Value.u64 + Data2.Value.u64; + break; + + case EFI_IFR_SUBTRACT_OP: + Value->Value.u64 = Data1.Value.u64 - Data2.Value.u64; + break; + + case EFI_IFR_MULTIPLY_OP: + Value->Value.u64 = MultU64x32 (Data1.Value.u64, (UINT32)Data2.Value.u64); + break; + + case EFI_IFR_DIVIDE_OP: + Value->Value.u64 = AmiTseDivU64x32 (Data1.Value.u64, (UINT32)Data2.Value.u64,NULL); + break; + + case EFI_IFR_MODULO_OP: + Value->Value.u64 = 0; + AmiTseDivU64x32(Data1.Value.u64, (UINT32)Data2.Value.u64, (UINTN*)&Value->Value.u64); + break; + + case EFI_IFR_BITWISE_AND_OP: + Value->Value.u64 = Data1.Value.u64 & Data2.Value.u64; + break; + + case EFI_IFR_BITWISE_OR_OP: + Value->Value.u64 = Data1.Value.u64 | Data2.Value.u64; + break; + + case EFI_IFR_SHIFT_LEFT_OP: + Value->Value.u64 = LShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64); + break; + + case EFI_IFR_SHIFT_RIGHT_OP: + Value->Value.u64 = RShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64); + break; + + default: + break; + } + break; + + case EFI_IFR_AND_OP: + case EFI_IFR_OR_OP: + // + // Two Boolean operator + // + Status = PopExpression (&Data2); + if (EFI_ERROR (Status)) { + goto DONE; + } + if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) { + Status = EFI_INVALID_PARAMETER; + goto DONE; + } + + // + // Pop another expression from the expression stack + // + Status = PopExpression (&Data1); + if (EFI_ERROR (Status)) { + goto DONE; + } + if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) { + Status = EFI_INVALID_PARAMETER; + goto DONE; + } + + if (ifrData->OpCode == EFI_IFR_AND_OP) { + Value->Value.b = Data1.Value.b && Data2.Value.b; + } else { + Value->Value.b = Data1.Value.b || Data2.Value.b; + } + break; + + case EFI_IFR_EQUAL_OP: + case EFI_IFR_NOT_EQUAL_OP: + case EFI_IFR_GREATER_EQUAL_OP: + case EFI_IFR_GREATER_THAN_OP: + case EFI_IFR_LESS_EQUAL_OP: + case EFI_IFR_LESS_THAN_OP: + // + // Compare two integer, string, boolean or date/time + // + Status = PopExpression (&Data2); + if (EFI_ERROR (Status)) { + goto DONE; + } + if (Data2.Type > EFI_IFR_TYPE_BOOLEAN && Data2.Type != EFI_IFR_TYPE_STRING) { + Status = EFI_INVALID_PARAMETER; + goto DONE; + } + + // + // Pop another expression from the expression stack + // + Status = PopExpression (&Data1); + if (EFI_ERROR (Status)) { + goto DONE; + } + + Result = CompareHiiValue (&Data1, &Data2, ControlInfo->ControlHandle); + if (Result == EFI_INVALID_PARAMETER) { + Status = EFI_INVALID_PARAMETER; + goto DONE; + } + + switch (ifrData->OpCode) { + case EFI_IFR_EQUAL_OP: + Value->Value.b = (Result == 0) ? TRUE : FALSE; + break; + + case EFI_IFR_NOT_EQUAL_OP: + Value->Value.b = (Result != 0) ? TRUE : FALSE; + break; + + case EFI_IFR_GREATER_EQUAL_OP: + Value->Value.b = (Result >= 0) ? TRUE : FALSE; + break; + + case EFI_IFR_GREATER_THAN_OP: + Value->Value.b = (Result > 0) ? TRUE : FALSE; + break; + + case EFI_IFR_LESS_EQUAL_OP: + Value->Value.b = (Result <= 0) ? TRUE : FALSE; + break; + + case EFI_IFR_LESS_THAN_OP: + Value->Value.b = (Result < 0) ? TRUE : FALSE; + break; + + default: + break; + } + break; + + case EFI_IFR_MATCH_OP: + Status = IfrMatch (ControlInfo->ControlHandle, Value); + break; + + case EFI_IFR_CATENATE_OP: + Status = IfrCatenate (ControlInfo->ControlHandle, Value); + break; + + // + // ternary-op + // + case EFI_IFR_CONDITIONAL_OP: + // + // Pop third expression from the expression stack + // + Status = PopExpression (&Data3); + if (EFI_ERROR (Status)) { + goto DONE; + } + + // + // Pop second expression from the expression stack + // + Status = PopExpression (&Data2); + if (EFI_ERROR (Status)) { + goto DONE; + } + + // + // Pop first expression from the expression stack + // + Status = PopExpression (&Data1); + if (EFI_ERROR (Status)) { + goto DONE; + } + if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) { + Status = EFI_INVALID_PARAMETER; + goto DONE; + } + + if (Data1.Value.b) { + Value = &Data3; + } else { + Value = &Data2; + } + break; + + case EFI_IFR_FIND_OP: + Status = IfrFind (ControlInfo->ControlHandle, ((EFI_IFR_FIND*)ifrData)->Format, Value); + break; + + case EFI_IFR_MID_OP: + Status = IfrMid (ControlInfo->ControlHandle, Value); + break; + + case EFI_IFR_TOKEN_OP: + Status = IfrToken (ControlInfo->ControlHandle, Value); + break; + + case EFI_IFR_SPAN_OP: + Status = IfrSpan (ControlInfo->ControlHandle, ((EFI_IFR_SPAN*)ifrData)->Flags, Value); + break; + + default: + Status = PopScope(&opCode); + if (EFI_ERROR (Status)) + { + goto DONE; + } + continue; + } + if (EFI_ERROR (Status)) + { + goto DONE; + } + + Status = PushExpression (Value); + if (EFI_ERROR (Status)) + { + goto DONE; + } + + i += ifrData->Length; + } + if (NULL != ifrData)//EIP-75384 Static code + { + if(ifrData->OpCode == EFI_IFR_END_OP) + i += ifrData->Length; + } + + // + // Pop the final result from expression stack + // + Value = &Data1; + Status = PopExpression (Value); + if (EFI_ERROR (Status)) { + goto DONE; + } + + // + // After evaluating an expression, there should be only one value left on the expression stack + // + if (PopExpression (Value) != EFI_ACCESS_DENIED) + { + Status = EFI_INVALID_PARAMETER; + goto DONE; + } + + EfiCopyMem (ExpressionResult, Value, sizeof (EFI_HII_VALUE)); + +DONE: + MemFreePointer(&questionValue); + MemFreePointer(&questionValue2); + + *Offset = i; + gInconsistCondPtr = NULL; + return Status; +} + +// +//---------------------------------------------------------------------------- +// Procedure: _SkipExpression +// +// Description: Travels till the end of the current Expression and returns the offset +// +// Parameter: ControlCondPtr - Pointer to the Expression beginning. +// +// Return value: UINTN - Offsets to skip the current expression. +//---------------------------------------------------------------------------- +// +UINTN _SkipExpression(UINT8 *ControlCondPtr) +{ + EFI_IFR_OP_HEADER *OpHeader = ( EFI_IFR_OP_HEADER * )ControlCondPtr; + UINTN offset = 0; + INTN inScope = 0; + + // Skip the If condition OpCode + if( + OpHeader->OpCode != EFI_IFR_SUPPRESS_IF_OP && + OpHeader->OpCode != EFI_IFR_NO_SUBMIT_IF_OP && + OpHeader->OpCode != EFI_IFR_INCONSISTENT_IF_OP && + OpHeader->OpCode != EFI_IFR_GRAY_OUT_IF_OP && + OpHeader->OpCode != EFI_IFR_DISABLE_IF_OP + ) + { + // This should not happen. The code should halt here. + offset = 0; + goto DONE; + } + + // Skip the If opcode + offset = OpHeader->Length; + OpHeader = ( EFI_IFR_OP_HEADER * )(( UINT8 *)OpHeader + offset ); + + do + { + switch( OpHeader->OpCode ) + { + case EFI_IFR_END_OP: + inScope--; + break; + default: + if(OpHeader->Scope) + inScope++; + break; + } + offset += OpHeader->Length; + OpHeader = ( EFI_IFR_OP_HEADER * )(( UINT8 *)OpHeader + OpHeader->Length ); + }while(inScope > 0); + +DONE: + return offset; +} + + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2011, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Building 200,Norcross, Georgia 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** -- cgit v1.2.3