summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Universal/SetupBrowserDxe
diff options
context:
space:
mode:
authorlgao4 <lgao4@6f19259b-4bc3-4df7-8a09-765794883524>2010-02-25 10:10:59 +0000
committerlgao4 <lgao4@6f19259b-4bc3-4df7-8a09-765794883524>2010-02-25 10:10:59 +0000
commit2573712e0132deac7591f9ed5e2423c5e61e5af6 (patch)
tree8b213960d0df7d73510f3cadd48218667350ef76 /MdeModulePkg/Universal/SetupBrowserDxe
parent234980f6e935a51fdafecb9930b4a2ecbf47b727 (diff)
downloadedk2-platforms-2573712e0132deac7591f9ed5e2423c5e61e5af6.tar.xz
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
Diffstat (limited to 'MdeModulePkg/Universal/SetupBrowserDxe')
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Expression.c672
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c262
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c6
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Setup.c28
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Setup.h64
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf1
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Ui.h74
7 files changed, 1012 insertions, 95 deletions
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;
}
@@ -179,6 +185,144 @@ PopStack (
**/
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.
+
+**/
+VOID
ResetScopeStack (
VOID
)
@@ -235,9 +379,8 @@ PopScope (
EFI_HII_VALUE Data;
Status = PopStack (
- &mOpCodeScopeStack,
+ mOpCodeScopeStack,
&mOpCodeScopeStackPointer,
- &mOpCodeScopeStackEnd,
&Data
);
@@ -248,19 +391,6 @@ PopScope (
/**
- Reset stack pointer to begin of the stack.
-
-**/
-VOID
-ResetExpressionStack (
- VOID
- )
-{
- mExpressionEvaluationStackPointer = mExpressionEvaluationStack;
-}
-
-
-/**
Push an Expression value onto the Stack
@param Value Expression value to push.
@@ -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 <Guid/MdeModuleHii.h>
#include <Guid/HiiPlatformSetupFormset.h>
+#include <Guid/HiiFormMapMethodGuid.h>
#include <Library/PrintLib.h>
#include <Library/DebugLib.h>
@@ -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;
@@ -796,6 +810,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.
@param FormSet FormSet data structure.
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
@@ -736,6 +736,80 @@ PopScope (
);
/**
+ 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.
@param FormSet The formset which contains this form.