]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
1. Support inconsistent if opcode used in string/password opcode.
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Presentation.c
index a89bb2f50b28029cecd252a1a8c1a70ac7a78a88..6d9a555b4920c1e33b88f6102a0215d47f835485 100644 (file)
@@ -16,7 +16,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 BOOLEAN            mHiiPackageListUpdated;\r
 UI_MENU_SELECTION  *gCurrentSelection;\r
-\r
+EFI_HII_HANDLE     mCurrentHiiHandle = NULL;\r
+EFI_GUID           mCurrentFormSetGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};\r
+UINT16             mCurrentFormId = 0;\r
 \r
 /**\r
   Clear retangle with specified text attribute.\r
@@ -870,10 +872,12 @@ SetupBrowser (
   EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess;\r
   FORM_BROWSER_FORMSET            *FormSet;\r
   EFI_INPUT_KEY                   Key;\r
+  BOOLEAN                         SubmitFormIsRequired;\r
 \r
   gMenuRefreshHead = NULL;\r
   gResetRequired = FALSE;\r
   FormSet = Selection->FormSet;\r
+  ConfigAccess = Selection->FormSet->ConfigAccess;\r
 \r
   //\r
   // Register notify for Form package update\r
@@ -890,59 +894,11 @@ SetupBrowser (
     return Status;\r
   }\r
 \r
-  //\r
-  // Before display the formset, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_OPEN\r
-  //\r
-  ConfigAccess = Selection->FormSet->ConfigAccess;\r
-  if ((ConfigAccess != NULL) && (Selection->Action != UI_ACTION_REFRESH_FORMSET)) {\r
-    ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
-    mHiiPackageListUpdated = FALSE;\r
-    Status = ConfigAccess->Callback (\r
-                             ConfigAccess,\r
-                             EFI_BROWSER_ACTION_FORM_OPEN,\r
-                             0,\r
-                             EFI_IFR_TYPE_UNDEFINED,\r
-                             NULL,\r
-                             &ActionRequest\r
-                             );\r
-\r
-    if (!EFI_ERROR (Status)) {\r
-      switch (ActionRequest) {\r
-      case EFI_BROWSER_ACTION_REQUEST_RESET:\r
-        gResetRequired = TRUE;\r
-        break;\r
-\r
-      case EFI_BROWSER_ACTION_REQUEST_SUBMIT:\r
-        //\r
-        // Till now there is no uncommitted data, so ignore this request\r
-        //\r
-        break;\r
-\r
-      case EFI_BROWSER_ACTION_REQUEST_EXIT:\r
-        Selection->Action = UI_ACTION_EXIT;\r
-        break;\r
-\r
-      default:\r
-        break;\r
-      }\r
-    }\r
-\r
-    if (mHiiPackageListUpdated) {\r
-      //\r
-      // IFR is updated during callback, force to reparse the IFR binary\r
-      //\r
-      mHiiPackageListUpdated = FALSE;\r
-      Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
-      goto Done;\r
-    }\r
-  }\r
-\r
   //\r
   // Initialize current settings of Questions in this FormSet\r
   //\r
   Status = InitializeCurrentSetting (Selection->FormSet);\r
   if (EFI_ERROR (Status)) {\r
-    Selection->Action = UI_ACTION_EXIT;\r
     goto Done;\r
   }\r
 \r
@@ -966,7 +922,8 @@ SetupBrowser (
       //\r
       // No Form to display\r
       //\r
-      return EFI_NOT_FOUND;\r
+      Status = EFI_NOT_FOUND;\r
+      goto Done;\r
     }\r
 \r
     //\r
@@ -974,8 +931,9 @@ SetupBrowser (
     //\r
     if (Selection->Form->SuppressExpression != NULL) {\r
       Status = EvaluateExpression (Selection->FormSet, Selection->Form, Selection->Form->SuppressExpression);\r
-      if (EFI_ERROR (Status)) {\r
-        return Status;\r
+      if (EFI_ERROR (Status) || (Selection->Form->SuppressExpression->Result.Type != EFI_IFR_TYPE_BOOLEAN)) {\r
+        Status = EFI_INVALID_PARAMETER;\r
+        goto Done;\r
       }\r
 \r
       if (Selection->Form->SuppressExpression->Result.Value.b) {\r
@@ -986,23 +944,121 @@ SetupBrowser (
           CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gFormSuppress, gPressEnter, gEmptyString);\r
         } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
 \r
-        return EFI_NOT_FOUND;\r
+        Status = EFI_NOT_FOUND;\r
+        goto Done;\r
       }\r
     }\r
-    \r
+\r
     //\r
     // Reset FormPackage update flag\r
     //\r
     mHiiPackageListUpdated = FALSE;\r
 \r
+    //\r
+    // Before display new form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_OPEN\r
+    // for each question with callback flag.\r
+    // New form may be the first form, or the different form after another form close.\r
+    //\r
+    if ((ConfigAccess != NULL) &&\r
+        ((Selection->Handle != mCurrentHiiHandle) ||\r
+        (!CompareGuid (&Selection->FormSetGuid, &mCurrentFormSetGuid)) ||\r
+        (Selection->FormId != mCurrentFormId))) {\r
+\r
+      //\r
+      // Keep current form information\r
+      //\r
+      mCurrentHiiHandle   = Selection->Handle;\r
+      CopyGuid (&mCurrentFormSetGuid, &Selection->FormSetGuid);\r
+      mCurrentFormId      = Selection->FormId;\r
+\r
+      //\r
+      // Go through each statement in this form\r
+      //\r
+      SubmitFormIsRequired = FALSE;\r
+      Link = GetFirstNode (&Selection->Form->StatementListHead);\r
+      while (!IsNull (&Selection->Form->StatementListHead, Link)) {\r
+        Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+        Link = GetNextNode (&Selection->Form->StatementListHead, Link);\r
+        \r
+        if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) {\r
+          continue;\r
+        }\r
+\r
+        //\r
+        // Check whether Statement is disabled.\r
+        //\r
+        if (Statement->DisableExpression != NULL) {\r
+          Status = EvaluateExpression (Selection->FormSet, Selection->Form, Statement->DisableExpression);\r
+          if (!EFI_ERROR (Status) && \r
+              (Statement->DisableExpression->Result.Type == EFI_IFR_TYPE_BOOLEAN) && \r
+              (Statement->DisableExpression->Result.Value.b)) {\r
+            continue;\r
+          }\r
+        }\r
+\r
+        ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+        Status = ConfigAccess->Callback (\r
+                                 ConfigAccess,\r
+                                 EFI_BROWSER_ACTION_FORM_OPEN,\r
+                                 Statement->QuestionId,\r
+                                 EFI_IFR_TYPE_UNDEFINED,\r
+                                 NULL,\r
+                                 &ActionRequest\r
+                                 );\r
+\r
+        if (!EFI_ERROR (Status)) {\r
+          switch (ActionRequest) {\r
+          case EFI_BROWSER_ACTION_REQUEST_RESET:\r
+            gResetRequired = TRUE;\r
+            break;\r
+\r
+          case EFI_BROWSER_ACTION_REQUEST_SUBMIT:\r
+            SubmitFormIsRequired = TRUE;\r
+            break;\r
+\r
+          case EFI_BROWSER_ACTION_REQUEST_EXIT:\r
+            Selection->Action = UI_ACTION_EXIT;\r
+            gNvUpdateRequired = FALSE;\r
+            break;\r
+\r
+          default:\r
+            break;\r
+          }\r
+        }\r
+      }\r
+      if (SubmitFormIsRequired) {\r
+        SubmitForm (Selection->FormSet, Selection->Form);\r
+      }\r
+      //\r
+      // EXIT requests to close form.\r
+      //\r
+      if (Selection->Action == UI_ACTION_EXIT) {\r
+        goto Done;\r
+      }\r
+      //\r
+      // IFR is updated during callback of open form, force to reparse the IFR binary\r
+      //\r
+      if (mHiiPackageListUpdated) {\r
+        Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+        mHiiPackageListUpdated = FALSE;\r
+        goto Done;\r
+      }\r
+    }\r
+\r
     //\r
     // Load Questions' Value for display\r
     //\r
     Status = LoadFormSetConfig (Selection, Selection->FormSet);\r
     if (EFI_ERROR (Status)) {\r
-      return Status;\r
+      goto Done;\r
     }\r
 \r
+    //\r
+    // EXIT requests to close form.\r
+    //\r
+    if (Selection->Action == UI_ACTION_EXIT) {\r
+      goto Done;\r
+    }\r
     //\r
     // IFR is updated during callback of read value, force to reparse the IFR binary\r
     //\r
@@ -1022,7 +1078,7 @@ SetupBrowser (
     //\r
     Status = DisplayForm (Selection);\r
     if (EFI_ERROR (Status)) {\r
-      return Status;\r
+      goto Done;\r
     }\r
 \r
     //\r
@@ -1039,21 +1095,15 @@ SetupBrowser (
       //\r
       mHiiPackageListUpdated = FALSE;\r
 \r
-      if (((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) && (Statement->Operand != EFI_IFR_PASSWORD_OP)) {\r
-        ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+      if ((ConfigAccess != NULL) && \r
+          ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) && \r
+          (Statement->Operand != EFI_IFR_PASSWORD_OP)) {\r
 \r
-        if (ConfigAccess == NULL) {\r
-          return EFI_UNSUPPORTED;\r
-        }\r
+        ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
 \r
         HiiValue = &Statement->HiiValue;\r
         TypeValue = &HiiValue->Value;\r
-        if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
-          //\r
-          // Create String in HII database for Configuration Driver to retrieve\r
-          //\r
-          HiiValue->Value.string = NewString ((CHAR16 *) Statement->BufferValue, Selection->FormSet->HiiHandle);\r
-        } else if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
+        if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
           //\r
           // For OrderedList, passing in the value buffer to Callback()\r
           //\r
@@ -1069,13 +1119,6 @@ SetupBrowser (
                                  &ActionRequest\r
                                  );\r
 \r
-        if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
-          //\r
-          // Clean the String in HII Database\r
-          //\r
-          DeleteString (HiiValue->Value.string, Selection->FormSet->HiiHandle);\r
-        }\r
-\r
         if (!EFI_ERROR (Status)) {\r
           switch (ActionRequest) {\r
           case EFI_BROWSER_ACTION_REQUEST_RESET:\r
@@ -1119,41 +1162,64 @@ SetupBrowser (
         Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
       }\r
     }\r
-  } while (Selection->Action == UI_ACTION_REFRESH_FORM);\r
 \r
-  //\r
-  // Before exit the formset, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_CLOSE\r
-  //\r
-  if ((ConfigAccess != NULL) && (Selection->Action == UI_ACTION_EXIT)) {\r
-    ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
-    Status = ConfigAccess->Callback (\r
-                             ConfigAccess,\r
-                             EFI_BROWSER_ACTION_FORM_CLOSE,\r
-                             0,\r
-                             EFI_IFR_TYPE_UNDEFINED,\r
-                             NULL,\r
-                             &ActionRequest\r
-                             );\r
-\r
-    if (!EFI_ERROR (Status)) {\r
-      switch (ActionRequest) {\r
-      case EFI_BROWSER_ACTION_REQUEST_RESET:\r
-        gResetRequired = TRUE;\r
-        break;\r
+    //\r
+    // Before exit the form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_CLOSE\r
+    // for each question with callback flag.\r
+    //\r
+    if ((ConfigAccess != NULL) && \r
+        ((Selection->Action == UI_ACTION_EXIT) || \r
+         (Selection->Handle != mCurrentHiiHandle) ||\r
+         (!CompareGuid (&Selection->FormSetGuid, &mCurrentFormSetGuid)) ||\r
+         (Selection->FormId != mCurrentFormId))) {\r
+      //\r
+      // Go through each statement in this form\r
+      //\r
+      SubmitFormIsRequired = FALSE;\r
+      Link = GetFirstNode (&Selection->Form->StatementListHead);\r
+      while (!IsNull (&Selection->Form->StatementListHead, Link)) {\r
+        Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+        Link = GetNextNode (&Selection->Form->StatementListHead, Link);\r
+        \r
+        if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) {\r
+          continue;\r
+        }\r
 \r
-      case EFI_BROWSER_ACTION_REQUEST_SUBMIT:\r
-        SubmitForm (Selection->FormSet, Selection->Form);\r
-        break;\r
+        ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+        Status = ConfigAccess->Callback (\r
+                                 ConfigAccess,\r
+                                 EFI_BROWSER_ACTION_FORM_CLOSE,\r
+                                 Statement->QuestionId,\r
+                                 EFI_IFR_TYPE_UNDEFINED,\r
+                                 NULL,\r
+                                 &ActionRequest\r
+                                 );\r
+\r
+        if (!EFI_ERROR (Status)) {\r
+          switch (ActionRequest) {\r
+          case EFI_BROWSER_ACTION_REQUEST_RESET:\r
+            gResetRequired = TRUE;\r
+            break;\r
 \r
-      case EFI_BROWSER_ACTION_REQUEST_EXIT:\r
-        gNvUpdateRequired = FALSE;\r
-        break;\r
+          case EFI_BROWSER_ACTION_REQUEST_SUBMIT:\r
+            SubmitFormIsRequired = TRUE;\r
+            break;\r
 \r
-      default:\r
-        break;\r
+          case EFI_BROWSER_ACTION_REQUEST_EXIT:\r
+            Selection->Action = UI_ACTION_EXIT;\r
+            gNvUpdateRequired = FALSE;\r
+            break;\r
+\r
+          default:\r
+            break;\r
+          }\r
+        }\r
+      }\r
+      if (SubmitFormIsRequired) {\r
+        SubmitForm (Selection->FormSet, Selection->Form);\r
       }\r
     }\r
-  }\r
+  } while (Selection->Action == UI_ACTION_REFRESH_FORM);\r
 \r
   //\r
   // Record the old formset\r
@@ -1164,12 +1230,21 @@ SetupBrowser (
   gOldFormSet = FormSet;\r
 \r
 Done:\r
+  //\r
+  // Reset current form information to the initial setting when error happens or form exit.\r
+  //\r
+  if (EFI_ERROR (Status) || Selection->Action == UI_ACTION_EXIT) {\r
+    mCurrentHiiHandle = NULL;\r
+    CopyGuid (&mCurrentFormSetGuid, &gZeroGuid);\r
+    mCurrentFormId = 0;\r
+  }\r
+\r
   //\r
   // Unregister notify for Form package update\r
   //\r
-  Status = mHiiDatabase->UnregisterPackageNotify (\r
-                           mHiiDatabase,\r
-                           NotifyHandle\r
-                           );\r
+  mHiiDatabase->UnregisterPackageNotify (\r
+                   mHiiDatabase,\r
+                   NotifyHandle\r
+                   );\r
   return Status;\r
 }\r