X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FUniversal%2FSetupBrowserDxe%2FExpression.c;h=7f4929c2fcd90a59e934723ba158a20db03a9fd5;hp=883693fde59233acd397001b1bf3d8b290bb5246;hb=9d510e61fceee7b92955ef9a3c20343752d8ce3f;hpb=901ba0e78d02bd4407571c296871f96a0d225698 diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Expression.c b/MdeModulePkg/Universal/SetupBrowserDxe/Expression.c index 883693fde5..7f4929c2fc 100644 --- a/MdeModulePkg/Universal/SetupBrowserDxe/Expression.c +++ b/MdeModulePkg/Universal/SetupBrowserDxe/Expression.c @@ -1,14 +1,8 @@ /** @file Utility functions for expression evaluation. -Copyright (c) 2007 - 2011, 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. +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -34,6 +28,19 @@ EFI_HII_VALUE *mMapExpressionListStack = NULL; EFI_HII_VALUE *mMapExpressionListEnd = NULL; EFI_HII_VALUE *mMapExpressionListPointer = NULL; +FORM_EXPRESSION **mFormExpressionStack = NULL; +FORM_EXPRESSION **mFormExpressionEnd = NULL; +FORM_EXPRESSION **mFormExpressionPointer = NULL; + +FORM_EXPRESSION **mStatementExpressionStack = NULL; +FORM_EXPRESSION **mStatementExpressionEnd = NULL; +FORM_EXPRESSION **mStatementExpressionPointer = NULL; + +FORM_EXPRESSION **mOptionExpressionStack = NULL; +FORM_EXPRESSION **mOptionExpressionEnd = NULL; +FORM_EXPRESSION **mOptionExpressionPointer = NULL; + + // // Unicode collation protocol interface // @@ -144,7 +151,7 @@ PushStack ( (*StackPtr)->Buffer = AllocateCopyPool(Data->BufferLen, Data->Buffer); ASSERT ((*StackPtr)->Buffer != NULL); } - + *StackPtr = *StackPtr + 1; return EFI_SUCCESS; @@ -194,7 +201,10 @@ ResetCurrentExpressionStack ( VOID ) { - mCurrentExpressionPointer = mCurrentExpressionStack; + mCurrentExpressionPointer = mCurrentExpressionStack; + mFormExpressionPointer = mFormExpressionStack; + mStatementExpressionPointer = mStatementExpressionStack; + mOptionExpressionPointer = mOptionExpressionStack; } @@ -267,6 +277,294 @@ ResetMapExpressionListStack ( } +/** + Grow size of the stack. + + This is an internal function. + + @param Stack On input: old stack; On output: new stack + @param StackPtr On input: old stack pointer; On output: new stack + pointer + @param StackEnd On input: old stack end; On output: new stack end + @param MemberSize The stack member size. + + @retval EFI_SUCCESS Grow stack success. + @retval EFI_OUT_OF_RESOURCES No enough memory for stack space. + +**/ +EFI_STATUS +GrowConditionalStack ( + IN OUT FORM_EXPRESSION ***Stack, + IN OUT FORM_EXPRESSION ***StackPtr, + IN OUT FORM_EXPRESSION ***StackEnd, + IN UINTN MemberSize + ) +{ + UINTN Size; + FORM_EXPRESSION **NewStack; + + Size = EXPRESSION_STACK_SIZE_INCREMENT; + if (*StackPtr != NULL) { + Size = Size + (*StackEnd - *Stack); + } + + NewStack = AllocatePool (Size * MemberSize); + if (NewStack == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + if (*StackPtr != NULL) { + // + // Copy from Old Stack to the New Stack + // + CopyMem ( + NewStack, + *Stack, + (*StackEnd - *Stack) * MemberSize + ); + + // + // Free The Old Stack + // + 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; +} + +/** + Push an element onto the Stack. + + @param Stack On input: old stack; On output: new stack + @param StackPtr On input: old stack pointer; On output: new stack + pointer + @param StackEnd On input: old stack end; On output: new stack end + @param Data Data to push. + + @retval EFI_SUCCESS Push stack success. + +**/ +EFI_STATUS +PushConditionalStack ( + IN OUT FORM_EXPRESSION ***Stack, + IN OUT FORM_EXPRESSION ***StackPtr, + IN OUT FORM_EXPRESSION ***StackEnd, + IN FORM_EXPRESSION **Data + ) +{ + EFI_STATUS Status; + + // + // Check for a stack overflow condition + // + if (*StackPtr >= *StackEnd) { + // + // Grow the stack + // + Status = GrowConditionalStack (Stack, StackPtr, StackEnd, sizeof (FORM_EXPRESSION *)); + if (EFI_ERROR (Status)) { + return Status; + } + } + + // + // Push the item onto the stack + // + CopyMem (*StackPtr, Data, sizeof (FORM_EXPRESSION *)); + *StackPtr = *StackPtr + 1; + + return EFI_SUCCESS; + +} + +/** + Pop an element from the stack. + + @param Stack On input: old stack + @param StackPtr On input: old stack pointer; On output: new stack pointer + @param Data Data to pop. + + @retval EFI_SUCCESS The value was popped onto the stack. + @retval EFI_ACCESS_DENIED The pop operation underflowed the stack + +**/ +EFI_STATUS +PopConditionalStack ( + IN FORM_EXPRESSION **Stack, + IN OUT FORM_EXPRESSION ***StackPtr, + OUT FORM_EXPRESSION **Data + ) +{ + // + // Check for a stack underflow condition + // + if (*StackPtr == Stack) { + return EFI_ACCESS_DENIED; + } + + // + // Pop the item off the stack + // + *StackPtr = *StackPtr - 1; + CopyMem (Data, *StackPtr, sizeof (FORM_EXPRESSION *)); + return EFI_SUCCESS; + +} + +/** + Get the expression list count. + + @param Level Which type this expression belong to. Form, + statement or option? + + @retval >=0 The expression count + @retval -1 Input parameter error. + +**/ +INTN +GetConditionalExpressionCount ( + IN EXPRESS_LEVEL Level + ) +{ + switch (Level) { + case ExpressForm: + return mFormExpressionPointer - mFormExpressionStack; + case ExpressStatement: + return mStatementExpressionPointer - mStatementExpressionStack; + case ExpressOption: + return mOptionExpressionPointer - mOptionExpressionStack; + default: + ASSERT (FALSE); + return -1; + } +} + +/** + Get the expression Buffer pointer. + + @param Level Which type this expression belong to. Form, + statement or option? + + @retval The start pointer of the expression buffer or NULL. + +**/ +FORM_EXPRESSION ** +GetConditionalExpressionList ( + IN EXPRESS_LEVEL Level + ) +{ + switch (Level) { + case ExpressForm: + return mFormExpressionStack; + case ExpressStatement: + return mStatementExpressionStack; + case ExpressOption: + return mOptionExpressionStack; + default: + ASSERT (FALSE); + return NULL; + } +} + + +/** + Push the expression options onto the Stack. + + @param Pointer Pointer to the current expression. + @param Level Which type this expression belong to. Form, + statement or option? + + @retval EFI_SUCCESS The value was pushed onto the stack. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. + +**/ +EFI_STATUS +PushConditionalExpression ( + IN FORM_EXPRESSION *Pointer, + IN EXPRESS_LEVEL Level + ) +{ + switch (Level) { + case ExpressForm: + return PushConditionalStack ( + &mFormExpressionStack, + &mFormExpressionPointer, + &mFormExpressionEnd, + &Pointer + ); + case ExpressStatement: + return PushConditionalStack ( + &mStatementExpressionStack, + &mStatementExpressionPointer, + &mStatementExpressionEnd, + &Pointer + ); + case ExpressOption: + return PushConditionalStack ( + &mOptionExpressionStack, + &mOptionExpressionPointer, + &mOptionExpressionEnd, + &Pointer + ); + default: + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } +} + +/** + Pop the expression options from the Stack + + @param Level Which type this expression belong to. Form, + statement or option? + + @retval EFI_SUCCESS The value was pushed onto the stack. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. + +**/ +EFI_STATUS +PopConditionalExpression ( + IN EXPRESS_LEVEL Level + ) +{ + FORM_EXPRESSION *Pointer; + + switch (Level) { + case ExpressForm: + return PopConditionalStack ( + mFormExpressionStack, + &mFormExpressionPointer, + &Pointer + ); + + case ExpressStatement: + return PopConditionalStack ( + mStatementExpressionStack, + &mStatementExpressionPointer, + &Pointer + ); + + case ExpressOption: + return PopConditionalStack ( + mOptionExpressionStack, + &mOptionExpressionPointer, + &Pointer + ); + + default: + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } +} + + /** Push the list of map expression onto the Stack @@ -447,6 +745,7 @@ PopExpression ( **/ UINTN SaveExpressionEvaluationStackOffset ( + VOID ) { UINTN TempStackOffset; @@ -483,7 +782,7 @@ FORM_BROWSER_FORM * IdToForm ( IN FORM_BROWSER_FORMSET *FormSet, IN UINT16 FormId -) + ) { LIST_ENTRY *Link; FORM_BROWSER_FORM *Form; @@ -522,7 +821,7 @@ IdToQuestion2 ( LIST_ENTRY *Link; FORM_BROWSER_STATEMENT *Question; - if (QuestionId == 0) { + if (QuestionId == 0 || Form == NULL) { // // The value of zero is reserved // @@ -587,7 +886,7 @@ IdToQuestion ( // to keep synchronous, always reload the Question Value. // if (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) { - GetQuestionValue (FormSet, Form, Question, FALSE); + GetQuestionValue (FormSet, Form, Question, GetSetValueWithHiiDriver); } return Question; @@ -684,95 +983,236 @@ IfrStrToUpper ( } } - /** - Evaluate opcode EFI_IFR_TO_STRING. + Check whether this value type can be transfer to EFI_IFR_TYPE_BUFFER type. - @param FormSet Formset which contains this opcode. - @param Format String format in EFI_IFR_TO_STRING. - @param Result Evaluation result for this opcode. + EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to + EFI_IFR_TYPE_BUFFER when do the value compare. - @retval EFI_SUCCESS Opcode evaluation success. - @retval Other Opcode evaluation failed. + @param Value Expression value to compare on. + + @retval TRUE This value type can be transter to EFI_IFR_TYPE_BUFFER type. + @retval FALSE This value type can't be transter to EFI_IFR_TYPE_BUFFER type. **/ -EFI_STATUS -IfrToString ( - IN FORM_BROWSER_FORMSET *FormSet, - IN UINT8 Format, - OUT EFI_HII_VALUE *Result +BOOLEAN +IsTypeInBuffer ( + IN EFI_HII_VALUE *Value ) { - EFI_STATUS Status; - EFI_HII_VALUE Value; - CHAR16 *String; - CHAR16 *PrintFormat; - CHAR16 Buffer[MAXIMUM_VALUE_CHARACTERS]; - UINT8 *TmpBuf; - UINTN BufferSize; + switch (Value->Type) { + case EFI_IFR_TYPE_BUFFER: + case EFI_IFR_TYPE_DATE: + case EFI_IFR_TYPE_TIME: + case EFI_IFR_TYPE_REF: + return TRUE; - Status = PopExpression (&Value); - if (EFI_ERROR (Status)) { - return Status; + default: + return FALSE; } +} - switch (Value.Type) { +/** + Check whether this value type can be transfer to EFI_IFR_TYPE_UINT64 + + @param Value Expression value to compare on. + + @retval TRUE This value type can be transter to EFI_IFR_TYPE_BUFFER type. + @retval FALSE This value type can't be transter to EFI_IFR_TYPE_BUFFER type. + +**/ +BOOLEAN +IsTypeInUINT64 ( + IN EFI_HII_VALUE *Value + ) +{ + 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 = MAXIMUM_VALUE_CHARACTERS * sizeof (CHAR16); - switch (Format) { - case EFI_IFR_STRING_UNSIGNED_DEC: - case EFI_IFR_STRING_SIGNED_DEC: - PrintFormat = L"%ld"; - break; + case EFI_IFR_TYPE_BOOLEAN: + return TRUE; - case EFI_IFR_STRING_LOWERCASE_HEX: - PrintFormat = L"%lx"; - break; + default: + return FALSE; + } +} - case EFI_IFR_STRING_UPPERCASE_HEX: - PrintFormat = L"%lX"; - break; +/** + Return the buffer length for this value. - default: - return EFI_UNSUPPORTED; - } - UnicodeSPrint (Buffer, BufferSize, PrintFormat, Value.Value.u64); - String = Buffer; - break; + EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to + EFI_IFR_TYPE_BUFFER when do the value compare. - case EFI_IFR_TYPE_STRING: - CopyMem (Result, &Value, sizeof (EFI_HII_VALUE)); - return EFI_SUCCESS; + @param Value Expression value to compare on. - case EFI_IFR_TYPE_BOOLEAN: - String = (Value.Value.b) ? L"True" : L"False"; + @retval BufLen Return the buffer length. + +**/ +UINT16 +GetLengthForValue ( + IN EFI_HII_VALUE *Value + ) +{ + switch (Value->Type) { + case EFI_IFR_TYPE_BUFFER: + return Value->BufferLen; + + case EFI_IFR_TYPE_DATE: + return (UINT16) sizeof (EFI_HII_DATE); + + case EFI_IFR_TYPE_TIME: + return (UINT16) sizeof (EFI_HII_TIME); + + case EFI_IFR_TYPE_REF: + return (UINT16) sizeof (EFI_HII_REF); + + default: + return 0; + } +} + +/** + Return the buffer pointer for this value. + + EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to + EFI_IFR_TYPE_BUFFER when do the value compare. + + @param Value Expression value to compare on. + + @retval Buf Return the buffer pointer. + +**/ +UINT8 * +GetBufferForValue ( + IN EFI_HII_VALUE *Value + ) +{ + switch (Value->Type) { + case EFI_IFR_TYPE_BUFFER: + return Value->Buffer; + + case EFI_IFR_TYPE_DATE: + return (UINT8 *) (&Value->Value.date); + + case EFI_IFR_TYPE_TIME: + return (UINT8 *) (&Value->Value.time); + + case EFI_IFR_TYPE_REF: + return (UINT8 *) (&Value->Value.ref); + + default: + return NULL; + } +} + +/** + Evaluate opcode EFI_IFR_TO_STRING. + + @param FormSet Formset which contains this opcode. + @param Format String format in EFI_IFR_TO_STRING. + @param Result Evaluation result for this opcode. + + @retval EFI_SUCCESS Opcode evaluation success. + @retval Other Opcode evaluation failed. + +**/ +EFI_STATUS +IfrToString ( + IN FORM_BROWSER_FORMSET *FormSet, + IN UINT8 Format, + OUT EFI_HII_VALUE *Result + ) +{ + EFI_STATUS Status; + EFI_HII_VALUE Value; + CHAR16 *String; + CHAR16 *PrintFormat; + CHAR16 Buffer[MAXIMUM_VALUE_CHARACTERS]; + UINT8 *TmpBuf; + UINT8 *SrcBuf; + UINTN SrcLen; + 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 = MAXIMUM_VALUE_CHARACTERS * 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: + Result->Type = EFI_IFR_TYPE_UNDEFINED; + return EFI_SUCCESS; + } + UnicodeSPrint (Buffer, BufferSize, PrintFormat, Value.Value.u64); + String = Buffer; break; - + + case EFI_IFR_TYPE_STRING: + CopyMem (Result, &Value, sizeof (EFI_HII_VALUE)); + return EFI_SUCCESS; + + case EFI_IFR_TYPE_BOOLEAN: + String = (Value.Value.b) ? L"True" : L"False"; + break; + case EFI_IFR_TYPE_BUFFER: + case EFI_IFR_TYPE_DATE: + case EFI_IFR_TYPE_TIME: + case EFI_IFR_TYPE_REF: // - // + 3 is base on the unicode format, the length may be odd number, + // + 3 is base on the unicode format, the length may be odd number, // so need 1 byte to align, also need 2 bytes for L'\0'. // - TmpBuf = AllocateZeroPool (Value.BufferLen + 3); + if (Value.Type == EFI_IFR_TYPE_BUFFER) { + SrcLen = Value.BufferLen; + SrcBuf = Value.Buffer; + } else { + SrcBuf = GetBufferForValue(&Value); + SrcLen = GetLengthForValue(&Value); + } + + TmpBuf = AllocateZeroPool (SrcLen + 3); + ASSERT (TmpBuf != NULL); if (Format == EFI_IFR_STRING_ASCII) { - CopyMem (TmpBuf, Value.Buffer, Value.BufferLen); - PrintFormat = L"%a"; + CopyMem (TmpBuf, SrcBuf, SrcLen); + PrintFormat = L"%a"; } else { // Format == EFI_IFR_STRING_UNICODE - CopyMem (TmpBuf, Value.Buffer, Value.BufferLen * sizeof (CHAR16)); - PrintFormat = L"%s"; + CopyMem (TmpBuf, SrcBuf, SrcLen * sizeof (CHAR16)); + PrintFormat = L"%s"; } - UnicodeSPrint (Buffer, MAXIMUM_VALUE_CHARACTERS, PrintFormat, Value.Buffer); - String = Buffer; + UnicodeSPrint (Buffer, sizeof (Buffer), PrintFormat, TmpBuf); + String = Buffer; FreePool (TmpBuf); - FreePool (Value.Buffer); + if (Value.Type == EFI_IFR_TYPE_BUFFER) { + FreePool (Value.Buffer); + } break; - + default: - return EFI_UNSUPPORTED; + Result->Type = EFI_IFR_TYPE_UNDEFINED; + return EFI_SUCCESS; } Result->Type = EFI_IFR_TYPE_STRING; @@ -807,8 +1247,9 @@ IfrToUint ( return Status; } - if (Value.Type >= EFI_IFR_TYPE_OTHER && Value.Type != EFI_IFR_TYPE_BUFFER) { - return EFI_UNSUPPORTED; + if (Value.Type >= EFI_IFR_TYPE_OTHER && !IsTypeInBuffer(&Value)) { + Result->Type = EFI_IFR_TYPE_UNDEFINED; + return EFI_SUCCESS; } Status = EFI_SUCCESS; @@ -832,13 +1273,18 @@ IfrToUint ( Result->Value.u64 = StrDecimalToUint64 (String); } FreePool (String); - } else if (Value.Type == EFI_IFR_TYPE_BUFFER) { - if (Value.BufferLen > 8) { + } else if (IsTypeInBuffer(&Value)) { + if (GetLengthForValue (&Value) > 8) { + if (Value.Type == EFI_IFR_TYPE_BUFFER) { + FreePool (Value.Buffer); + } + Result->Type = EFI_IFR_TYPE_UNDEFINED; + return EFI_SUCCESS; + } + Result->Value.u64 = *(UINT64*) GetBufferForValue (&Value); + if (Value.Type == EFI_IFR_TYPE_BUFFER) { FreePool (Value.Buffer); - return EFI_UNSUPPORTED; } - Result->Value.u64 = *(UINT64*) Value.Buffer; - FreePool (Value.Buffer); } else { CopyMem (Result, &Value, sizeof (EFI_HII_VALUE)); } @@ -870,6 +1316,10 @@ IfrCatenate ( UINTN Index; CHAR16 *StringPtr; UINTN Size; + UINT16 Length0; + UINT16 Length1; + UINT8 *TmpBuf; + UINTN MaxLen; // // String[0] - The second string @@ -881,14 +1331,20 @@ IfrCatenate ( Status = EFI_SUCCESS; ZeroMem (Value, sizeof (Value)); - for (Index = 0; Index < 2; Index++) { - Status = PopExpression (&Value[Index]); - if (EFI_ERROR (Status)) { - goto Done; - } + Status = PopExpression (&Value[0]); + if (EFI_ERROR (Status)) { + goto Done; + } - if (Value[Index].Type != EFI_IFR_TYPE_STRING && Value[Index].Type != EFI_IFR_TYPE_BUFFER) { - Status = EFI_UNSUPPORTED; + Status = PopExpression (&Value[1]); + if (EFI_ERROR (Status)) { + goto Done; + } + + for (Index = 0; Index < 2; Index++) { + if (Value[Index].Type != EFI_IFR_TYPE_STRING && !IsTypeInBuffer(&Value[Index])) { + Result->Type = EFI_IFR_TYPE_UNDEFINED; + Status = EFI_SUCCESS; goto Done; } @@ -903,22 +1359,29 @@ IfrCatenate ( if (Value[0].Type == EFI_IFR_TYPE_STRING) { Size = StrSize (String[0]); - StringPtr= AllocatePool (StrSize (String[1]) + Size); + MaxLen = (StrSize (String[1]) + Size) / sizeof (CHAR16); + StringPtr= AllocatePool (MaxLen * sizeof (CHAR16)); ASSERT (StringPtr != NULL); - StrCpy (StringPtr, String[1]); - StrCat (StringPtr, String[0]); + StrCpyS (StringPtr, MaxLen, String[1]); + StrCatS (StringPtr, MaxLen, String[0]); Result->Type = EFI_IFR_TYPE_STRING; Result->Value.string = NewString (StringPtr, FormSet->HiiHandle); } else { Result->Type = EFI_IFR_TYPE_BUFFER; - Result->BufferLen = (UINT16) (Value[0].BufferLen + Value[1].BufferLen); + Length0 = GetLengthForValue(&Value[0]); + Length1 = GetLengthForValue(&Value[1]); + Result->BufferLen = (UINT16) (Length0 + Length1); Result->Buffer = AllocateZeroPool (Result->BufferLen); ASSERT (Result->Buffer != NULL); - CopyMem (Result->Buffer, Value[0].Buffer, Value[0].BufferLen); - CopyMem (&Result->Buffer[Value[0].BufferLen], Value[1].Buffer, Value[1].BufferLen); + TmpBuf = GetBufferForValue(&Value[0]); + ASSERT (TmpBuf != NULL); + CopyMem (Result->Buffer, TmpBuf, Length0); + TmpBuf = GetBufferForValue(&Value[1]); + ASSERT (TmpBuf != NULL); + CopyMem (&Result->Buffer[Length0], TmpBuf, Length1); } Done: if (Value[0].Buffer != NULL) { @@ -958,7 +1421,7 @@ IfrMatch ( ) { EFI_STATUS Status; - EFI_HII_VALUE Value; + EFI_HII_VALUE Value[2]; CHAR16 *String[2]; UINTN Index; @@ -969,18 +1432,26 @@ IfrMatch ( String[0] = NULL; String[1] = NULL; Status = EFI_SUCCESS; - for (Index = 0; Index < 2; Index++) { - Status = PopExpression (&Value); - if (EFI_ERROR (Status)) { - goto Done; - } + ZeroMem (Value, sizeof (Value)); + + Status = PopExpression (&Value[0]); + if (EFI_ERROR (Status)) { + goto Done; + } - if (Value.Type != EFI_IFR_TYPE_STRING) { - Status = EFI_UNSUPPORTED; + Status = PopExpression (&Value[1]); + if (EFI_ERROR (Status)) { + goto Done; + } + + for (Index = 0; Index < 2; Index++) { + if (Value[Index].Type != EFI_IFR_TYPE_STRING) { + Result->Type = EFI_IFR_TYPE_UNDEFINED; + Status = EFI_SUCCESS; goto Done; } - String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle); + String[Index] = GetToken (Value[Index].Value.string, FormSet->HiiHandle); if (String [Index] == NULL) { Status = EFI_NOT_FOUND; goto Done; @@ -1001,6 +1472,180 @@ Done: return Status; } +/** + Evaluate opcode EFI_IFR_MATCH2. + + @param FormSet Formset which contains this opcode. + @param SyntaxType Syntax type for match2. + @param Result Evaluation result for this opcode. + + @retval EFI_SUCCESS Opcode evaluation success. + @retval Other Opcode evaluation failed. + +**/ +EFI_STATUS +IfrMatch2 ( + IN FORM_BROWSER_FORMSET *FormSet, + IN EFI_GUID *SyntaxType, + OUT EFI_HII_VALUE *Result + ) +{ + EFI_STATUS Status; + EFI_HII_VALUE Value[2]; + CHAR16 *String[2]; + UINTN Index; + UINTN GuidIndex; + EFI_HANDLE *HandleBuffer; + UINTN BufferSize; + EFI_REGULAR_EXPRESSION_PROTOCOL *RegularExpressionProtocol; + UINTN RegExSyntaxTypeListSize; + EFI_REGEX_SYNTAX_TYPE *RegExSyntaxTypeList; + UINTN CapturesCount; + + // + // String[0] - The string to search + // String[1] - pattern + // + String[0] = NULL; + String[1] = NULL; + HandleBuffer = NULL; + RegExSyntaxTypeList = NULL; + Status = EFI_SUCCESS; + ZeroMem (Value, sizeof (Value)); + + Status = PopExpression (&Value[0]); + if (EFI_ERROR (Status)) { + goto Done; + } + + Status = PopExpression (&Value[1]); + if (EFI_ERROR (Status)) { + goto Done; + } + + for (Index = 0; Index < 2; Index++) { + if (Value[Index].Type != EFI_IFR_TYPE_STRING) { + Result->Type = EFI_IFR_TYPE_UNDEFINED; + Status = EFI_SUCCESS; + goto Done; + } + + String[Index] = GetToken (Value[Index].Value.string, FormSet->HiiHandle); + if (String [Index] == NULL) { + Status = EFI_NOT_FOUND; + goto Done; + } + } + + BufferSize = 0; + HandleBuffer = NULL; + Status = gBS->LocateHandle( + ByProtocol, + &gEfiRegularExpressionProtocolGuid, + NULL, + &BufferSize, + HandleBuffer); + if (Status == EFI_BUFFER_TOO_SMALL) { + HandleBuffer = AllocateZeroPool(BufferSize); + if (HandleBuffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + Status = gBS->LocateHandle( + ByProtocol, + &gEfiRegularExpressionProtocolGuid, + NULL, + &BufferSize, + HandleBuffer); + + } + + if (EFI_ERROR (Status)) { + Result->Type = EFI_IFR_TYPE_UNDEFINED; + Status = EFI_SUCCESS; + goto Done; + } + + ASSERT (HandleBuffer != NULL); + for ( Index = 0; Index < BufferSize / sizeof(EFI_HANDLE); Index ++) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiRegularExpressionProtocolGuid, + (VOID**)&RegularExpressionProtocol + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + RegExSyntaxTypeListSize = 0; + RegExSyntaxTypeList = NULL; + + Status = RegularExpressionProtocol->GetInfo ( + RegularExpressionProtocol, + &RegExSyntaxTypeListSize, + RegExSyntaxTypeList + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + RegExSyntaxTypeList = AllocateZeroPool(RegExSyntaxTypeListSize); + if (RegExSyntaxTypeList == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + Status = RegularExpressionProtocol->GetInfo ( + RegularExpressionProtocol, + &RegExSyntaxTypeListSize, + RegExSyntaxTypeList + ); + } else if (EFI_ERROR (Status)) { + goto Done; + } + + for (GuidIndex = 0; GuidIndex < RegExSyntaxTypeListSize / sizeof(EFI_GUID); GuidIndex++) { + if (CompareGuid (&RegExSyntaxTypeList[GuidIndex], SyntaxType)) { + // + // Find the match type, return the value. + // + Result->Type = EFI_IFR_TYPE_BOOLEAN; + Status = RegularExpressionProtocol->MatchString ( + RegularExpressionProtocol, + String[0], + String[1], + SyntaxType, + &Result->Value.b, + NULL, + &CapturesCount + ); + goto Done; + } + } + + if (RegExSyntaxTypeList != NULL) { + FreePool (RegExSyntaxTypeList); + } + } + + // + // Type specified by SyntaxType is not supported + // in any of the EFI_REGULAR_EXPRESSION_PROTOCOL instances. + // + Result->Type = EFI_IFR_TYPE_UNDEFINED; + Status = EFI_SUCCESS; + +Done: + if (String[0] != NULL) { + FreePool (String[0]); + } + if (String[1] != NULL) { + FreePool (String[1]); + } + if (RegExSyntaxTypeList != NULL) { + FreePool (RegExSyntaxTypeList); + } + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + } + return Status; +} /** Evaluate opcode EFI_IFR_FIND. @@ -1021,24 +1666,38 @@ IfrFind ( ) { EFI_STATUS Status; - EFI_HII_VALUE Value; + EFI_HII_VALUE Value[3]; CHAR16 *String[2]; UINTN Base; CHAR16 *StringPtr; UINTN Index; + ZeroMem (Value, sizeof (Value)); + if (Format > EFI_IFR_FF_CASE_INSENSITIVE) { - return EFI_UNSUPPORTED; + return EFI_INVALID_PARAMETER; } - Status = PopExpression (&Value); + Status = PopExpression (&Value[0]); if (EFI_ERROR (Status)) { return Status; } - if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) { - return EFI_UNSUPPORTED; + + Status = PopExpression (&Value[1]); + if (EFI_ERROR (Status)) { + return Status; } - Base = (UINTN) Value.Value.u64; + + Status = PopExpression (&Value[2]); + if (EFI_ERROR (Status)) { + return Status; + } + + if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) { + Result->Type = EFI_IFR_TYPE_UNDEFINED; + return EFI_SUCCESS; + } + Base = (UINTN) Value[0].Value.u64; // // String[0] - sub-string @@ -1047,17 +1706,13 @@ IfrFind ( String[0] = NULL; String[1] = NULL; for (Index = 0; Index < 2; Index++) { - Status = PopExpression (&Value); - if (EFI_ERROR (Status)) { + if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) { + Result->Type = EFI_IFR_TYPE_UNDEFINED; + Status = EFI_SUCCESS; goto Done; } - if (Value.Type != EFI_IFR_TYPE_STRING) { - Status = EFI_UNSUPPORTED; - goto Done; - } - - String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle); + String[Index] = GetToken (Value[Index + 1].Value.string, FormSet->HiiHandle); if (String[Index] == NULL) { Status = EFI_NOT_FOUND; goto Done; @@ -1108,41 +1763,49 @@ IfrMid ( ) { EFI_STATUS Status; - EFI_HII_VALUE Value; + EFI_HII_VALUE Value[3]; CHAR16 *String; UINTN Base; UINTN Length; CHAR16 *SubString; - UINT8 *Buffer; UINT16 BufferLen; + UINT8 *Buffer; - Status = PopExpression (&Value); + ZeroMem (Value, sizeof (Value)); + + Status = PopExpression (&Value[0]); 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); + Status = PopExpression (&Value[1]); 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); + Status = PopExpression (&Value[2]); if (EFI_ERROR (Status)) { return Status; } - if (Value.Type != EFI_IFR_TYPE_STRING && Value.Type != EFI_IFR_TYPE_BUFFER) { - return EFI_UNSUPPORTED; + + if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) { + Result->Type = EFI_IFR_TYPE_UNDEFINED; + return EFI_SUCCESS; } - if (Value.Type == EFI_IFR_TYPE_STRING) { - String = GetToken (Value.Value.string, FormSet->HiiHandle); + Length = (UINTN) Value[0].Value.u64; + + if (Value[1].Type > EFI_IFR_TYPE_NUM_SIZE_64) { + Result->Type = EFI_IFR_TYPE_UNDEFINED; + return EFI_SUCCESS; + } + Base = (UINTN) Value[1].Value.u64; + + if (Value[2].Type != EFI_IFR_TYPE_STRING && !IsTypeInBuffer(&Value[2])) { + Result->Type = EFI_IFR_TYPE_UNDEFINED; + return EFI_SUCCESS; + } + if (Value[2].Type == EFI_IFR_TYPE_STRING) { + String = GetToken (Value[2].Value.string, FormSet->HiiHandle); if (String == NULL) { return EFI_NOT_FOUND; } @@ -1161,23 +1824,25 @@ IfrMid ( FreePool (String); } else { - Buffer = Value.Buffer; - BufferLen = Value.BufferLen; - + BufferLen = GetLengthForValue (&Value[2]); + Buffer = GetBufferForValue (&Value[2]); + Result->Type = EFI_IFR_TYPE_BUFFER; if (Length == 0 || Base >= BufferLen) { Result->BufferLen = 0; Result->Buffer = NULL; } else { - Result->BufferLen = (UINT16)((BufferLen - Base) < Length ? (BufferLen - Base) : Length); + Result->BufferLen = (UINT16)((BufferLen - Base) < Length ? (BufferLen - Base) : Length); Result->Buffer = AllocateZeroPool (Result->BufferLen); ASSERT (Result->Buffer != NULL); - CopyMem (Result->Buffer, &Value.Buffer[Base], Result->BufferLen); + CopyMem (Result->Buffer, &Buffer[Base], Result->BufferLen); } - FreePool (Value.Buffer); + if (Value[2].Type == EFI_IFR_TYPE_BUFFER) { + FreePool (Value[2].Buffer); + } } - + return Status; } @@ -1199,7 +1864,7 @@ IfrToken ( ) { EFI_STATUS Status; - EFI_HII_VALUE Value; + EFI_HII_VALUE Value[3]; CHAR16 *String[2]; UINTN Count; CHAR16 *Delimiter; @@ -1207,14 +1872,28 @@ IfrToken ( CHAR16 *StringPtr; UINTN Index; - Status = PopExpression (&Value); + ZeroMem (Value, sizeof (Value)); + + Status = PopExpression (&Value[0]); if (EFI_ERROR (Status)) { return Status; } - if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) { - return EFI_UNSUPPORTED; + + Status = PopExpression (&Value[1]); + if (EFI_ERROR (Status)) { + return Status; } - Count = (UINTN) Value.Value.u64; + + Status = PopExpression (&Value[2]); + if (EFI_ERROR (Status)) { + return Status; + } + + if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) { + Result->Type = EFI_IFR_TYPE_UNDEFINED; + return EFI_SUCCESS; + } + Count = (UINTN) Value[0].Value.u64; // // String[0] - Delimiter @@ -1223,17 +1902,13 @@ IfrToken ( String[0] = NULL; String[1] = NULL; for (Index = 0; Index < 2; Index++) { - Status = PopExpression (&Value); - if (EFI_ERROR (Status)) { + if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) { + Result->Type = EFI_IFR_TYPE_UNDEFINED; + Status = EFI_SUCCESS; goto Done; } - if (Value.Type != EFI_IFR_TYPE_STRING) { - Status = EFI_UNSUPPORTED; - goto Done; - } - - String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle); + String[Index] = GetToken (Value[Index + 1].Value.string, FormSet->HiiHandle); if (String[Index] == NULL) { Status = EFI_NOT_FOUND; goto Done; @@ -1304,7 +1979,7 @@ IfrSpan ( ) { EFI_STATUS Status; - EFI_HII_VALUE Value; + EFI_HII_VALUE Value[3]; CHAR16 *String[2]; CHAR16 *Charset; UINTN Base; @@ -1312,14 +1987,28 @@ IfrSpan ( CHAR16 *StringPtr; BOOLEAN Found; - Status = PopExpression (&Value); + ZeroMem (Value, sizeof (Value)); + + Status = PopExpression (&Value[0]); if (EFI_ERROR (Status)) { return Status; } - if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) { - return EFI_UNSUPPORTED; + + Status = PopExpression (&Value[1]); + if (EFI_ERROR (Status)) { + return Status; } - Base = (UINTN) Value.Value.u64; + + Status = PopExpression (&Value[2]); + if (EFI_ERROR (Status)) { + return Status; + } + + if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) { + Result->Type = EFI_IFR_TYPE_UNDEFINED; + return EFI_SUCCESS; + } + Base = (UINTN) Value[0].Value.u64; // // String[0] - Charset @@ -1328,17 +2017,13 @@ IfrSpan ( 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; + if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) { + Result->Type = EFI_IFR_TYPE_UNDEFINED; + Status = EFI_SUCCESS; goto Done; } - String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle); + String[Index] = GetToken (Value[Index + 1].Value.string, FormSet->HiiHandle); if (String [Index] == NULL) { Status = EFI_NOT_FOUND; goto Done; @@ -1346,7 +2031,8 @@ IfrSpan ( } if (Base >= StrLen (String[1])) { - Status = EFI_UNSUPPORTED; + Result->Type = EFI_IFR_TYPE_UNDEFINED; + Status = EFI_SUCCESS; goto Done; } @@ -1439,47 +2125,89 @@ ExtendValueToU64 ( Value->Value.u64 = Temp; } +/** + Get UINT64 type value. + + @param Value Input Hii value. + + @retval UINT64 Return the UINT64 type value. + +**/ +UINT64 +HiiValueToUINT64 ( + IN EFI_HII_VALUE *Value + ) +{ + UINT64 RetVal; + + RetVal = 0; + + switch (Value->Type) { + case EFI_IFR_TYPE_NUM_SIZE_8: + RetVal = Value->Value.u8; + break; + + case EFI_IFR_TYPE_NUM_SIZE_16: + RetVal = Value->Value.u16; + break; + + case EFI_IFR_TYPE_NUM_SIZE_32: + RetVal = Value->Value.u32; + break; + + case EFI_IFR_TYPE_BOOLEAN: + RetVal = Value->Value.b; + break; + + case EFI_IFR_TYPE_DATE: + RetVal = *(UINT64*) &Value->Value.date; + break; + + case EFI_IFR_TYPE_TIME: + RetVal = (*(UINT64*) &Value->Value.time) & 0xffffff; + break; + + default: + RetVal = Value->Value.u64; + break; + } + + return RetVal; +} /** Compare two Hii value. @param Value1 Expression value to compare on left-hand. @param Value2 Expression value to compare on right-hand. + @param Result Return value after compare. + retval 0 Two operators equal. + return Positive value if Value1 is greater than Value2. + retval Negative value if Value1 is less than Value2. @param HiiHandle Only required for string compare. - @retval EFI_INVALID_PARAMETER Could not perform compare on two values. - @retval 0 Two operators equal. - @return Positive value if Value1 is greater than Value2. - @retval Negative value if Value1 is less than Value2. + @retval other Could not perform compare on two values. + @retval EFI_SUCCESS Compare the value success. **/ -INTN +EFI_STATUS CompareHiiValue ( IN EFI_HII_VALUE *Value1, IN EFI_HII_VALUE *Value2, + OUT INTN *Result, IN EFI_HII_HANDLE HiiHandle OPTIONAL ) { - INTN Result; INT64 Temp64; CHAR16 *Str1; CHAR16 *Str2; UINTN Len; + UINT8 *Buf1; + UINT16 Buf1Len; + UINT8 *Buf2; + UINT16 Buf2Len; - if (Value1->Type >= EFI_IFR_TYPE_OTHER || Value2->Type >= EFI_IFR_TYPE_OTHER ) { - if (Value1->Type != EFI_IFR_TYPE_BUFFER && Value2->Type != EFI_IFR_TYPE_BUFFER) { - 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->Type == EFI_IFR_TYPE_STRING && Value2->Type == EFI_IFR_TYPE_STRING) { if (Value1->Value.string == 0 || Value2->Value.string == 0) { // // StringId 0 is reserved @@ -1488,7 +2216,8 @@ CompareHiiValue ( } if (Value1->Value.string == Value2->Value.string) { - return 0; + *Result = 0; + return EFI_SUCCESS; } Str1 = GetToken (Value1->Value.string, HiiHandle); @@ -1496,56 +2225,61 @@ CompareHiiValue ( // // String not found // - return EFI_INVALID_PARAMETER; + return EFI_NOT_FOUND; } Str2 = GetToken (Value2->Value.string, HiiHandle); if (Str2 == NULL) { FreePool (Str1); - return EFI_INVALID_PARAMETER; + return EFI_NOT_FOUND; } - Result = StrCmp (Str1, Str2); + *Result = StrCmp (Str1, Str2); FreePool (Str1); FreePool (Str2); - return Result; + return EFI_SUCCESS; } - if (Value1->Type == EFI_IFR_TYPE_BUFFER || Value2->Type == EFI_IFR_TYPE_BUFFER ) { - if (Value1->Type != Value2->Type) { - // - // Both Operator should be type of Buffer. - // - return EFI_INVALID_PARAMETER; - } - Len = Value1->BufferLen > Value2->BufferLen ? Value2->BufferLen : Value1->BufferLen; - Result = CompareMem (Value1->Buffer, Value2->Buffer, Len); - if ((Result == 0) && (Value1->BufferLen != Value2->BufferLen)) - { + // + // Take types(date, time, ref, buffer) as buffer + // + if (IsTypeInBuffer(Value1) && IsTypeInBuffer(Value2)) { + Buf1 = GetBufferForValue(Value1); + Buf1Len = GetLengthForValue(Value1); + Buf2 = GetBufferForValue(Value2); + Buf2Len = GetLengthForValue(Value2); + + Len = Buf1Len > Buf2Len ? Buf2Len : Buf1Len; + *Result = CompareMem (Buf1, Buf2, Len); + if ((*Result == 0) && (Buf1Len != Buf2Len)) { // // In this case, means base on samll number buffer, the data is same // So which value has more data, which value is bigger. // - Result = Value1->BufferLen > Value2->BufferLen ? 1 : -1; + *Result = Buf1Len > Buf2Len ? 1 : -1; } - return Result; - } + return EFI_SUCCESS; + } // - // Take remain types(integer, boolean, date/time) as integer + // Take types(integer, boolean) as integer // - Temp64 = (INT64) (Value1->Value.u64 - Value2->Value.u64); - if (Temp64 > 0) { - Result = 1; - } else if (Temp64 < 0) { - Result = -1; - } else { - Result = 0; + if (IsTypeInUINT64(Value1) && IsTypeInUINT64(Value2)) { + Temp64 = HiiValueToUINT64(Value1) - HiiValueToUINT64(Value2); + if (Temp64 > 0) { + *Result = 1; + } else if (Temp64 < 0) { + *Result = -1; + } else { + *Result = 0; + } + + return EFI_SUCCESS; } - return Result; + return EFI_UNSUPPORTED; } /** @@ -1594,7 +2328,7 @@ CheckUserPrivilege ( /// Enumerate all user information of the current user profile /// to look for any EFI_USER_INFO_ACCESS_SETUP record. /// - + for (UserInfoHandle = NULL;;) { Status = mUserManager->GetNextInfo (mUserManager, UserProfileHandle, &UserInfoHandle); if (EFI_ERROR (Status)) { @@ -1631,24 +2365,136 @@ CheckUserPrivilege ( /// Check if current user has the privilege specified by the permissions GUID. /// - UserPermissionsGuid = (EFI_GUID *)(AccessControl + 1); - AccessControlDataSize = AccessControl->Size - sizeof (EFI_USER_INFO_ACCESS_CONTROL); - while (AccessControlDataSize >= sizeof (EFI_GUID)) { - if (CompareGuid (Guid, UserPermissionsGuid)) { - FreePool (UserInfo); - return TRUE; - } - UserPermissionsGuid++; - AccessControlDataSize -= sizeof (EFI_GUID); - } - } - RemainSize -= AccessControl->Size; - AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)((UINT8 *)AccessControl + AccessControl->Size); + UserPermissionsGuid = (EFI_GUID *)(AccessControl + 1); + AccessControlDataSize = AccessControl->Size - sizeof (EFI_USER_INFO_ACCESS_CONTROL); + while (AccessControlDataSize >= sizeof (EFI_GUID)) { + if (CompareGuid (Guid, UserPermissionsGuid)) { + FreePool (UserInfo); + return TRUE; + } + UserPermissionsGuid++; + AccessControlDataSize -= sizeof (EFI_GUID); + } + } + RemainSize -= AccessControl->Size; + AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)((UINT8 *)AccessControl + AccessControl->Size); + } + + FreePool (UserInfo); + } + return FALSE; +} + +/** + Get question value from the predefined formset. + + @param DevicePath The driver's device path which produece the formset data. + @param InputHiiHandle The hii handle associate with the formset data. + @param FormSetGuid The formset guid which include the question. + @param QuestionId The question id which need to get value from. + @param Value The return data about question's value. + + @retval TRUE Get the question value success. + @retval FALSE Get the question value failed. +**/ +BOOLEAN +GetQuestionValueFromForm ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN EFI_HII_HANDLE InputHiiHandle, + IN EFI_GUID *FormSetGuid, + IN EFI_QUESTION_ID QuestionId, + OUT EFI_HII_VALUE *Value + ) +{ + EFI_STATUS Status; + EFI_HII_HANDLE HiiHandle; + FORM_BROWSER_STATEMENT *Question; + FORM_BROWSER_FORMSET *FormSet; + FORM_BROWSER_FORM *Form; + BOOLEAN GetTheVal; + LIST_ENTRY *Link; + + // + // The input parameter DevicePath or InputHiiHandle must have one valid input. + // + ASSERT ((DevicePath != NULL && InputHiiHandle == NULL) || + (DevicePath == NULL && InputHiiHandle != NULL) ); + + GetTheVal = TRUE; + HiiHandle = NULL; + Question = NULL; + Form = NULL; + + // + // Get HiiHandle. + // + if (DevicePath != NULL) { + HiiHandle = DevicePathToHiiHandle (DevicePath, FormSetGuid); + if (HiiHandle == NULL) { + return FALSE; + } + } else { + HiiHandle = InputHiiHandle; + } + ASSERT (HiiHandle != NULL); + + // + // Get the formset data include this question. + // + FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET)); + ASSERT (FormSet != NULL); + Status = InitializeFormSet(HiiHandle, FormSetGuid, FormSet); + if (EFI_ERROR (Status)) { + GetTheVal = FALSE; + goto Done; + } + + // + // Base on the Question Id to get the question info. + // + Question = IdToQuestion(FormSet, NULL, QuestionId); + if (Question == NULL) { + GetTheVal = FALSE; + goto Done; + } + + // + // Search form 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) { + break; } - FreePool (UserInfo); + Link = GetNextNode (&FormSet->FormListHead, Link); + Form = NULL; } - return FALSE; + ASSERT (Form != NULL); + + // + // Get the question value. + // + Status = GetQuestionValue(FormSet, Form, Question, GetSetValueWithEditBuffer); + if (EFI_ERROR (Status)) { + GetTheVal = FALSE; + goto Done; + } + + CopyMem (Value, &Question->HiiValue, sizeof (EFI_HII_VALUE)); + +Done: + // + // Clean the formset structure and restore the global parameter. + // + if (FormSet != NULL) { + DestroyFormSet (FormSet); + } + + return GetTheVal; } /** @@ -1699,6 +2545,10 @@ EvaluateExpression ( UINT8 DigitUint8; UINT8 *TempBuffer; EFI_TIME EfiTime; + EFI_HII_VALUE QuestionVal; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + StrPtr = NULL; // // Save current stack offset. @@ -1729,13 +2579,18 @@ EvaluateExpression ( case EFI_IFR_EQ_ID_VAL_OP: Question = IdToQuestion (FormSet, Form, OpCode->QuestionId); if (Question == NULL) { - Status = EFI_NOT_FOUND; - goto Done; + Value->Type = EFI_IFR_TYPE_UNDEFINED; + break; } - Result = CompareHiiValue (&Question->HiiValue, &OpCode->Value, NULL); - if (Result == EFI_INVALID_PARAMETER) { - Status = EFI_INVALID_PARAMETER; + Status = CompareHiiValue (&Question->HiiValue, &OpCode->Value, &Result, NULL); + if (Status == EFI_UNSUPPORTED) { + Status = EFI_SUCCESS; + Value->Type = EFI_IFR_TYPE_UNDEFINED; + break; + } + + if (EFI_ERROR (Status)) { goto Done; } Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE); @@ -1744,29 +2599,33 @@ EvaluateExpression ( case EFI_IFR_EQ_ID_ID_OP: Question = IdToQuestion (FormSet, Form, OpCode->QuestionId); if (Question == NULL) { - Status = EFI_NOT_FOUND; - goto Done; + Value->Type = EFI_IFR_TYPE_UNDEFINED; + break; } Question2 = IdToQuestion (FormSet, Form, OpCode->QuestionId2); if (Question2 == NULL) { - Status = EFI_NOT_FOUND; - goto Done; + Value->Type = EFI_IFR_TYPE_UNDEFINED; + break; } - Result = CompareHiiValue (&Question->HiiValue, &Question2->HiiValue, FormSet->HiiHandle); - if (Result == EFI_INVALID_PARAMETER) { - Status = EFI_INVALID_PARAMETER; + Status = CompareHiiValue (&Question->HiiValue, &Question2->HiiValue, &Result, FormSet->HiiHandle); + if (Status == EFI_UNSUPPORTED) { + Value->Type = EFI_IFR_TYPE_UNDEFINED; + Status = EFI_SUCCESS; + break; + } + if (EFI_ERROR (Status)) { goto Done; } Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE); break; - case EFI_IFR_EQ_ID_LIST_OP: + case EFI_IFR_EQ_ID_VAL_LIST_OP: Question = IdToQuestion (FormSet, Form, OpCode->QuestionId); if (Question == NULL) { - Status = EFI_NOT_FOUND; - goto Done; + Value->Type = EFI_IFR_TYPE_UNDEFINED; + break; } Value->Value.b = FALSE; @@ -1823,7 +2682,7 @@ EvaluateExpression ( // // Get value from string except for STRING value. // - Status = GetValueByName (OpCode->VarStorage, OpCode->ValueName, &StrPtr); + Status = GetValueByName (OpCode->VarStorage, OpCode->ValueName, &StrPtr, GetSetValueWithEditBuffer); if (!EFI_ERROR (Status)) { ASSERT (StrPtr != NULL); TempLength = StrLen (StrPtr); @@ -1840,7 +2699,7 @@ EvaluateExpression ( TempBuffer [Index/2] = (UINT8) ((DigitUint8 << 4) + TempBuffer [Index/2]); } } - } + } } } break; @@ -1931,41 +2790,57 @@ EvaluateExpression ( break; case EFI_IFR_QUESTION_REF3_OP: - if (OpCode->DevicePath == 0) { - // - // EFI_IFR_QUESTION_REF3 - // Pop an expression from the expression stack - // - Status = PopExpression (Value); - if (EFI_ERROR (Status)) { - goto Done; - } + // + // 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; + // + // Validate the expression value + // + if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) { + Value->Type = EFI_IFR_TYPE_UNDEFINED; + break; + } + + if (OpCode->DevicePath != 0) { + Value->Type = EFI_IFR_TYPE_UNDEFINED; + + StrPtr = GetToken (OpCode->DevicePath, FormSet->HiiHandle); + if (StrPtr != NULL && mPathFromText != NULL) { + DevicePath = mPathFromText->ConvertTextToDevicePath(StrPtr); + if (DevicePath != NULL && GetQuestionValueFromForm(DevicePath, NULL, &OpCode->Guid, Value->Value.u16, &QuestionVal)) { + Value = &QuestionVal; + } + if (DevicePath != NULL) { + FreePool (DevicePath); + } } + if (StrPtr != NULL) { + FreePool (StrPtr); + } + } else if (IsZeroGuid (&OpCode->Guid)) { + if (!GetQuestionValueFromForm(NULL, FormSet->HiiHandle, &OpCode->Guid, Value->Value.u16, &QuestionVal)){ + Value->Type = EFI_IFR_TYPE_UNDEFINED; + break; + } + Value = &QuestionVal; + } else { Question = IdToQuestion (FormSet, Form, Value->Value.u16); if (Question == NULL) { - Status = EFI_NOT_FOUND; - goto Done; + Value->Type = EFI_IFR_TYPE_UNDEFINED; + break; } // // push the questions' value on to the expression stack // Value = &Question->HiiValue; - } else { - // - // BUGBUG: push 0 for EFI_IFR_QUESTION_REF3_2 and EFI_IFR_QUESTION_REF3_3, - // since it is impractical to evaluate the value of a Question in another - // Hii Package list. - // - ZeroMem (Value, sizeof (EFI_HII_VALUE)); } break; @@ -1975,16 +2850,17 @@ EvaluateExpression ( // RuleExpression = RuleIdToExpression (Form, OpCode->RuleId); if (RuleExpression == NULL) { - Status = EFI_NOT_FOUND; - goto Done; + Value->Type = EFI_IFR_TYPE_UNDEFINED; + break; } // // Evaluate this rule expression // Status = EvaluateExpression (FormSet, Form, RuleExpression); - if (EFI_ERROR (Status)) { - goto Done; + if (EFI_ERROR (Status) || RuleExpression->Result.Type == EFI_IFR_TYPE_UNDEFINED) { + Value->Type = EFI_IFR_TYPE_UNDEFINED; + break; } Value = &RuleExpression->Result; @@ -2020,9 +2896,9 @@ EvaluateExpression ( if (EFI_ERROR (Status)) { goto Done; } - if (Value->Type != EFI_IFR_TYPE_STRING && Value->Type != EFI_IFR_TYPE_BUFFER) { - Status = EFI_INVALID_PARAMETER; - goto Done; + if (Value->Type != EFI_IFR_TYPE_STRING && !IsTypeInBuffer (Value)) { + Value->Type = EFI_IFR_TYPE_UNDEFINED; + break; } if (Value->Type == EFI_IFR_TYPE_STRING) { @@ -2037,7 +2913,7 @@ EvaluateExpression ( FreePool (StrPtr); } else { Value->Type = EFI_IFR_TYPE_NUM_SIZE_64; - Value->Value.u64 = Value->BufferLen; + Value->Value.u64 = GetLengthForValue(Value); FreePool (Value->Buffer); } break; @@ -2048,8 +2924,8 @@ EvaluateExpression ( goto Done; } if (Value->Type != EFI_IFR_TYPE_BOOLEAN) { - Status = EFI_INVALID_PARAMETER; - goto Done; + Value->Type = EFI_IFR_TYPE_UNDEFINED; + break; } Value->Value.b = (BOOLEAN) (!Value->Value.b); break; @@ -2067,14 +2943,14 @@ EvaluateExpression ( // 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_UNDEFINED; + break; } Question = IdToQuestion (FormSet, Form, Value->Value.u16); if (Question == NULL) { - Status = EFI_NOT_FOUND; - goto Done; + Value->Type = EFI_IFR_TYPE_UNDEFINED; + break; } Value = &Question->HiiValue; @@ -2093,8 +2969,8 @@ EvaluateExpression ( // 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_UNDEFINED; + break; } Value->Type = EFI_IFR_TYPE_STRING; @@ -2128,40 +3004,39 @@ EvaluateExpression ( // When converting from an unsigned integer, zero will be converted to // FALSE and any other value will be converted to TRUE. // - Value->Value.b = (BOOLEAN) (Value->Value.u64 != 0); + Value->Value.b = (BOOLEAN) (HiiValueToUINT64(Value) != 0); 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. Otherwise, push Undefined. + // with "false" is True, then push False. Otherwise, push Undefined. // StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle); if (StrPtr == NULL) { Status = EFI_INVALID_PARAMETER; goto Done; } - + IfrStrToUpper (StrPtr); if (StrCmp (StrPtr, L"TRUE") == 0){ Value->Value.b = TRUE; + Value->Type = EFI_IFR_TYPE_BOOLEAN; } else if (StrCmp (StrPtr, L"FALSE") == 0) { Value->Value.b = FALSE; + Value->Type = EFI_IFR_TYPE_BOOLEAN; } else { - Status = EFI_INVALID_PARAMETER; - FreePool (StrPtr); - goto Done; + Value->Type = EFI_IFR_TYPE_UNDEFINED; } FreePool (StrPtr); - Value->Type = EFI_IFR_TYPE_BOOLEAN; } else if (Value->Type == EFI_IFR_TYPE_BUFFER) { // - // When converting from a buffer, if the buffer is all zeroes, - // then push False. Otherwise push True. + // When converting from a buffer, if the buffer is all zeroes, + // then push False. Otherwise push True. // for (Index =0; Index < Value->BufferLen; Index ++) { - if (Value->Buffer[Index] != 0) { + if (Value->Buffer[Index] != 0) { break; } } @@ -2197,8 +3072,8 @@ EvaluateExpression ( } if (Value->Type != EFI_IFR_TYPE_STRING) { - Status = EFI_UNSUPPORTED; - goto Done; + Value->Type = EFI_IFR_TYPE_UNDEFINED; + break; } StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle); @@ -2225,12 +3100,12 @@ EvaluateExpression ( goto Done; } if (Value->Type > EFI_IFR_TYPE_DATE) { - Status = EFI_INVALID_PARAMETER; - goto Done; + Value->Type = EFI_IFR_TYPE_UNDEFINED; + break; } Value->Type = EFI_IFR_TYPE_NUM_SIZE_64; - Value->Value.u64 = ~Value->Value.u64; + Value->Value.u64 = ~ HiiValueToUINT64(Value); break; case EFI_IFR_SET_OP: @@ -2256,16 +3131,23 @@ EvaluateExpression ( case EFI_HII_VARSTORE_NAME_VALUE: if (OpCode->ValueType != EFI_IFR_TYPE_STRING) { NameValue = AllocateZeroPool ((OpCode->ValueWidth * 2 + 1) * sizeof (CHAR16)); - ASSERT (Value != NULL); + ASSERT (NameValue != NULL); // // Convert Buffer to Hex String // TempBuffer = (UINT8 *) &Value->Value + OpCode->ValueWidth - 1; StrPtr = NameValue; for (Index = 0; Index < OpCode->ValueWidth; Index ++, TempBuffer --) { - StrPtr += UnicodeValueToString (StrPtr, PREFIX_ZERO | RADIX_HEX, *TempBuffer, 2); + UnicodeValueToStringS ( + StrPtr, + (OpCode->ValueWidth * 2 + 1) * sizeof (CHAR16) - ((UINTN)StrPtr - (UINTN)NameValue), + PREFIX_ZERO | RADIX_HEX, + *TempBuffer, + 2 + ); + StrPtr += StrnLenS (StrPtr, OpCode->ValueWidth * 2 + 1 - ((UINTN)StrPtr - (UINTN)NameValue) / sizeof (CHAR16)); } - Status = SetValueByName (OpCode->VarStorage, OpCode->ValueName, NameValue, TRUE); + Status = SetValueByName (OpCode->VarStorage, OpCode->ValueName, NameValue, GetSetValueWithEditBuffer, NULL); FreePool (NameValue); if (!EFI_ERROR (Status)) { Data1.Value.b = TRUE; @@ -2290,7 +3172,6 @@ EvaluateExpression ( // Status = EFI_UNSUPPORTED; goto Done; - break; } } else { // @@ -2370,10 +3251,6 @@ EvaluateExpression ( 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 @@ -2382,49 +3259,56 @@ EvaluateExpression ( if (EFI_ERROR (Status)) { goto Done; } + + if (Data2.Type > EFI_IFR_TYPE_DATE) { + Value->Type = EFI_IFR_TYPE_UNDEFINED; + break; + } + + if (Data1.Type > EFI_IFR_TYPE_DATE) { - Status = EFI_INVALID_PARAMETER; - goto Done; + Value->Type = EFI_IFR_TYPE_UNDEFINED; + break; } Value->Type = EFI_IFR_TYPE_NUM_SIZE_64; switch (OpCode->Operand) { case EFI_IFR_ADD_OP: - Value->Value.u64 = Data1.Value.u64 + Data2.Value.u64; + Value->Value.u64 = HiiValueToUINT64(&Data1) + HiiValueToUINT64(&Data2); break; case EFI_IFR_SUBTRACT_OP: - Value->Value.u64 = Data1.Value.u64 - Data2.Value.u64; + Value->Value.u64 = HiiValueToUINT64(&Data1) - HiiValueToUINT64(&Data2); break; case EFI_IFR_MULTIPLY_OP: - Value->Value.u64 = MultU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64); + Value->Value.u64 = MultU64x32 (HiiValueToUINT64(&Data1), (UINT32) HiiValueToUINT64(&Data2)); break; case EFI_IFR_DIVIDE_OP: - Value->Value.u64 = DivU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64); + Value->Value.u64 = DivU64x32 (HiiValueToUINT64(&Data1), (UINT32) HiiValueToUINT64(&Data2)); break; case EFI_IFR_MODULO_OP: - DivU64x32Remainder (Data1.Value.u64, (UINT32) Data2.Value.u64, &TempValue); + DivU64x32Remainder (HiiValueToUINT64(&Data1), (UINT32) HiiValueToUINT64(&Data2), &TempValue); Value->Value.u64 = TempValue; break; case EFI_IFR_BITWISE_AND_OP: - Value->Value.u64 = Data1.Value.u64 & Data2.Value.u64; + Value->Value.u64 = HiiValueToUINT64(&Data1) & HiiValueToUINT64(&Data2); break; case EFI_IFR_BITWISE_OR_OP: - Value->Value.u64 = Data1.Value.u64 | Data2.Value.u64; + Value->Value.u64 = HiiValueToUINT64(&Data1) | HiiValueToUINT64(&Data2); break; case EFI_IFR_SHIFT_LEFT_OP: - Value->Value.u64 = LShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64); + Value->Value.u64 = LShiftU64 (HiiValueToUINT64(&Data1), (UINTN) HiiValueToUINT64(&Data2)); break; case EFI_IFR_SHIFT_RIGHT_OP: - Value->Value.u64 = RShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64); + Value->Value.u64 = RShiftU64 (HiiValueToUINT64(&Data1), (UINTN) HiiValueToUINT64(&Data2)); break; default: @@ -2441,10 +3325,6 @@ EvaluateExpression ( 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 @@ -2453,9 +3333,15 @@ EvaluateExpression ( if (EFI_ERROR (Status)) { goto Done; } + + if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) { + Value->Type = EFI_IFR_TYPE_UNDEFINED; + break; + } + if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) { - Status = EFI_INVALID_PARAMETER; - goto Done; + Value->Type = EFI_IFR_TYPE_UNDEFINED; + break; } if (OpCode->Operand == EFI_IFR_AND_OP) { @@ -2478,12 +3364,6 @@ EvaluateExpression ( if (EFI_ERROR (Status)) { goto Done; } - if (Data2.Type > EFI_IFR_TYPE_BOOLEAN && - Data2.Type != EFI_IFR_TYPE_STRING && - Data2.Type != EFI_IFR_TYPE_BUFFER) { - Status = EFI_INVALID_PARAMETER; - goto Done; - } // // Pop another expression from the expression stack @@ -2493,14 +3373,35 @@ EvaluateExpression ( goto Done; } - Result = CompareHiiValue (&Data1, &Data2, FormSet->HiiHandle); + if (Data2.Type > EFI_IFR_TYPE_BOOLEAN && + Data2.Type != EFI_IFR_TYPE_STRING && + !IsTypeInBuffer(&Data2)) { + Value->Type = EFI_IFR_TYPE_UNDEFINED; + break; + } + + if (Data1.Type > EFI_IFR_TYPE_BOOLEAN && + Data1.Type != EFI_IFR_TYPE_STRING && + !IsTypeInBuffer(&Data1)) { + Value->Type = EFI_IFR_TYPE_UNDEFINED; + break; + } + + Status = CompareHiiValue (&Data1, &Data2, &Result, FormSet->HiiHandle); if (Data1.Type == EFI_IFR_TYPE_BUFFER) { FreePool (Data1.Buffer); + } + if (Data2.Type == EFI_IFR_TYPE_BUFFER) { FreePool (Data2.Buffer); } - - if (Result == EFI_INVALID_PARAMETER) { - Status = EFI_INVALID_PARAMETER; + + if (Status == EFI_UNSUPPORTED) { + Value->Type = EFI_IFR_TYPE_UNDEFINED; + Status = EFI_SUCCESS; + break; + } + + if (EFI_ERROR (Status)) { goto Done; } @@ -2539,10 +3440,14 @@ EvaluateExpression ( if (EFI_ERROR (Status)) { goto Done; } - + Status = IfrMatch (FormSet, Value); break; + case EFI_IFR_MATCH2_OP: + Status = IfrMatch2 (FormSet, &OpCode->Guid, Value); + break; + case EFI_IFR_CATENATE_OP: Status = IfrCatenate (FormSet, Value); break; @@ -2575,8 +3480,8 @@ EvaluateExpression ( goto Done; } if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) { - Status = EFI_INVALID_PARAMETER; - goto Done; + Value->Type = EFI_IFR_TYPE_UNDEFINED; + break; } if (Data1.Value.b) { @@ -2633,7 +3538,7 @@ EvaluateExpression ( // // Compare the expression value with current value // - if (CompareHiiValue (&Data1, &SubExpression->Result, NULL) == 0) { + if ((CompareHiiValue (&Data1, &SubExpression->Result, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) { // // Try get the map value. // @@ -2676,7 +3581,7 @@ EvaluateExpression ( default: break; } - if (EFI_ERROR (Status)) { + if (EFI_ERROR (Status) || Value->Type == EFI_IFR_TYPE_UNDEFINED) { goto Done; } @@ -2710,3 +3615,117 @@ Done: return Status; } + +/** + Check whether the result is TRUE or FALSE. + + For the EFI_HII_VALUE value type is numeric, return TRUE if the + value is not 0. + + @param Result Input the result data. + + @retval TRUE The result is TRUE. + @retval FALSE The result is FALSE. + +**/ +BOOLEAN +IsTrue ( + IN EFI_HII_VALUE *Result + ) +{ + switch (Result->Type) { + case EFI_IFR_TYPE_BOOLEAN: + return Result->Value.b; + + case EFI_IFR_TYPE_NUM_SIZE_8: + return (BOOLEAN)(Result->Value.u8 != 0); + + case EFI_IFR_TYPE_NUM_SIZE_16: + return (BOOLEAN)(Result->Value.u16 != 0); + + case EFI_IFR_TYPE_NUM_SIZE_32: + return (BOOLEAN)(Result->Value.u32 != 0); + + case EFI_IFR_TYPE_NUM_SIZE_64: + return (BOOLEAN)(Result->Value.u64 != 0); + + default: + return FALSE; + } +} + +/** + Return the result of the expression list. Check the expression list and + return the highest priority express result. + Priority: DisableIf > SuppressIf > GrayOutIf > FALSE + + @param ExpList The input expression list. + @param Evaluate Whether need to evaluate the expression first. + @param FormSet FormSet associated with this expression. + @param Form Form associated with this expression. + + @retval EXPRESS_RESULT Return the higher priority express result. + DisableIf > SuppressIf > GrayOutIf > FALSE + +**/ +EXPRESS_RESULT +EvaluateExpressionList ( + IN FORM_EXPRESSION_LIST *ExpList, + IN BOOLEAN Evaluate, + IN FORM_BROWSER_FORMSET *FormSet, OPTIONAL + IN FORM_BROWSER_FORM *Form OPTIONAL + ) +{ + UINTN Index; + EXPRESS_RESULT ReturnVal; + EXPRESS_RESULT CompareOne; + EFI_STATUS Status; + + if (ExpList == NULL) { + return ExpressFalse; + } + + ASSERT(ExpList->Signature == FORM_EXPRESSION_LIST_SIGNATURE); + Index = 0; + + // + // Check whether need to evaluate the expression first. + // + if (Evaluate) { + while (ExpList->Count > Index) { + Status = EvaluateExpression (FormSet, Form, ExpList->Expression[Index++]); + if (EFI_ERROR (Status)) { + return ExpressFalse; + } + } + } + + // + // Run the list of expressions. + // + ReturnVal = ExpressFalse; + for (Index = 0; Index < ExpList->Count; Index++) { + if (IsTrue (&ExpList->Expression[Index]->Result)) { + switch (ExpList->Expression[Index]->Type) { + case EFI_HII_EXPRESSION_SUPPRESS_IF: + CompareOne = ExpressSuppress; + break; + + case EFI_HII_EXPRESSION_GRAY_OUT_IF: + CompareOne = ExpressGrayOut; + break; + + case EFI_HII_EXPRESSION_DISABLE_IF: + CompareOne = ExpressDisable; + break; + + default: + return ExpressFalse; + } + + ReturnVal = ReturnVal < CompareOne ? CompareOne : ReturnVal; + } + } + + return ReturnVal; +}