]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
Support call of SendForm() from Callback(), i.e. nested call of SendForm().
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Presentation.c
index 2d0e1721c831dae6653a2a8a91b5837e9e605f72..93267f0fdeecfce49ad10287fa1769be543eea80 100644 (file)
@@ -31,11 +31,11 @@ UI_MENU_SELECTION  *gCurrentSelection;
 **/\r
 VOID\r
 ClearLines (\r
-  UINTN                                       LeftColumn,\r
-  UINTN                                       RightColumn,\r
-  UINTN                                       TopRow,\r
-  UINTN                                       BottomRow,\r
-  UINTN                                       TextAttribute\r
+  IN UINTN               LeftColumn,\r
+  IN UINTN               RightColumn,\r
+  IN UINTN               TopRow,\r
+  IN UINTN               BottomRow,\r
+  IN UINTN               TextAttribute\r
   )\r
 {\r
   CHAR16  *Buffer;\r
@@ -80,8 +80,8 @@ ClearLines (
 **/\r
 VOID\r
 NewStrCat (\r
-  CHAR16                                      *Destination,\r
-  CHAR16                                      *Source\r
+  IN OUT CHAR16               *Destination,\r
+  IN     CHAR16               *Source\r
   )\r
 {\r
   UINTN Length;\r
@@ -106,7 +106,7 @@ NewStrCat (
 \r
   This function handles the Unicode string with NARROW_CHAR\r
   and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR\r
-  does not count in the resultant output. If a WIDE_CHAR is \r
+  does not count in the resultant output. If a WIDE_CHAR is\r
   hit, then 2 Unicode character will consume an output storage\r
   space with size of CHAR16 till a NARROW_CHAR is hit.\r
 \r
@@ -117,7 +117,7 @@ NewStrCat (
 **/\r
 UINTN\r
 GetStringWidth (\r
-  CHAR16                                      *String\r
+  IN CHAR16               *String\r
   )\r
 {\r
   UINTN Index;\r
@@ -209,7 +209,7 @@ DisplayPageFrame (
     Buffer[Index] = Character;\r
   }\r
 \r
-  if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {\r
+  if (gClassOfVfr == FORMSET_CLASS_FRONT_PAGE) {\r
     //\r
     //    ClearLines(0, LocalScreen.RightColumn, 0, BANNER_HEIGHT-1, BANNER_TEXT | BANNER_BACKGROUND);\r
     //\r
@@ -236,11 +236,11 @@ DisplayPageFrame (
 \r
         ASSERT (RowIdx < BANNER_HEIGHT);\r
         ASSERT (ColumnIdx < BANNER_COLUMNS);\r
-        \r
-        if (BannerData->Banner[RowIdx][ColumnIdx] != 0x0000) {\r
+\r
+        if (gBannerData->Banner[RowIdx][ColumnIdx] != 0x0000) {\r
           StrFrontPageBanner = GetToken (\r
-                                BannerData->Banner[RowIdx][ColumnIdx],\r
-                                FrontPageHandle\r
+                                gBannerData->Banner[RowIdx][ColumnIdx],\r
+                                gFrontPageHandle\r
                                 );\r
         } else {\r
           continue;\r
@@ -290,7 +290,7 @@ DisplayPageFrame (
     KEYHELP_TEXT | KEYHELP_BACKGROUND\r
     );\r
 \r
-  if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {\r
+  if (gClassOfVfr != FORMSET_CLASS_FRONT_PAGE) {\r
     ClearLines (\r
       LocalScreen.LeftColumn,\r
       LocalScreen.RightColumn,\r
@@ -325,7 +325,7 @@ DisplayPageFrame (
     Character = BOXDRAW_UP_LEFT;\r
     PrintChar (Character);\r
 \r
-    if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {\r
+    if (gClassOfVfr == FORMSET_CLASS_PLATFORM_SETUP) {\r
       //\r
       // Print Bottom border line\r
       // +------------------------------------------------------------------------------+\r
@@ -406,7 +406,7 @@ EvaluateFormExpressions (
 \r
 /*\r
 +------------------------------------------------------------------------------+\r
-?F2=Previous Page                 Setup Page                                  ?\r
+?                                 Setup Page                                  ?\r
 +------------------------------------------------------------------------------+\r
 \r
 \r
@@ -433,9 +433,9 @@ EvaluateFormExpressions (
 \r
 /**\r
 \r
-  \r
+\r
   Display form and wait for user to select one menu option, then return it.\r
-  \r
+\r
   @param Selection       On input, Selection tell setup browser the information\r
                          about the Selection, form and formset to be displayed.\r
                          On output, Selection return the screen item that is selected\r
@@ -460,6 +460,7 @@ DisplayForm (
   FORM_BROWSER_STATEMENT *Statement;\r
   UINT16                 NumberOfLines;\r
   EFI_STATUS             Status;\r
+  UI_MENU_OPTION         *MenuOption;\r
 \r
   Handle        = Selection->Handle;\r
   MenuItemCount = 0;\r
@@ -472,7 +473,7 @@ DisplayForm (
 \r
   StringPtr = GetToken (Selection->Form->FormTitle, Handle);\r
 \r
-  if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {\r
+  if (gClassOfVfr != FORMSET_CLASS_FRONT_PAGE) {\r
     gST->ConOut->SetAttribute (gST->ConOut, TITLE_TEXT | TITLE_BACKGROUND);\r
     PrintStringAt (\r
       (LocalScreen.RightColumn + LocalScreen.LeftColumn - GetStringWidth (StringPtr) / 2) / 2,\r
@@ -481,16 +482,6 @@ DisplayForm (
       );\r
   }\r
 \r
-  if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {\r
-    gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
-\r
-    //\r
-    // Display the infrastructure strings\r
-    //\r
-    if (!IsListEmpty (&gMenuList)) {\r
-      PrintStringAt (LocalScreen.LeftColumn + 2, LocalScreen.TopRow + 1, gFunctionTwoString);\r
-    }\r
-  }\r
   //\r
   // Remove Buffer allocated for StringPtr after it has been used.\r
   //\r
@@ -504,6 +495,7 @@ DisplayForm (
     return Status;\r
   }\r
 \r
+  Selection->FormEditable = FALSE;\r
   Link = GetFirstNode (&Selection->Form->StatementListHead);\r
   while (!IsNull (&Selection->Form->StatementListHead, Link)) {\r
     Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
@@ -514,6 +506,10 @@ DisplayForm (
       Suppress = FALSE;\r
     }\r
 \r
+    if (Statement->DisableExpression != NULL) {\r
+      Suppress = (BOOLEAN) (Suppress || Statement->DisableExpression->Result.Value.b);\r
+    }\r
+\r
     if (!Suppress) {\r
       StringPtr = GetToken (Statement->Prompt, Handle);\r
 \r
@@ -536,8 +532,15 @@ DisplayForm (
       // We are NOT!! removing this StringPtr buffer via FreePool since it is being used in the menuoptions, we will do\r
       // it in UiFreeMenu.\r
       //\r
-      UiAddMenuOption (StringPtr, Selection->Handle, Statement, NumberOfLines, MenuItemCount);\r
+      MenuOption = UiAddMenuOption (StringPtr, Selection->Handle, Statement, NumberOfLines, MenuItemCount);\r
       MenuItemCount++;\r
+\r
+      if (MenuOption->IsQuestion && !MenuOption->ReadOnly) {\r
+        //\r
+        // At least one item is not readonly, this Form is considered as editable\r
+        //\r
+        Selection->FormEditable = TRUE;\r
+      }\r
     }\r
 \r
     Link = GetNextNode (&Selection->Form->StatementListHead, Link);\r
@@ -559,8 +562,6 @@ InitializeBrowserStrings (
   VOID\r
   )\r
 {\r
-  gFunctionOneString    = GetToken (STRING_TOKEN (FUNCTION_ONE_STRING), gHiiHandle);\r
-  gFunctionTwoString    = GetToken (STRING_TOKEN (FUNCTION_TWO_STRING), gHiiHandle);\r
   gFunctionNineString   = GetToken (STRING_TOKEN (FUNCTION_NINE_STRING), gHiiHandle);\r
   gFunctionTenString    = GetToken (STRING_TOKEN (FUNCTION_TEN_STRING), gHiiHandle);\r
   gEnterString          = GetToken (STRING_TOKEN (ENTER_STRING), gHiiHandle);\r
@@ -603,8 +604,6 @@ FreeBrowserStrings (
   VOID\r
   )\r
 {\r
-  FreePool (gFunctionOneString);\r
-  FreePool (gFunctionTwoString);\r
   FreePool (gFunctionNineString);\r
   FreePool (gFunctionTenString);\r
   FreePool (gEnterString);\r
@@ -640,12 +639,14 @@ FreeBrowserStrings (
 /**\r
   Update key's help imformation.\r
 \r
+  @param Selection       Tell setup browser the information about the Selection\r
   @param  MenuOption     The Menu option\r
   @param  Selected       Whether or not a tag be selected\r
 \r
 **/\r
 VOID\r
 UpdateKeyHelp (\r
+  IN  UI_MENU_SELECTION           *Selection,\r
   IN  UI_MENU_OPTION              *MenuOption,\r
   IN  BOOLEAN                     Selected\r
   )\r
@@ -671,10 +672,6 @@ UpdateKeyHelp (
   TopRowOfHelp      = LocalScreen.BottomRow - 4;\r
   BottomRowOfHelp   = LocalScreen.BottomRow - 3;\r
 \r
-  if (gClassOfVfr == EFI_GENERAL_APPLICATION_SUBCLASS) {\r
-    return ;\r
-  }\r
-\r
   gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
 \r
   Statement = MenuOption->ThisTag;\r
@@ -687,10 +684,11 @@ UpdateKeyHelp (
     ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
 \r
     if (!Selected) {\r
-      if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {\r
-        PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString);\r
-        PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);\r
-        PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);\r
+      if (gClassOfVfr == FORMSET_CLASS_PLATFORM_SETUP) {\r
+        if (Selection->FormEditable) {\r
+          PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);\r
+          PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);\r
+        }\r
         PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\r
       }\r
 \r
@@ -743,10 +741,11 @@ UpdateKeyHelp (
   case EFI_IFR_CHECKBOX_OP:\r
     ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
 \r
-    if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {\r
-      PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString);\r
-      PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);\r
-      PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);\r
+    if (gClassOfVfr == FORMSET_CLASS_PLATFORM_SETUP) {\r
+      if (Selection->FormEditable) {\r
+        PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);\r
+        PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);\r
+      }\r
       PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\r
     }\r
 \r
@@ -763,10 +762,11 @@ UpdateKeyHelp (
     ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
 \r
     if (!Selected) {\r
-      if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {\r
-        PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString);\r
-        PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);\r
-        PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);\r
+      if (gClassOfVfr == FORMSET_CLASS_PLATFORM_SETUP) {\r
+        if (Selection->FormEditable) {\r
+          PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);\r
+          PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);\r
+        }\r
         PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\r
       }\r
 \r
@@ -857,15 +857,11 @@ SetupBrowser (
   EFI_HII_VALUE                   *HiiValue;\r
   FORM_BROWSER_STATEMENT          *Statement;\r
   EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess;\r
-  EFI_INPUT_KEY                   Key;\r
-  CHAR16                          YesResponse;\r
-  CHAR16                          NoResponse;\r
+  FORM_BROWSER_FORMSET            *FormSet;\r
 \r
   gMenuRefreshHead = NULL;\r
   gResetRequired = FALSE;\r
-  gNvUpdateRequired = FALSE;\r
-\r
-  UiInitMenuList ();\r
+  FormSet = Selection->FormSet;\r
 \r
   //\r
   // Register notify for Form package update\r
@@ -882,12 +878,62 @@ SetupBrowser (
     return Status;\r
   }\r
 \r
-  do {\r
-    //\r
-    // Displays the Header and Footer borders\r
-    //\r
-    DisplayPageFrame ();\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
+      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
+  do {\r
     //\r
     // Initialize Selection->Form\r
     //\r
@@ -903,14 +949,26 @@ SetupBrowser (
       Selection->Form = IdToForm (Selection->FormSet, Selection->FormId);\r
     }\r
 \r
+    if (Selection->Form == NULL) {\r
+      //\r
+      // No Form to display\r
+      //\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
     //\r
     // Load Questions' Value for display\r
     //\r
-    Status = LoadFormConfig (Selection->FormSet, Selection->Form);\r
+    Status = LoadFormSetConfig (Selection->FormSet);\r
     if (EFI_ERROR (Status)) {\r
       return Status;\r
     }\r
 \r
+    //\r
+    // Displays the Header and Footer borders\r
+    //\r
+    DisplayPageFrame ();\r
+\r
     //\r
     // Display form\r
     //\r
@@ -944,7 +1002,6 @@ SetupBrowser (
           HiiValue->Value.string = NewString ((CHAR16 *) Statement->BufferValue, Selection->FormSet->HiiHandle);\r
         }\r
 \r
-        ConfigAccess = Selection->FormSet->ConfigAccess;\r
         if (ConfigAccess == NULL) {\r
           return EFI_UNSUPPORTED;\r
         }\r
@@ -982,6 +1039,17 @@ SetupBrowser (
           default:\r
             break;\r
           }\r
+        } else if (Status != EFI_UNSUPPORTED) {\r
+          //\r
+          // Callback return error status other than EFI_UNSUPPORTED\r
+          //\r
+          if (Statement->Operand == EFI_IFR_REF_OP) {\r
+            //\r
+            // Cross reference will not be taken\r
+            //\r
+            Selection->FormId = Selection->Form->FormId;\r
+            Selection->QuestionId = 0;\r
+          }\r
         }\r
       }\r
 \r
@@ -993,36 +1061,53 @@ SetupBrowser (
         // Force to reparse IFR binary of target Formset\r
         //\r
         Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+      }\r
+    }\r
+  } while (Selection->Action == UI_ACTION_REFRESH_FORM);\r
 \r
-        //\r
-        // Uncommitted data will be lost after IFR binary re-pasing, so confirm on whether to save\r
-        //\r
-        if (gNvUpdateRequired) {\r
-          Status      = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
-\r
-          YesResponse = gYesResponse[0];\r
-          NoResponse  = gNoResponse[0];\r
-\r
-          do {\r
-            CreateDialog (3, TRUE, 0, NULL, &Key, gEmptyString, gSaveChanges, gEmptyString);\r
-          } while\r
-          (\r
-            (Key.ScanCode != SCAN_ESC) &&\r
-            ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (NoResponse | UPPER_LOWER_CASE_OFFSET)) &&\r
-            ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (YesResponse | UPPER_LOWER_CASE_OFFSET))\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
-          if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse | UPPER_LOWER_CASE_OFFSET)) {\r
-            //\r
-            // If the user hits the YesResponse key\r
-            //\r
-            SubmitForm (Selection->FormSet, Selection->Form);\r
-          }\r
-        }\r
+      case EFI_BROWSER_ACTION_REQUEST_SUBMIT:\r
+        SubmitForm (Selection->FormSet, Selection->Form);\r
+        break;\r
+\r
+      case EFI_BROWSER_ACTION_REQUEST_EXIT:\r
+        gNvUpdateRequired = FALSE;\r
+        break;\r
+\r
+      default:\r
+        break;\r
       }\r
     }\r
-  } while (Selection->Action == UI_ACTION_REFRESH_FORM);\r
+  }\r
+\r
+  //\r
+  // Record the old formset\r
+  //\r
+  if (gOldFormSet != NULL) {\r
+    DestroyFormSet (gOldFormSet);\r
+  }\r
+  gOldFormSet = FormSet;\r
 \r
+Done:\r
   //\r
   // Unregister notify for Form package update\r
   //\r