From 2573712e0132deac7591f9ed5e2423c5e61e5af6 Mon Sep 17 00:00:00 2001 From: lgao4 Date: Thu, 25 Feb 2010 10:10:59 +0000 Subject: Enhance SetupBrowser to support new UEFI HiiFormMap feature git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10069 6f19259b-4bc3-4df7-8a09-765794883524 --- .../Universal/SetupBrowserDxe/Expression.c | 672 ++++++++++++++++++--- MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c | 262 +++++++- .../Universal/SetupBrowserDxe/Presentation.c | 6 +- MdeModulePkg/Universal/SetupBrowserDxe/Setup.c | 28 + MdeModulePkg/Universal/SetupBrowserDxe/Setup.h | 64 +- .../Universal/SetupBrowserDxe/SetupBrowserDxe.inf | 1 + MdeModulePkg/Universal/SetupBrowserDxe/Ui.h | 74 +++ 7 files changed, 1012 insertions(+), 95 deletions(-) (limited to 'MdeModulePkg/Universal/SetupBrowserDxe') diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Expression.c b/MdeModulePkg/Universal/SetupBrowserDxe/Expression.c index b429605662..90fdc7462f 100644 --- a/MdeModulePkg/Universal/SetupBrowserDxe/Expression.c +++ b/MdeModulePkg/Universal/SetupBrowserDxe/Expression.c @@ -24,6 +24,15 @@ EFI_HII_VALUE *mOpCodeScopeStackPointer = NULL; EFI_HII_VALUE *mExpressionEvaluationStack = NULL; EFI_HII_VALUE *mExpressionEvaluationStackEnd = NULL; EFI_HII_VALUE *mExpressionEvaluationStackPointer = NULL; +UINTN mExpressionEvaluationStackOffset = 0; + +EFI_HII_VALUE *mCurrentExpressionStack = NULL; +EFI_HII_VALUE *mCurrentExpressionEnd = NULL; +EFI_HII_VALUE *mCurrentExpressionPointer = NULL; + +EFI_HII_VALUE *mMapExpressionListStack = NULL; +EFI_HII_VALUE *mMapExpressionListEnd = NULL; +EFI_HII_VALUE *mMapExpressionListPointer = NULL; // // Unicode collation protocol interface @@ -140,10 +149,8 @@ PushStack ( /** Pop an element from 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 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. @@ -152,16 +159,15 @@ PushStack ( **/ EFI_STATUS PopStack ( - IN OUT EFI_HII_VALUE **Stack, + IN 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) { + if (*StackPtr == Stack) { return EFI_ACCESS_DENIED; } @@ -174,6 +180,144 @@ PopStack ( } +/** + Reset stack pointer to begin of the stack. + +**/ +VOID +ResetCurrentExpressionStack ( + VOID + ) +{ + mCurrentExpressionPointer = mCurrentExpressionStack; +} + + +/** + Push current expression onto the Stack + + @param Pointer Pointer to current expression. + + @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 +PushCurrentExpression ( + IN VOID *Pointer + ) +{ + EFI_HII_VALUE Data; + + Data.Type = EFI_IFR_TYPE_NUM_SIZE_64; + Data.Value.u64 = (UINT64) (UINTN) Pointer; + + return PushStack ( + &mCurrentExpressionStack, + &mCurrentExpressionPointer, + &mCurrentExpressionEnd, + &Data + ); +} + + +/** + Pop current expression from the Stack + + @param Pointer Pointer to current expression to be pop. + + @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 +PopCurrentExpression ( + OUT VOID **Pointer + ) +{ + EFI_STATUS Status; + EFI_HII_VALUE Data; + + Status = PopStack ( + mCurrentExpressionStack, + &mCurrentExpressionPointer, + &Data + ); + + *Pointer = (VOID *) (UINTN) Data.Value.u64; + + return Status; +} + +/** + Reset stack pointer to begin of the stack. + +**/ +VOID +ResetMapExpressionListStack ( + VOID + ) +{ + mMapExpressionListPointer = mMapExpressionListStack; +} + + +/** + Push the list of map expression onto the Stack + + @param Pointer Pointer to the list of map expression to be pushed. + + @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 +PushMapExpressionList ( + IN VOID *Pointer + ) +{ + EFI_HII_VALUE Data; + + Data.Type = EFI_IFR_TYPE_NUM_SIZE_64; + Data.Value.u64 = (UINT64) (UINTN) Pointer; + + return PushStack ( + &mMapExpressionListStack, + &mMapExpressionListPointer, + &mMapExpressionListEnd, + &Data + ); +} + + +/** + Pop the list of map expression from the Stack + + @param Pointer Pointer to the list of map expression to be pop. + + @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 +PopMapExpressionList ( + OUT VOID **Pointer + ) +{ + EFI_STATUS Status; + EFI_HII_VALUE Data; + + Status = PopStack ( + mMapExpressionListStack, + &mMapExpressionListPointer, + &Data + ); + + *Pointer = (VOID *) (UINTN) Data.Value.u64; + + return Status; +} + /** Reset stack pointer to begin of the stack. @@ -235,9 +379,8 @@ PopScope ( EFI_HII_VALUE Data; Status = PopStack ( - &mOpCodeScopeStack, + mOpCodeScopeStack, &mOpCodeScopeStackPointer, - &mOpCodeScopeStackEnd, &Data ); @@ -247,19 +390,6 @@ PopScope ( } -/** - Reset stack pointer to begin of the stack. - -**/ -VOID -ResetExpressionStack ( - VOID - ) -{ - mExpressionEvaluationStackPointer = mExpressionEvaluationStack; -} - - /** Push an Expression value onto the Stack @@ -299,13 +429,40 @@ PopExpression ( ) { return PopStack ( - &mExpressionEvaluationStack, + mExpressionEvaluationStack + mExpressionEvaluationStackOffset, &mExpressionEvaluationStackPointer, - &mExpressionEvaluationStackEnd, Value ); } +/** + Get current stack offset from stack start. + + @return Stack offset to stack start. +**/ +UINTN +SaveExpressionEvaluationStackOffset ( + ) +{ + UINTN TempStackOffset; + TempStackOffset = mExpressionEvaluationStackOffset; + mExpressionEvaluationStackOffset = mExpressionEvaluationStackPointer - mExpressionEvaluationStack; + return TempStackOffset; +} + +/** + Restore stack offset based on input stack offset + + @param StackOffset Offset to stack start. + +**/ +VOID +RestoreExpressionEvaluationStackOffset ( + UINTN StackOffset + ) +{ + mExpressionEvaluationStackOffset = StackOffset; +} /** Get Form given its FormId. @@ -1218,8 +1375,8 @@ ExtendValueToU64 ( @param Value2 Expression value to compare on right-hand. @param HiiHandle Only required for string compare. - @retval EFI_INVALID_PARAMETER Could not perform comparation on two values. - @retval 0 Two operators equeal. + @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. @@ -1437,12 +1594,21 @@ EvaluateExpression ( EFI_HII_VALUE *Value; INTN Result; CHAR16 *StrPtr; + CHAR16 *NameValue; UINT32 TempValue; + LIST_ENTRY *SubExpressionLink; + FORM_EXPRESSION *SubExpression; + UINTN StackOffset; + UINTN TempLength; + CHAR16 TempStr[5]; + UINT8 DigitUint8; + UINT8 *TempBuffer; + EFI_TIME EfiTime; // - // Always reset the stack before evaluating an Expression + // Save current stack offset. // - ResetExpressionStack (); + StackOffset = SaveExpressionEvaluationStackOffset (); ASSERT (Expression != NULL); Expression->Result.Type = EFI_IFR_TYPE_OTHER; @@ -1468,12 +1634,14 @@ EvaluateExpression ( case EFI_IFR_EQ_ID_VAL_OP: Question = IdToQuestion (FormSet, Form, OpCode->QuestionId); if (Question == NULL) { - return EFI_NOT_FOUND; + Status = EFI_NOT_FOUND; + goto Done; } Result = CompareHiiValue (&Question->HiiValue, &OpCode->Value, NULL); if (Result == EFI_INVALID_PARAMETER) { - return EFI_INVALID_PARAMETER; + Status = EFI_INVALID_PARAMETER; + goto Done; } Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE); break; @@ -1481,17 +1649,20 @@ EvaluateExpression ( case EFI_IFR_EQ_ID_ID_OP: Question = IdToQuestion (FormSet, Form, OpCode->QuestionId); if (Question == NULL) { - return EFI_NOT_FOUND; + Status = EFI_NOT_FOUND; + goto Done; } Question2 = IdToQuestion (FormSet, Form, OpCode->QuestionId2); if (Question2 == NULL) { - return EFI_NOT_FOUND; + Status = EFI_NOT_FOUND; + goto Done; } Result = CompareHiiValue (&Question->HiiValue, &Question2->HiiValue, FormSet->HiiHandle); if (Result == EFI_INVALID_PARAMETER) { - return EFI_INVALID_PARAMETER; + Status = EFI_INVALID_PARAMETER; + goto Done; } Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE); break; @@ -1499,7 +1670,8 @@ EvaluateExpression ( case EFI_IFR_EQ_ID_LIST_OP: Question = IdToQuestion (FormSet, Form, OpCode->QuestionId); if (Question == NULL) { - return EFI_NOT_FOUND; + Status = EFI_NOT_FOUND; + goto Done; } Value->Value.b = FALSE; @@ -1514,7 +1686,7 @@ EvaluateExpression ( case EFI_IFR_DUP_OP: Status = PopExpression (Value); if (EFI_ERROR (Status)) { - return Status; + goto Done; } Status = PushExpression (Value); @@ -1524,7 +1696,8 @@ EvaluateExpression ( case EFI_IFR_THIS_OP: Question = IdToQuestion (FormSet, Form, OpCode->QuestionId); if (Question == NULL) { - return EFI_NOT_FOUND; + Status = EFI_NOT_FOUND; + goto Done; } Value = &Question->HiiValue; @@ -1534,6 +1707,131 @@ EvaluateExpression ( Value->Value.b = CheckUserPrivilege (&OpCode->Guid); break; + case EFI_IFR_GET_OP: + // + // Get Value from VarStore buffer, EFI VarStore, Name/Value VarStore. + // + Value->Type = EFI_IFR_TYPE_UNDEFINED; + Value->Value.u8 = 0; + if (OpCode->VarStorage != NULL) { + switch (OpCode->VarStorage->Type) { + case EFI_HII_VARSTORE_BUFFER: + // + // Get value from Edit Buffer + // + Value->Type = OpCode->ValueType; + CopyMem (&Value->Value, OpCode->VarStorage->EditBuffer + OpCode->VarStoreInfo.VarOffset, OpCode->ValueWidth); + break; + case EFI_HII_VARSTORE_NAME_VALUE: + if (OpCode->ValueType != EFI_IFR_TYPE_STRING) { + // + // Get value from string except for STRING value. + // + Status = GetValueByName (OpCode->VarStorage, OpCode->ValueName, &StrPtr); + if (!EFI_ERROR (Status)) { + TempLength = StrLen (StrPtr); + if (OpCode->ValueWidth >= ((TempLength + 1) / 2)) { + Value->Type = OpCode->ValueType; + TempBuffer = (UINT8 *) &Value->Value; + ZeroMem (TempStr, sizeof (TempStr)); + for (Index = 0; Index < TempLength; Index ++) { + TempStr[0] = StrPtr[TempLength - Index - 1]; + DigitUint8 = (UINT8) StrHexToUint64 (TempStr); + if ((Index & 1) == 0) { + TempBuffer [Index/2] = DigitUint8; + } else { + TempBuffer [Index/2] = (UINT8) ((DigitUint8 << 4) + TempStr [Index/2]); + } + } + } + } + } + break; + case EFI_HII_VARSTORE_EFI_VARIABLE: + // + // Get value from variable. + // + TempLength = OpCode->ValueWidth; + Value->Type = OpCode->ValueType; + Status = gRT->GetVariable ( + OpCode->ValueName, + &OpCode->VarStorage->Guid, + NULL, + &TempLength, + &Value->Value + ); + if (EFI_ERROR (Status)) { + Value->Type = EFI_IFR_TYPE_UNDEFINED; + Value->Value.u8 = 0; + } + default: + // + // Not recognize storage. + // + Status = EFI_UNSUPPORTED; + goto Done; + } + } else { + // + // For Time/Date Data + // + if (OpCode->ValueType != EFI_IFR_TYPE_DATE && OpCode->ValueType != EFI_IFR_TYPE_TIME) { + // + // Only support Data/Time data when storage doesn't exist. + // + Status = EFI_UNSUPPORTED; + goto Done; + } + Status = gRT->GetTime (&EfiTime, NULL); + if (!EFI_ERROR (Status)) { + if (OpCode->ValueType == EFI_IFR_TYPE_DATE) { + switch (OpCode->VarStoreInfo.VarOffset) { + case 0x00: + Value->Type = EFI_IFR_TYPE_NUM_SIZE_16; + Value->Value.u16 = EfiTime.Year; + break; + case 0x02: + Value->Type = EFI_IFR_TYPE_NUM_SIZE_8; + Value->Value.u8 = EfiTime.Month; + break; + case 0x03: + Value->Type = EFI_IFR_TYPE_NUM_SIZE_8; + Value->Value.u8 = EfiTime.Day; + break; + default: + // + // Invalid Date field. + // + Status = EFI_INVALID_PARAMETER; + goto Done; + } + } else { + switch (OpCode->VarStoreInfo.VarOffset) { + case 0x00: + Value->Type = EFI_IFR_TYPE_NUM_SIZE_8; + Value->Value.u8 = EfiTime.Hour; + break; + case 0x01: + Value->Type = EFI_IFR_TYPE_NUM_SIZE_8; + Value->Value.u8 = EfiTime.Minute; + break; + case 0x02: + Value->Type = EFI_IFR_TYPE_NUM_SIZE_8; + Value->Value.u8 = EfiTime.Second; + break; + default: + // + // Invalid Time field. + // + Status = EFI_INVALID_PARAMETER; + goto Done; + } + } + } + } + + break; + case EFI_IFR_QUESTION_REF3_OP: if (OpCode->DevicePath == 0) { // @@ -1542,19 +1840,21 @@ EvaluateExpression ( // Status = PopExpression (Value); if (EFI_ERROR (Status)) { - return Status; + goto Done; } // // Validate the expression value // if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) { - return EFI_NOT_FOUND; + Status = EFI_NOT_FOUND; + goto Done; } Question = IdToQuestion (FormSet, Form, Value->Value.u16); if (Question == NULL) { - return EFI_NOT_FOUND; + Status = EFI_NOT_FOUND; + goto Done; } // @@ -1577,7 +1877,8 @@ EvaluateExpression ( // RuleExpression = RuleIdToExpression (Form, OpCode->RuleId); if (RuleExpression == NULL) { - return EFI_NOT_FOUND; + Status = EFI_NOT_FOUND; + goto Done; } // @@ -1585,7 +1886,7 @@ EvaluateExpression ( // Status = EvaluateExpression (FormSet, Form, RuleExpression); if (EFI_ERROR (Status)) { - return Status; + goto Done; } Value = &RuleExpression->Result; @@ -1619,15 +1920,17 @@ EvaluateExpression ( case EFI_IFR_LENGTH_OP: Status = PopExpression (Value); if (EFI_ERROR (Status)) { - return Status; + goto Done; } if (Value->Type != EFI_IFR_TYPE_STRING) { - return EFI_INVALID_PARAMETER; + Status = EFI_INVALID_PARAMETER; + goto Done; } StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle); if (StrPtr == NULL) { - return EFI_INVALID_PARAMETER; + Status = EFI_INVALID_PARAMETER; + goto Done; } Value->Type = EFI_IFR_TYPE_NUM_SIZE_64; @@ -1638,10 +1941,11 @@ EvaluateExpression ( case EFI_IFR_NOT_OP: Status = PopExpression (Value); if (EFI_ERROR (Status)) { - return Status; + goto Done; } if (Value->Type != EFI_IFR_TYPE_BOOLEAN) { - return EFI_INVALID_PARAMETER; + Status = EFI_INVALID_PARAMETER; + goto Done; } Value->Value.b = (BOOLEAN) (!Value->Value.b); break; @@ -1652,19 +1956,21 @@ EvaluateExpression ( // Status = PopExpression (Value); if (EFI_ERROR (Status)) { - return Status; + goto Done; } // // Validate the expression value // if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) { - return EFI_NOT_FOUND; + Status = EFI_NOT_FOUND; + goto Done; } Question = IdToQuestion (FormSet, Form, Value->Value.u16); if (Question == NULL) { - return EFI_NOT_FOUND; + Status = EFI_NOT_FOUND; + goto Done; } Value = &Question->HiiValue; @@ -1676,14 +1982,15 @@ EvaluateExpression ( // Status = PopExpression (Value); if (EFI_ERROR (Status)) { - return Status; + goto Done; } // // Validate the expression value // if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) { - return EFI_NOT_FOUND; + Status = EFI_NOT_FOUND; + goto Done; } Value->Type = EFI_IFR_TYPE_STRING; @@ -1706,7 +2013,7 @@ EvaluateExpression ( // Status = PopExpression (Value); if (EFI_ERROR (Status)) { - return Status; + goto Done; } // @@ -1728,7 +2035,8 @@ EvaluateExpression ( // StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle); if (StrPtr == NULL) { - return EFI_INVALID_PARAMETER; + Status = EFI_INVALID_PARAMETER; + goto Done; } if ((StrCmp (StrPtr, L"true") == 0) || (StrCmp (StrPtr, L"false") == 0)){ @@ -1753,21 +2061,23 @@ EvaluateExpression ( case EFI_IFR_TO_UPPER_OP: Status = InitializeUnicodeCollationProtocol (); if (EFI_ERROR (Status)) { - return Status; + goto Done; } Status = PopExpression (Value); if (EFI_ERROR (Status)) { - return Status; + goto Done; } if (Value->Type != EFI_IFR_TYPE_STRING) { - return EFI_UNSUPPORTED; + Status = EFI_UNSUPPORTED; + goto Done; } StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle); if (StrPtr == NULL) { - return EFI_NOT_FOUND; + Status = EFI_NOT_FOUND; + goto Done; } if (OpCode->Operand == EFI_IFR_TO_LOWER_OP) { @@ -1785,16 +2095,134 @@ EvaluateExpression ( // Status = PopExpression (Value); if (EFI_ERROR (Status)) { - return Status; + goto Done; } if (Value->Type > EFI_IFR_TYPE_DATE) { - return EFI_INVALID_PARAMETER; + Status = EFI_INVALID_PARAMETER; + goto Done; } Value->Type = EFI_IFR_TYPE_NUM_SIZE_64; Value->Value.u64 = ~Value->Value.u64; break; + case EFI_IFR_SET_OP: + // + // Pop an expression from the expression stack + // + Status = PopExpression (Value); + if (EFI_ERROR (Status)) { + goto Done; + } + Data1.Type = EFI_IFR_TYPE_BOOLEAN; + Data1.Value.b = FALSE; + // + // Set value to var storage buffer + // + if (OpCode->VarStorage != NULL) { + switch (OpCode->VarStorage->Type) { + case EFI_HII_VARSTORE_BUFFER: + CopyMem (OpCode->VarStorage->EditBuffer + OpCode->VarStoreInfo.VarOffset, &Value->Value, OpCode->ValueWidth); + Data1.Value.b = TRUE; + break; + case EFI_HII_VARSTORE_NAME_VALUE: + if (OpCode->ValueType != EFI_IFR_TYPE_STRING) { + NameValue = AllocateZeroPool ((OpCode->ValueWidth * 2 + 1) * sizeof (CHAR16)); + ASSERT (Value != 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); + } + Status = SetValueByName (OpCode->VarStorage, OpCode->ValueName, NameValue); + FreePool (NameValue); + if (!EFI_ERROR (Status)) { + Data1.Value.b = TRUE; + } + } + break; + case EFI_HII_VARSTORE_EFI_VARIABLE: + Status = gRT->SetVariable ( + OpCode->ValueName, + &OpCode->VarStorage->Guid, + OpCode->VarStorage->Attributes, + OpCode->ValueWidth, + &Value->Value + ); + if (!EFI_ERROR (Status)) { + Data1.Value.b = TRUE; + } + break; + default: + // + // Not recognize storage. + // + Status = EFI_UNSUPPORTED; + goto Done; + break; + } + } else { + // + // For Time/Date Data + // + if (OpCode->ValueType != EFI_IFR_TYPE_DATE && OpCode->ValueType != EFI_IFR_TYPE_TIME) { + // + // Only support Data/Time data when storage doesn't exist. + // + Status = EFI_UNSUPPORTED; + goto Done; + } + Status = gRT->GetTime (&EfiTime, NULL); + if (!EFI_ERROR (Status)) { + if (OpCode->ValueType == EFI_IFR_TYPE_DATE) { + switch (OpCode->VarStoreInfo.VarOffset) { + case 0x00: + EfiTime.Year = Value->Value.u16; + break; + case 0x02: + EfiTime.Month = Value->Value.u8; + break; + case 0x03: + EfiTime.Day = Value->Value.u8; + break; + default: + // + // Invalid Date field. + // + Status = EFI_INVALID_PARAMETER; + goto Done; + } + } else { + switch (OpCode->VarStoreInfo.VarOffset) { + case 0x00: + EfiTime.Hour = Value->Value.u8; + break; + case 0x01: + EfiTime.Minute = Value->Value.u8; + break; + case 0x02: + EfiTime.Second = Value->Value.u8; + break; + default: + // + // Invalid Time field. + // + Status = EFI_INVALID_PARAMETER; + goto Done; + } + } + Status = gRT->SetTime (&EfiTime); + if (!EFI_ERROR (Status)) { + Data1.Value.b = TRUE; + } + } + } + Value = &Data1; + break; + // // binary-op // @@ -1812,10 +2240,11 @@ EvaluateExpression ( // Status = PopExpression (&Data2); if (EFI_ERROR (Status)) { - return Status; + goto Done; } if (Data2.Type > EFI_IFR_TYPE_DATE) { - return EFI_INVALID_PARAMETER; + Status = EFI_INVALID_PARAMETER; + goto Done; } // @@ -1823,10 +2252,11 @@ EvaluateExpression ( // Status = PopExpression (&Data1); if (EFI_ERROR (Status)) { - return Status; + goto Done; } if (Data1.Type > EFI_IFR_TYPE_DATE) { - return EFI_INVALID_PARAMETER; + Status = EFI_INVALID_PARAMETER; + goto Done; } Value->Type = EFI_IFR_TYPE_NUM_SIZE_64; @@ -1881,10 +2311,11 @@ EvaluateExpression ( // Status = PopExpression (&Data2); if (EFI_ERROR (Status)) { - return Status; + goto Done; } if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) { - return EFI_INVALID_PARAMETER; + Status = EFI_INVALID_PARAMETER; + goto Done; } // @@ -1892,10 +2323,11 @@ EvaluateExpression ( // Status = PopExpression (&Data1); if (EFI_ERROR (Status)) { - return Status; + goto Done; } if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) { - return EFI_INVALID_PARAMETER; + Status = EFI_INVALID_PARAMETER; + goto Done; } if (OpCode->Operand == EFI_IFR_AND_OP) { @@ -1916,10 +2348,11 @@ EvaluateExpression ( // Status = PopExpression (&Data2); if (EFI_ERROR (Status)) { - return Status; + goto Done; } if (Data2.Type > EFI_IFR_TYPE_BOOLEAN && Data2.Type != EFI_IFR_TYPE_STRING) { - return EFI_INVALID_PARAMETER; + Status = EFI_INVALID_PARAMETER; + goto Done; } // @@ -1927,12 +2360,13 @@ EvaluateExpression ( // Status = PopExpression (&Data1); if (EFI_ERROR (Status)) { - return Status; + goto Done; } Result = CompareHiiValue (&Data1, &Data2, FormSet->HiiHandle); if (Result == EFI_INVALID_PARAMETER) { - return EFI_INVALID_PARAMETER; + Status = EFI_INVALID_PARAMETER; + goto Done; } switch (OpCode->Operand) { @@ -1982,7 +2416,7 @@ EvaluateExpression ( // Status = PopExpression (&Data3); if (EFI_ERROR (Status)) { - return Status; + goto Done; } // @@ -1990,7 +2424,7 @@ EvaluateExpression ( // Status = PopExpression (&Data2); if (EFI_ERROR (Status)) { - return Status; + goto Done; } // @@ -1998,10 +2432,11 @@ EvaluateExpression ( // Status = PopExpression (&Data1); if (EFI_ERROR (Status)) { - return Status; + goto Done; } if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) { - return EFI_INVALID_PARAMETER; + Status = EFI_INVALID_PARAMETER; + goto Done; } if (Data1.Value.b) { @@ -2027,16 +2462,87 @@ EvaluateExpression ( Status = IfrSpan (FormSet, OpCode->Flags, Value); break; + case EFI_IFR_MAP_OP: + // + // Pop the check value + // + Status = PopExpression (&Data1); + if (EFI_ERROR (Status)) { + goto Done; + } + // + // Check MapExpression list is valid. + // + if (OpCode->MapExpressionList.ForwardLink == NULL) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + // + // Go through map expression list. + // + SubExpressionLink = GetFirstNode(&OpCode->MapExpressionList); + while (!IsNull (&OpCode->MapExpressionList, SubExpressionLink)) { + SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink); + // + // Evaluate the first expression in this pair. + // + Status = EvaluateExpression (FormSet, Form, SubExpression); + if (EFI_ERROR (Status)) { + goto Done; + } + // + // Compare the expression value with current value + // + if (CompareHiiValue (&Data1, &SubExpression->Result, NULL) == 0) { + // + // Try get the map value. + // + SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink); + if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink); + Status = EvaluateExpression (FormSet, Form, SubExpression); + if (EFI_ERROR (Status)) { + goto Done; + } + Value = &SubExpression->Result; + break; + } + // + // Skip the second expression on this pair. + // + SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink); + if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + // + // Goto the first expression on next pair. + // + SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink); + } + + // + // No map value is found. + // + if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) { + Value->Type = EFI_IFR_TYPE_UNDEFINED; + Value->Value.u8 = 0; + } + break; + default: break; } if (EFI_ERROR (Status)) { - return Status; + goto Done; } Status = PushExpression (Value); if (EFI_ERROR (Status)) { - return Status; + goto Done; } } @@ -2046,17 +2552,21 @@ EvaluateExpression ( Value = &Data1; Status = PopExpression (Value); if (EFI_ERROR (Status)) { - return Status; + goto Done; } // // After evaluating an expression, there should be only one value left on the expression stack // if (PopExpression (Value) != EFI_ACCESS_DENIED) { - return EFI_INVALID_PARAMETER; + Status = EFI_INVALID_PARAMETER; } - CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE)); +Done: + RestoreExpressionEvaluationStackOffset (StackOffset); + if (!EFI_ERROR (Status)) { + CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE)); + } - return EFI_SUCCESS; + return Status; } diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c b/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c index fc03834f1d..5593b6eeb5 100644 --- a/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c +++ b/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c @@ -450,6 +450,8 @@ DestroyExpression ( { LIST_ENTRY *Link; EXPRESSION_OPCODE *OpCode; + LIST_ENTRY *SubExpressionLink; + FORM_EXPRESSION *SubExpression; while (!IsListEmpty (&Expression->OpCodeListHead)) { Link = GetFirstNode (&Expression->OpCodeListHead); @@ -459,6 +461,19 @@ DestroyExpression ( if (OpCode->ValueList != NULL) { FreePool (OpCode->ValueList); } + + if (OpCode->ValueName != NULL) { + FreePool (OpCode->ValueName); + } + + if (OpCode->MapExpressionList.ForwardLink != NULL) { + while (!IsListEmpty (&OpCode->MapExpressionList)) { + SubExpressionLink = GetFirstNode(&OpCode->MapExpressionList); + SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink); + RemoveEntryList(&SubExpression->Link); + DestroyExpression (SubExpression); + } + } } // @@ -746,10 +761,12 @@ IsExpressionOpCode ( ) { if (((Operand >= EFI_IFR_EQ_ID_VAL_OP) && (Operand <= EFI_IFR_NOT_OP)) || - ((Operand >= EFI_IFR_MATCH_OP) && (Operand <= EFI_IFR_SPAN_OP)) || + ((Operand >= EFI_IFR_MATCH_OP) && (Operand <= EFI_IFR_SET_OP)) || + ((Operand >= EFI_IFR_EQUAL_OP) && (Operand <= EFI_IFR_SPAN_OP)) || (Operand == EFI_IFR_CATENATE_OP) || (Operand == EFI_IFR_TO_LOWER_OP) || (Operand == EFI_IFR_TO_UPPER_OP) || + (Operand == EFI_IFR_MAP_OP) || (Operand == EFI_IFR_VERSION_OP) || (Operand == EFI_IFR_SECURITY_OP)) { return TRUE; @@ -848,6 +865,12 @@ ParseOpCodes ( BOOLEAN SingleOpCodeExpression; BOOLEAN InScopeDefault; EFI_HII_VALUE *Value; + EFI_IFR_FORM_MAP_METHOD *MapMethod; + UINT8 MapScopeDepth; + LIST_ENTRY *Link; + FORMSET_STORAGE *VarStorage; + LIST_ENTRY *MapExpressionList; + EFI_VARSTORE_ID TempVarstoreId; mInScopeSubtitle = FALSE; SuppressForQuestion = FALSE; @@ -867,6 +890,12 @@ ParseOpCodes ( OptionSuppressExpression = NULL; FormSuppressExpression = NULL; ImageId = NULL; + MapMethod = NULL; + MapScopeDepth = 0; + Link = NULL; + VarStorage = NULL; + MapExpressionList = NULL; + TempVarstoreId = 0; // // Get the number of Statements and Expressions @@ -888,6 +917,8 @@ ParseOpCodes ( InitializeListHead (&FormSet->StorageListHead); InitializeListHead (&FormSet->DefaultStoreListHead); InitializeListHead (&FormSet->FormListHead); + ResetCurrentExpressionStack (); + ResetMapExpressionListStack (); CurrentForm = NULL; CurrentStatement = NULL; @@ -989,6 +1020,81 @@ ParseOpCodes ( CopyMem (&ExpressionOpCode->Guid, &((EFI_IFR_SECURITY *) OpCodeData)->Permissions, sizeof (EFI_GUID)); break; + case EFI_IFR_GET_OP: + case EFI_IFR_SET_OP: + CopyMem (&TempVarstoreId, &((EFI_IFR_GET *) OpCodeData)->VarStoreId, sizeof (TempVarstoreId)); + if (TempVarstoreId != 0) { + if (FormSet->StorageListHead.ForwardLink != NULL) { + Link = GetFirstNode (&FormSet->StorageListHead); + while (!IsNull (&FormSet->StorageListHead, Link)) { + VarStorage = FORMSET_STORAGE_FROM_LINK (Link); + if (VarStorage->VarStoreId == ((EFI_IFR_GET *) OpCodeData)->VarStoreId) { + ExpressionOpCode->VarStorage = VarStorage; + break; + } + Link = GetNextNode (&FormSet->StorageListHead, Link); + } + } + if (ExpressionOpCode->VarStorage == NULL) { + // + // VarStorage is not found. + // + return EFI_INVALID_PARAMETER; + } + } + ExpressionOpCode->ValueType = ((EFI_IFR_GET *) OpCodeData)->VarStoreType; + switch (ExpressionOpCode->ValueType) { + case EFI_IFR_TYPE_BOOLEAN: + case EFI_IFR_TYPE_NUM_SIZE_8: + ExpressionOpCode->ValueWidth = 1; + break; + + case EFI_IFR_TYPE_NUM_SIZE_16: + case EFI_IFR_TYPE_STRING: + ExpressionOpCode->ValueWidth = 2; + break; + + case EFI_IFR_TYPE_NUM_SIZE_32: + ExpressionOpCode->ValueWidth = 4; + break; + + case EFI_IFR_TYPE_NUM_SIZE_64: + ExpressionOpCode->ValueWidth = 8; + break; + + case EFI_IFR_TYPE_DATE: + ExpressionOpCode->ValueWidth = sizeof (EFI_IFR_DATE); + break; + + case EFI_IFR_TYPE_TIME: + ExpressionOpCode->ValueWidth = sizeof (EFI_IFR_TIME); + break; + + case EFI_IFR_TYPE_OTHER: + case EFI_IFR_TYPE_UNDEFINED: + case EFI_IFR_TYPE_ACTION: + case EFI_IFR_TYPE_BUFFER: + default: + // + // Invalid value type for Get/Set opcode. + // + return EFI_INVALID_PARAMETER; + } + CopyMem (&ExpressionOpCode->VarStoreInfo.VarName, &((EFI_IFR_GET *) OpCodeData)->VarStoreInfo.VarName, sizeof (EFI_STRING_ID)); + CopyMem (&ExpressionOpCode->VarStoreInfo.VarOffset, &((EFI_IFR_GET *) OpCodeData)->VarStoreInfo.VarOffset, sizeof (UINT16)); + if ((ExpressionOpCode->VarStorage != NULL) && + (ExpressionOpCode->VarStorage->Type == EFI_HII_VARSTORE_NAME_VALUE || + ExpressionOpCode->VarStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) { + ExpressionOpCode->ValueName = GetToken (ExpressionOpCode->VarStoreInfo.VarName, FormSet->HiiHandle); + if (ExpressionOpCode->ValueName == NULL) { + // + // String ID is invalid. + // + return EFI_INVALID_PARAMETER; + } + } + break; + case EFI_IFR_QUESTION_REF1_OP: CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID)); break; @@ -1063,11 +1169,37 @@ ParseOpCodes ( default: break; } - + // + // Create sub expression nested in MAP opcode + // + if (CurrentExpression == NULL && MapScopeDepth > 0) { + CurrentExpression = CreateExpression (CurrentForm); + InsertTailList (MapExpressionList, &CurrentExpression->Link); + if (Scope == 0) { + SingleOpCodeExpression = TRUE; + } + } ASSERT (CurrentExpression != NULL); InsertTailList (&CurrentExpression->OpCodeListHead, &ExpressionOpCode->Link); - - if (SingleOpCodeExpression) { + if (Operand == EFI_IFR_MAP_OP) { + // + // Store current Map Expression List. + // + if (MapExpressionList != NULL) { + PushMapExpressionList (MapExpressionList); + } + // + // Initialize new Map Expression List. + // + MapExpressionList = &ExpressionOpCode->MapExpressionList; + InitializeListHead (MapExpressionList); + // + // Store current expression. + // + PushCurrentExpression (CurrentExpression); + CurrentExpression = NULL; + MapScopeDepth ++; + } else if (SingleOpCodeExpression) { // // There are two cases to indicate the end of an Expression: // for single OpCode expression: one Expression OpCode @@ -1134,6 +1266,7 @@ ParseOpCodes ( InitializeListHead (&CurrentForm->ExpressionListHead); InitializeListHead (&CurrentForm->StatementListHead); + CurrentForm->FormType = STANDARD_MAP_FORM_TYPE; CopyMem (&CurrentForm->FormId, &((EFI_IFR_FORM *) OpCodeData)->FormId, sizeof (UINT16)); CopyMem (&CurrentForm->FormTitle, &((EFI_IFR_FORM *) OpCodeData)->FormTitle, sizeof (EFI_STRING_ID)); @@ -1157,6 +1290,63 @@ ParseOpCodes ( InsertTailList (&FormSet->FormListHead, &CurrentForm->Link); break; + case EFI_IFR_FORM_MAP_OP: + // + // Create a new Form for this FormSet + // + CurrentForm = AllocateZeroPool (sizeof (FORM_BROWSER_FORM)); + ASSERT (CurrentForm != NULL); + CurrentForm->Signature = FORM_BROWSER_FORM_SIGNATURE; + InitializeListHead (&CurrentForm->ExpressionListHead); + InitializeListHead (&CurrentForm->StatementListHead); + CopyMem (&CurrentForm->FormId, &((EFI_IFR_FORM *) OpCodeData)->FormId, sizeof (UINT16)); + + MapMethod = (EFI_IFR_FORM_MAP_METHOD *) (OpCodeData + sizeof (EFI_IFR_FORM_MAP)); + // + // FormMap Form must contain at least one Map Method. + // + if (((EFI_IFR_OP_HEADER *) OpCodeData)->Length < ((UINTN) (UINT8 *) (MapMethod + 1) - (UINTN) OpCodeData)) { + return EFI_INVALID_PARAMETER; + } + // + // Try to find the standard form map method. + // + while (((UINTN) (UINT8 *) MapMethod - (UINTN) OpCodeData) < ((EFI_IFR_OP_HEADER *) OpCodeData)->Length) { + if (CompareGuid ((EFI_GUID *) (VOID *) &MapMethod->MethodIdentifier, &gEfiHiiStandardFormGuid)) { + CopyMem (&CurrentForm->FormTitle, &MapMethod->MethodTitle, sizeof (EFI_STRING_ID)); + CurrentForm->FormType = STANDARD_MAP_FORM_TYPE; + break; + } + MapMethod ++; + } + // + // If the standard form map method is not found, the first map method title will be used. + // + if (CurrentForm->FormTitle == 0) { + MapMethod = (EFI_IFR_FORM_MAP_METHOD *) (OpCodeData + sizeof (EFI_IFR_FORM_MAP)); + CopyMem (&CurrentForm->FormTitle, &MapMethod->MethodTitle, sizeof (EFI_STRING_ID)); + } + + if (InScopeFormSuppress) { + // + // Form is inside of suppressif + // + CurrentForm->SuppressExpression = FormSuppressExpression; + } + + if (Scope != 0) { + // + // Enter scope of a Form, suppressif will be used for Question or Option + // + SuppressForQuestion = TRUE; + } + + // + // Insert into Form list of this FormSet + // + InsertTailList (&FormSet->FormListHead, &CurrentForm->Link); + break; + // // Storage // @@ -1707,6 +1897,50 @@ ParseOpCodes ( } break; + case EFI_IFR_READ_OP: + CurrentExpression = CreateExpression (CurrentForm); + CurrentExpression->Type = EFI_HII_EXPRESSION_READ; + InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link); + + // + // Make sure CurrentStatement is not NULL. + // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR + // file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler. + // + ASSERT (CurrentStatement != NULL); + CurrentStatement->ReadExpression = CurrentExpression; + + // + // Take a look at next OpCode to see whether current expression consists + // of single OpCode + // + if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) { + SingleOpCodeExpression = TRUE; + } + break; + + case EFI_IFR_WRITE_OP: + CurrentExpression = CreateExpression (CurrentForm); + CurrentExpression->Type = EFI_HII_EXPRESSION_WRITE; + InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link); + + // + // Make sure CurrentStatement is not NULL. + // If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR + // file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler. + // + ASSERT (CurrentStatement != NULL); + CurrentStatement->WriteExpression = CurrentExpression; + + // + // Take a look at next OpCode to see whether current expression consists + // of single OpCode + // + if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) { + SingleOpCodeExpression = TRUE; + } + break; + // // Image // @@ -1723,6 +1957,7 @@ ParseOpCodes ( break; case EFI_IFR_FORM_OP: + case EFI_IFR_FORM_MAP_OP: ASSERT (CurrentForm != NULL); ImageId = &CurrentForm->ImageId; break; @@ -1818,6 +2053,7 @@ ParseOpCodes ( break; case EFI_IFR_FORM_OP: + case EFI_IFR_FORM_MAP_OP: // // End of Form // @@ -1871,6 +2107,22 @@ ParseOpCodes ( InScopeDefault = FALSE; break; + case EFI_IFR_MAP_OP: + // + // Get current Map Expression List. + // + Status = PopMapExpressionList ((VOID **) &MapExpressionList); + if (Status == EFI_ACCESS_DENIED) { + MapExpressionList = NULL; + } + // + // Get current expression. + // + Status = PopCurrentExpression ((VOID **) &CurrentExpression); + ASSERT_EFI_ERROR (Status); + MapScopeDepth --; + break; + default: if (IsExpressionOpCode (ScopeOpCode)) { if (mInScopeDisable && CurrentForm == NULL) { @@ -1889,7 +2141,7 @@ ParseOpCodes ( OpCodeDisabled = CurrentExpression->Result.Value.b; // - // DisableIf Expression is only used once and not quequed, free it + // DisableIf Expression is only used once and not queued, free it // DestroyExpression (CurrentExpression); } diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c b/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c index 9301fe606a..6d5a3db2e5 100644 --- a/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c +++ b/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c @@ -387,9 +387,11 @@ EvaluateFormExpressions ( Link = GetNextNode (&Form->ExpressionListHead, Link); if (Expression->Type == EFI_HII_EXPRESSION_INCONSISTENT_IF || - Expression->Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) { + Expression->Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF || + Expression->Type == EFI_HII_EXPRESSION_WRITE || + (Expression->Type == EFI_HII_EXPRESSION_READ && Form->FormType != STANDARD_MAP_FORM_TYPE)) { // - // Postpone Form validation to Question editing or Form submiting + // Postpone Form validation to Question editing or Form submitting or Question Write or Question Read for nonstandard form. // continue; } diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c index 81de737a03..d50071e550 100644 --- a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c +++ b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c @@ -661,6 +661,10 @@ GetToken ( { EFI_STRING String; + if (HiiHandle == NULL) { + return NULL; + } + String = HiiGetString (HiiHandle, Token, NULL); if (String == NULL) { String = AllocateCopyPool (sizeof (mUnknownString), mUnknownString); @@ -1041,6 +1045,20 @@ GetQuestionValue ( } return Status; } + + // + // Get question value by read expression. + // + if (Question->ReadExpression != NULL && Form->FormType == STANDARD_MAP_FORM_TYPE) { + Status = EvaluateExpression (FormSet, Form, Question->ReadExpression); + if (!EFI_ERROR (Status) && (Question->ReadExpression->Result.Type < EFI_IFR_TYPE_OTHER)) { + // + // Only update question value to the valid result. + // + CopyMem (&Question->HiiValue, &Question->ReadExpression->Result, sizeof (EFI_HII_VALUE)); + return EFI_SUCCESS; + } + } // // Question value is provided by RTC @@ -1369,6 +1387,16 @@ SetQuestionValue ( if (Question->ValueExpression != NULL) { return Status; } + + // + // Before set question value, evaluate its write expression. + // + if (Question->WriteExpression != NULL && Form->FormType == STANDARD_MAP_FORM_TYPE) { + Status = EvaluateExpression (FormSet, Form, Question->WriteExpression); + if (EFI_ERROR (Status)) { + return Status; + } + } // // Question value is provided by RTC diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h index 40030be196..fdbb4c1290 100644 --- a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h +++ b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h @@ -32,6 +32,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include +#include #include #include @@ -183,6 +184,8 @@ typedef struct { #define EFI_HII_EXPRESSION_DISABLE_IF 4 #define EFI_HII_EXPRESSION_VALUE 5 #define EFI_HII_EXPRESSION_RULE 6 +#define EFI_HII_EXPRESSION_READ 7 +#define EFI_HII_EXPRESSION_WRITE 8 #define EFI_HII_VARSTORE_BUFFER 0 #define EFI_HII_VARSTORE_NAME_VALUE 1 @@ -239,6 +242,11 @@ typedef struct { #define FORMSET_STORAGE_FROM_LINK(a) CR (a, FORMSET_STORAGE, Link, FORMSET_STORAGE_SIGNATURE) +typedef union { + EFI_STRING_ID VarName; + UINT16 VarOffset; +} VAR_STORE_INFO; + #define EXPRESSION_OPCODE_SIGNATURE SIGNATURE_32 ('E', 'X', 'O', 'P') typedef struct { @@ -261,6 +269,13 @@ typedef struct { EFI_STRING_ID DevicePath; // For EFI_IFR_QUESTION_REF3_2, EFI_IFR_QUESTION_REF3_3 EFI_GUID Guid; + + FORMSET_STORAGE *VarStorage; // For EFI_IFR_SET, EFI_IFR_GET + VAR_STORE_INFO VarStoreInfo;// For EFI_IFR_SET, EFI_IFR_GET + UINT8 ValueType; // For EFI_IFR_SET, EFI_IFR_GET + UINT8 ValueWidth; // For EFI_IFR_SET, EFI_IFR_GET + CHAR16 *ValueName; // For EFI_IFR_SET, EFI_IFR_GET + LIST_ENTRY MapExpressionList; // nested expressions inside of Map opcode. } EXPRESSION_OPCODE; #define EXPRESSION_OPCODE_FROM_LINK(a) CR (a, EXPRESSION_OPCODE, Link, EXPRESSION_OPCODE_SIGNATURE) @@ -315,11 +330,6 @@ typedef struct { #define FORM_BROWSER_STATEMENT_SIGNATURE SIGNATURE_32 ('F', 'S', 'T', 'A') -typedef union { - EFI_STRING_ID VarName; - UINT16 VarOffset; -} VAR_STORE_INFO; - typedef struct { UINTN Signature; LIST_ENTRY Link; @@ -386,18 +396,22 @@ typedef struct { FORM_EXPRESSION *SuppressExpression; // nesting inside of SuppressIf FORM_EXPRESSION *DisableExpression; // nesting inside of DisableIf + FORM_EXPRESSION *ReadExpression; // nested EFI_IFR_READ, provide this question value by read expression. + FORM_EXPRESSION *WriteExpression; // nested EFI_IFR_WRITE, evaluate write expression after this question value is set. } FORM_BROWSER_STATEMENT; #define FORM_BROWSER_STATEMENT_FROM_LINK(a) CR (a, FORM_BROWSER_STATEMENT, Link, FORM_BROWSER_STATEMENT_SIGNATURE) #define FORM_BROWSER_FORM_SIGNATURE SIGNATURE_32 ('F', 'F', 'R', 'M') +#define STANDARD_MAP_FORM_TYPE 0x01 typedef struct { UINTN Signature; LIST_ENTRY Link; - UINT16 FormId; - EFI_STRING_ID FormTitle; + UINT16 FormId; // FormId of normal form or formmap form. + EFI_STRING_ID FormTitle; // FormTile of normal form, or FormMapMethod title of formmap form. + UINT16 FormType; // Specific form type for the different form. EFI_IMAGE_ID ImageId; @@ -795,6 +809,42 @@ CreateDialog ( ... ); +/** + Get Value for given Name from a NameValue Storage. + + @param Storage The NameValue Storage. + @param Name The Name. + @param Value The retured Value. + + @retval EFI_SUCCESS Value found for given Name. + @retval EFI_NOT_FOUND No such Name found in NameValue storage. + +**/ +EFI_STATUS +GetValueByName ( + IN FORMSET_STORAGE *Storage, + IN CHAR16 *Name, + IN OUT CHAR16 **Value + ); + +/** + Set Value of given Name in a NameValue Storage. + + @param Storage The NameValue Storage. + @param Name The Name. + @param Value The Value to set. + + @retval EFI_SUCCESS Value found for given Name. + @retval EFI_NOT_FOUND No such Name found in NameValue storage. + +**/ +EFI_STATUS +SetValueByName ( + IN FORMSET_STORAGE *Storage, + IN CHAR16 *Name, + IN CHAR16 *Value + ); + /** Get Question's current Value. diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf b/MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf index 4b5128b2d6..dcaca62173 100644 --- a/MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf +++ b/MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf @@ -63,6 +63,7 @@ gEfiIfrTianoGuid ## CONSUMES ## GUID gEfiIfrFrameworkGuid ## CONSUMES ## GUID gEfiHiiPlatformSetupFormsetGuid + gEfiHiiStandardFormGuid ## SOMETIMES_CONSUMES ## GUID [Protocols] gEfiHiiConfigAccessProtocolGuid ## CONSUMES diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Ui.h b/MdeModulePkg/Universal/SetupBrowserDxe/Ui.h index 6fb3d9369a..45fb3eba3e 100644 --- a/MdeModulePkg/Universal/SetupBrowserDxe/Ui.h +++ b/MdeModulePkg/Universal/SetupBrowserDxe/Ui.h @@ -735,6 +735,80 @@ PopScope ( OUT UINT8 *Operand ); +/** + Reset stack pointer to begin of the stack. + +**/ +VOID +ResetCurrentExpressionStack ( + VOID + ); + +/** + Push current expression onto the Stack + + @param Pointer Pointer to current expression. + + @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 +PushCurrentExpression ( + IN VOID *Pointer + ); + +/** + Pop current expression from the Stack + + @param Pointer Pointer to current expression to be pop. + + @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 +PopCurrentExpression ( + OUT VOID **Pointer + ); + +/** + Reset stack pointer to begin of the stack. + +**/ +VOID +ResetMapExpressionListStack ( + VOID + ); + +/** + Push the list of map expression onto the Stack + + @param Pointer Pointer to the list of map expression to be pushed. + + @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 +PushMapExpressionList ( + IN VOID *Pointer + ); + +/** + Pop the list of map expression from the Stack + + @param Pointer Pointer to the list of map expression to be pop. + + @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 +PopMapExpressionList ( + OUT VOID **Pointer + ); + /** Get Form given its FormId. -- cgit v1.2.3