]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/SetupBrowserDxe/Expression.c
Enable nest for suppressif/grayoutif/diableif for form/question/option.
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Expression.c
index 1420f91828075e0f8bf4788dcca270624e1f73be..37dd6a0f61d48e99db8afa289ff9a5648bb60687 100644 (file)
@@ -34,6 +34,19 @@ EFI_HII_VALUE *mMapExpressionListStack = NULL;
 EFI_HII_VALUE *mMapExpressionListEnd = NULL;\r
 EFI_HII_VALUE *mMapExpressionListPointer = NULL;\r
 \r
+FORM_EXPRESSION   **mFormExpressionStack = NULL;\r
+FORM_EXPRESSION   **mFormExpressionEnd = NULL;\r
+FORM_EXPRESSION   **mFormExpressionPointer = NULL;\r
+\r
+FORM_EXPRESSION   **mStatementExpressionStack = NULL;\r
+FORM_EXPRESSION   **mStatementExpressionEnd = NULL;\r
+FORM_EXPRESSION   **mStatementExpressionPointer = NULL;\r
+\r
+FORM_EXPRESSION   **mOptionExpressionStack = NULL;\r
+FORM_EXPRESSION   **mOptionExpressionEnd = NULL;\r
+FORM_EXPRESSION   **mOptionExpressionPointer = NULL;\r
+\r
+\r
 //\r
 // Unicode collation protocol interface\r
 //\r
@@ -194,7 +207,10 @@ ResetCurrentExpressionStack (
   VOID\r
   )\r
 {\r
-  mCurrentExpressionPointer = mCurrentExpressionStack;\r
+  mCurrentExpressionPointer   = mCurrentExpressionStack;\r
+  mFormExpressionPointer      = mFormExpressionStack;\r
+  mStatementExpressionPointer = mStatementExpressionStack;\r
+  mOptionExpressionPointer    = mOptionExpressionStack;  \r
 }\r
 \r
 \r
@@ -267,6 +283,294 @@ ResetMapExpressionListStack (
 }\r
 \r
 \r
+/**\r
+  Grow size of the stack.\r
+\r
+  This is an internal function.\r
+\r
+  @param  Stack                  On input: old stack; On output: new stack\r
+  @param  StackPtr               On input: old stack pointer; On output: new stack\r
+                                 pointer\r
+  @param  StackEnd               On input: old stack end; On output: new stack end\r
+  @param  MemberSize             The stack member size.\r
+  \r
+  @retval EFI_SUCCESS            Grow stack success.\r
+  @retval EFI_OUT_OF_RESOURCES   No enough memory for stack space.\r
+\r
+**/\r
+EFI_STATUS\r
+GrowConditionalStack (\r
+  IN OUT FORM_EXPRESSION   ***Stack,\r
+  IN OUT FORM_EXPRESSION   ***StackPtr,\r
+  IN OUT FORM_EXPRESSION   ***StackEnd,\r
+  IN     UINTN             MemberSize\r
+  )\r
+{\r
+  UINTN             Size;\r
+  FORM_EXPRESSION   **NewStack;\r
+\r
+  Size = EXPRESSION_STACK_SIZE_INCREMENT;\r
+  if (*StackPtr != NULL) {\r
+    Size = Size + (*StackEnd - *Stack);\r
+  }\r
+\r
+  NewStack = AllocatePool (Size * MemberSize);\r
+  if (NewStack == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  if (*StackPtr != NULL) {\r
+    //\r
+    // Copy from Old Stack to the New Stack\r
+    //\r
+    CopyMem (\r
+      NewStack,\r
+      *Stack,\r
+      (*StackEnd - *Stack) * MemberSize\r
+      );\r
+\r
+    //\r
+    // Free The Old Stack\r
+    //\r
+    FreePool (*Stack);\r
+  }\r
+\r
+  //\r
+  // Make the Stack pointer point to the old data in the new stack\r
+  //\r
+  *StackPtr = NewStack + (*StackPtr - *Stack);\r
+  *Stack    = NewStack;\r
+  *StackEnd = NewStack + Size;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Push an element onto the Stack.\r
+\r
+  @param  Stack                  On input: old stack; On output: new stack\r
+  @param  StackPtr               On input: old stack pointer; On output: new stack\r
+                                 pointer\r
+  @param  StackEnd               On input: old stack end; On output: new stack end\r
+  @param  Data                   Data to push.\r
+\r
+  @retval EFI_SUCCESS            Push stack success.\r
+\r
+**/\r
+EFI_STATUS\r
+PushConditionalStack (\r
+  IN OUT FORM_EXPRESSION   ***Stack,\r
+  IN OUT FORM_EXPRESSION   ***StackPtr,\r
+  IN OUT FORM_EXPRESSION   ***StackEnd,\r
+  IN     FORM_EXPRESSION   **Data\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // Check for a stack overflow condition\r
+  //\r
+  if (*StackPtr >= *StackEnd) {\r
+    //\r
+    // Grow the stack\r
+    //\r
+    Status = GrowConditionalStack (Stack, StackPtr, StackEnd, sizeof (FORM_EXPRESSION *));\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Push the item onto the stack\r
+  //\r
+  CopyMem (*StackPtr, Data, sizeof (FORM_EXPRESSION *)); \r
+  *StackPtr = *StackPtr + 1;\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+/**\r
+  Pop an element from the stack.\r
+\r
+  @param  Stack                  On input: old stack\r
+  @param  StackPtr               On input: old stack pointer; On output: new stack pointer\r
+  @param  Data                   Data to pop.\r
+\r
+  @retval EFI_SUCCESS            The value was popped onto the stack.\r
+  @retval EFI_ACCESS_DENIED      The pop operation underflowed the stack\r
+\r
+**/\r
+EFI_STATUS\r
+PopConditionalStack (\r
+  IN     FORM_EXPRESSION   **Stack,\r
+  IN OUT FORM_EXPRESSION   ***StackPtr,\r
+  OUT    FORM_EXPRESSION   **Data\r
+  )\r
+{\r
+  //\r
+  // Check for a stack underflow condition\r
+  //\r
+  if (*StackPtr == Stack) {\r
+    return EFI_ACCESS_DENIED;\r
+  }\r
+\r
+  //\r
+  // Pop the item off the stack\r
+  //\r
+  *StackPtr = *StackPtr - 1;\r
+  CopyMem (Data, *StackPtr, sizeof (FORM_EXPRESSION  *));\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+/**\r
+  Get the expression list count.\r
+  \r
+  @param  Level                  Which type this expression belong to. Form, \r
+                                 statement or option?\r
+\r
+  @retval >=0                    The expression count\r
+  @retval -1                     Input parameter error.\r
+\r
+**/\r
+INTN \r
+GetConditionalExpressionCount (\r
+  IN EXPRESS_LEVEL       Level\r
+  )\r
+{\r
+  switch (Level) {\r
+    case ExpressForm:\r
+      return mFormExpressionPointer - mFormExpressionStack;\r
+    case ExpressStatement:\r
+      return mStatementExpressionPointer - mStatementExpressionStack;\r
+    case ExpressOption:\r
+      return mOptionExpressionPointer - mOptionExpressionStack;\r
+    default:\r
+      ASSERT (FALSE);\r
+      return -1;\r
+  } \r
+}\r
+\r
+/**\r
+  Get the expression Buffer pointer.\r
+  \r
+  @param  Level                  Which type this expression belong to. Form, \r
+                                 statement or option?\r
+\r
+  @retval  The start pointer of the expression buffer or NULL.\r
+\r
+**/\r
+FORM_EXPRESSION **\r
+GetConditionalExpressionList (\r
+  IN EXPRESS_LEVEL       Level\r
+  )\r
+{\r
+  switch (Level) {\r
+    case ExpressForm:\r
+      return mFormExpressionStack;\r
+    case ExpressStatement:\r
+      return mStatementExpressionStack;\r
+    case ExpressOption:\r
+      return mOptionExpressionStack;\r
+    default:\r
+      ASSERT (FALSE);\r
+      return NULL;\r
+  } \r
+}\r
+\r
+\r
+/**\r
+  Push the expression options onto the Stack.\r
+\r
+  @param  Pointer                Pointer to the current expression.\r
+  @param  Level                  Which type this expression belong to. Form, \r
+                                 statement or option?\r
+\r
+  @retval EFI_SUCCESS            The value was pushed onto the stack.\r
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PushConditionalExpression (\r
+  IN FORM_EXPRESSION   *Pointer,\r
+  IN EXPRESS_LEVEL     Level\r
+  )\r
+{\r
+  switch (Level) {\r
+    case ExpressForm:\r
+      return PushConditionalStack (\r
+        &mFormExpressionStack,\r
+        &mFormExpressionPointer,\r
+        &mFormExpressionEnd,\r
+        &Pointer\r
+        );\r
+    case ExpressStatement:\r
+      return PushConditionalStack (\r
+        &mStatementExpressionStack,\r
+        &mStatementExpressionPointer,\r
+        &mStatementExpressionEnd,\r
+        &Pointer\r
+        );\r
+    case ExpressOption:\r
+      return PushConditionalStack (\r
+        &mOptionExpressionStack,\r
+        &mOptionExpressionPointer,\r
+        &mOptionExpressionEnd,\r
+        &Pointer\r
+        );\r
+    default:\r
+      ASSERT (FALSE);\r
+      return EFI_INVALID_PARAMETER;\r
+  }\r
+}\r
+\r
+/**\r
+  Pop the expression options from the Stack\r
+\r
+  @param  Level                  Which type this expression belong to. Form, \r
+                                 statement or option?\r
+\r
+  @retval EFI_SUCCESS            The value was pushed onto the stack.\r
+  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PopConditionalExpression (\r
+  IN  EXPRESS_LEVEL      Level\r
+  )\r
+{\r
+  FORM_EXPRESSION   *Pointer;\r
+\r
+  switch (Level) {\r
+    case ExpressForm:\r
+      return PopConditionalStack (\r
+        mFormExpressionStack,\r
+        &mFormExpressionPointer,\r
+        &Pointer\r
+      );\r
+\r
+    case ExpressStatement:\r
+      return PopConditionalStack (\r
+        mStatementExpressionStack,\r
+        &mStatementExpressionPointer,\r
+        &Pointer\r
+      );\r
+\r
+    case ExpressOption:\r
+      return PopConditionalStack (\r
+        mOptionExpressionStack,\r
+        &mOptionExpressionPointer,\r
+        &Pointer\r
+      );\r
+\r
+    default:\r
+      ASSERT (FALSE);\r
+      return EFI_INVALID_PARAMETER;\r
+  }\r
+}\r
+\r
+\r
 /**\r
   Push the list of map expression onto the Stack\r
 \r
@@ -2868,3 +3172,80 @@ Done:
 \r
   return Status;\r
 }\r
+\r
+/**\r
+  Return the result of the expression list. Check the expression list and \r
+  return the highest priority express result.  \r
+  Priority: DisableIf > SuppressIf > GrayOutIf > FALSE\r
+\r
+  @param  ExpList             The input expression list.\r
+  @param  Evaluate            Whether need to evaluate the expression first.\r
+  @param  FormSet             FormSet associated with this expression.\r
+  @param  Form                Form associated with this expression.  \r
+\r
+  @retval EXPRESS_RESULT      Return the higher priority express result. \r
+                              DisableIf > SuppressIf > GrayOutIf > FALSE\r
+\r
+**/\r
+EXPRESS_RESULT \r
+EvaluateExpressionList (\r
+  IN FORM_EXPRESSION_LIST *ExpList,\r
+  IN BOOLEAN              Evaluate,\r
+  IN FORM_BROWSER_FORMSET *FormSet, OPTIONAL\r
+  IN FORM_BROWSER_FORM    *Form OPTIONAL\r
+  )\r
+{\r
+  UINTN              Index;\r
+  EXPRESS_RESULT     ReturnVal;\r
+  EXPRESS_RESULT     CompareOne;\r
+  EFI_STATUS         Status;\r
+\r
+  if (ExpList == NULL) {\r
+    return ExpressFalse;\r
+  }\r
+\r
+  ASSERT(ExpList->Signature == FORM_EXPRESSION_LIST_SIGNATURE);\r
+  Index     = 0;\r
+\r
+  //\r
+  // Check whether need to evaluate the expression first.\r
+  //\r
+  if (Evaluate) {  \r
+    while (ExpList->Count > Index) {\r
+      Status = EvaluateExpression (FormSet, Form, ExpList->Expression[Index++]);\r
+      if (EFI_ERROR (Status)) {\r
+        return ExpressFalse;\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // Run the list of expressions.\r
+  //\r
+  ReturnVal = ExpressFalse;\r
+  for (Index = 0; Index < ExpList->Count; Index++) {\r
+    if (ExpList->Expression[Index]->Result.Type == EFI_IFR_TYPE_BOOLEAN &&\r
+        ExpList->Expression[Index]->Result.Value.b) {\r
+      switch (ExpList->Expression[Index]->Type) {\r
+        case EFI_HII_EXPRESSION_SUPPRESS_IF:\r
+          CompareOne = ExpressSuppress;\r
+          break;\r
+\r
+        case EFI_HII_EXPRESSION_GRAY_OUT_IF:\r
+          CompareOne = ExpressGrayOut;\r
+          break;\r
+\r
+        case EFI_HII_EXPRESSION_DISABLE_IF:\r
+          CompareOne = ExpressDisable;\r
+          break;\r
+\r
+        default:\r
+          return ExpressFalse; \r
+      }\r
+\r
+      ReturnVal = ReturnVal < CompareOne ? CompareOne : ReturnVal;\r
+    }\r
+  }\r
+  \r
+  return ReturnVal;\r
+}\r