]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
Rollback patch 14537 & 14538, because patch 14537 is not tested by Laszlo Ersek,...
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Presentation.c
index 0372f2755bda5f8079f9d9be86ef8471e659b488..4cd71e5d440d04e8653243361d9d1b705045c99d 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
 Utility functions for UI presentation.\r
 \r
-Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -300,7 +300,7 @@ DisplayPageFrame (
   ClearLines (\r
     LocalScreen.LeftColumn,\r
     LocalScreen.RightColumn,\r
-    LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT,\r
+    LocalScreen.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight,\r
     LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1,\r
     KEYHELP_TEXT | KEYHELP_BACKGROUND\r
     );\r
@@ -348,14 +348,14 @@ DisplayPageFrame (
       // +------------------------------------------------------------------------------+\r
       //\r
       Character = BOXDRAW_DOWN_RIGHT;\r
-      PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT, Character);\r
+      PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight, Character);\r
 \r
       PrintString (Buffer);\r
 \r
       Character = BOXDRAW_DOWN_LEFT;\r
       PrintChar (Character);\r
       Character = BOXDRAW_VERTICAL;\r
-      for (Row = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT + 1;\r
+      for (Row = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight + 1;\r
            Row <= LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 2;\r
            Row++\r
           ) {\r
@@ -468,7 +468,6 @@ DisplayForm (
   CHAR16                 *StringPtr;\r
   UINT16                 MenuItemCount;\r
   EFI_HII_HANDLE         Handle;\r
-  BOOLEAN                Suppress;\r
   EFI_SCREEN_DESCRIPTOR  LocalScreen;\r
   UINT16                 Width;\r
   UINTN                  ArrayEntry;\r
@@ -478,6 +477,7 @@ DisplayForm (
   UINT16                 NumberOfLines;\r
   EFI_STATUS             Status;\r
   UI_MENU_OPTION         *MenuOption;\r
+  UINT16                 GlyphWidth;\r
 \r
   Handle        = Selection->Handle;\r
   MenuItemCount = 0;\r
@@ -521,24 +521,16 @@ DisplayForm (
   while (!IsNull (&Selection->Form->StatementListHead, Link)) {\r
     Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
 \r
-    if (Statement->SuppressExpression != NULL) {\r
-      Suppress = Statement->SuppressExpression->Result.Value.b;\r
-    } else {\r
-      Suppress = FALSE;\r
-    }\r
-\r
-    if (Statement->DisableExpression != NULL) {\r
-      Suppress = (BOOLEAN) (Suppress || Statement->DisableExpression->Result.Value.b);\r
-    }\r
-\r
-    if (!Suppress) {\r
+    if (EvaluateExpressionList(Statement->Expression, FALSE, NULL, NULL) <= ExpressGrayOut) {\r
       StringPtr = GetToken (Statement->Prompt, Handle);\r
+      ASSERT (StringPtr != NULL);\r
 \r
       Width     = GetWidth (Statement, Handle);\r
 \r
       NumberOfLines = 1;\r
       ArrayEntry = 0;\r
-      for (; GetLineByWidth (StringPtr, Width, &ArrayEntry, &OutputString) != 0x0000;) {\r
+      GlyphWidth = 1;\r
+      for (; GetLineByWidth (StringPtr, Width, &GlyphWidth,&ArrayEntry, &OutputString) != 0x0000;) {\r
         //\r
         // If there is more string to process print on the next row and increment the Skip value\r
         //\r
@@ -553,7 +545,7 @@ 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
-      MenuOption = UiAddMenuOption (StringPtr, Selection->Handle, Statement, NumberOfLines, MenuItemCount);\r
+      MenuOption = UiAddMenuOption (StringPtr, Selection->Handle, Selection->Form, Statement, NumberOfLines, MenuItemCount);\r
       MenuItemCount++;\r
 \r
       if (MenuOption->IsQuestion && !MenuOption->ReadOnly) {\r
@@ -583,13 +575,10 @@ InitializeBrowserStrings (
   VOID\r
   )\r
 {\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
   gEnterCommitString    = GetToken (STRING_TOKEN (ENTER_COMMIT_STRING), gHiiHandle);\r
   gEnterEscapeString    = GetToken (STRING_TOKEN (ENTER_ESCAPE_STRING), gHiiHandle);\r
   gEscapeString         = GetToken (STRING_TOKEN (ESCAPE_STRING), gHiiHandle);\r
-  gSaveFailed           = GetToken (STRING_TOKEN (SAVE_FAILED), gHiiHandle);\r
   gMoveHighlight        = GetToken (STRING_TOKEN (MOVE_HIGHLIGHT), gHiiHandle);\r
   gMakeSelection        = GetToken (STRING_TOKEN (MAKE_SELECTION), gHiiHandle);\r
   gDecNumericInput      = GetToken (STRING_TOKEN (DEC_NUMERIC_INPUT), gHiiHandle);\r
@@ -613,6 +602,7 @@ InitializeBrowserStrings (
   gSaveChanges          = GetToken (STRING_TOKEN (SAVE_CHANGES), gHiiHandle);\r
   gOptionMismatch       = GetToken (STRING_TOKEN (OPTION_MISMATCH), gHiiHandle);\r
   gFormSuppress         = GetToken (STRING_TOKEN (FORM_SUPPRESSED), gHiiHandle);\r
+  gProtocolNotFound     = GetToken (STRING_TOKEN (PROTOCOL_NOT_FOUND), gHiiHandle);\r
   return ;\r
 }\r
 \r
@@ -626,8 +616,6 @@ FreeBrowserStrings (
   VOID\r
   )\r
 {\r
-  FreePool (gFunctionNineString);\r
-  FreePool (gFunctionTenString);\r
   FreePool (gEnterString);\r
   FreePool (gEnterCommitString);\r
   FreePool (gEnterEscapeString);\r
@@ -655,9 +643,68 @@ FreeBrowserStrings (
   FreePool (gSaveChanges);\r
   FreePool (gOptionMismatch);\r
   FreePool (gFormSuppress);\r
+  FreePool (gProtocolNotFound);\r
   return ;\r
 }\r
 \r
+/**\r
+  Show all registered HotKey help strings on bottom Rows.\r
+\r
+**/\r
+VOID\r
+PrintHotKeyHelpString (\r
+  VOID\r
+  )\r
+{\r
+  UINTN                  CurrentCol;\r
+  UINTN                  CurrentRow;\r
+  UINTN                  BottomRowOfHotKeyHelp;\r
+  UINTN                  ColumnWidth;\r
+  UINTN                  Index;\r
+  EFI_SCREEN_DESCRIPTOR  LocalScreen;\r
+  LIST_ENTRY             *Link;\r
+  BROWSER_HOT_KEY        *HotKey;\r
+\r
+  CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
+  ColumnWidth            = (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3;\r
+  BottomRowOfHotKeyHelp  = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 3;\r
+\r
+  //\r
+  // Calculate total number of Register HotKeys. \r
+  //\r
+  Index = 0;\r
+  Link  = GetFirstNode (&gBrowserHotKeyList);\r
+  while (!IsNull (&gBrowserHotKeyList, Link)) {\r
+    HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);\r
+    //\r
+    // Help string can't exceed ColumnWidth. One Row will show three Help information. \r
+    //\r
+    if (StrLen (HotKey->HelpString) > ColumnWidth) {\r
+      HotKey->HelpString[ColumnWidth] = L'\0';\r
+    }\r
+    //\r
+    // Calculate help information Column and Row.\r
+    //\r
+    if ((Index % 3) != 2) {\r
+      CurrentCol = LocalScreen.LeftColumn + (2 - Index % 3) * ColumnWidth;\r
+    } else {\r
+      CurrentCol = LocalScreen.LeftColumn + 2;\r
+    }\r
+    CurrentRow = BottomRowOfHotKeyHelp - Index / 3;\r
+    //\r
+    // Print HotKey help string on bottom Row.\r
+    //\r
+    PrintStringAt (CurrentCol, CurrentRow, HotKey->HelpString);\r
+\r
+    //\r
+    // Get Next Hot Key.\r
+    //\r
+    Link = GetNextNode (&gBrowserHotKeyList, Link);\r
+    Index ++;\r
+  }\r
+  \r
+  return;\r
+}\r
 \r
 /**\r
   Update key's help imformation.\r
@@ -693,13 +740,13 @@ UpdateKeyHelp (
   CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
 \r
   SecCol            = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3;\r
-  ThdCol            = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3;\r
+  ThdCol            = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3 * 2;\r
 \r
   StartColumnOfHelp = LocalScreen.LeftColumn + 2;\r
   LeftColumnOfHelp  = LocalScreen.LeftColumn + 1;\r
   RightColumnOfHelp = LocalScreen.RightColumn - 2;\r
-  TopRowOfHelp      = LocalScreen.BottomRow - 4;\r
-  BottomRowOfHelp   = LocalScreen.BottomRow - 3;\r
+  TopRowOfHelp      = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight + 1;\r
+  BottomRowOfHelp   = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 2;\r
 \r
   Statement = MenuOption->ThisTag;\r
   switch (Statement->Operand) {\r
@@ -711,11 +758,15 @@ UpdateKeyHelp (
     ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
 \r
     if (!Selected) {\r
+      //\r
+      // On system setting, HotKey will show on every form.\r
+      //\r
+      if (gBrowserSettingScope == SystemLevel ||\r
+          (Selection->FormEditable && gFunctionKeySetting != NONE_FUNCTION_KEY_SETTING)) {\r
+        PrintHotKeyHelpString ();\r
+      }\r
+\r
       if ((gClassOfVfr & FORMSET_CLASS_PLATFORM_SETUP) == 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
@@ -770,11 +821,14 @@ UpdateKeyHelp (
   case EFI_IFR_CHECKBOX_OP:\r
     ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
 \r
+    //\r
+    // On system setting, HotKey will show on every form.\r
+    //\r
+    if (gBrowserSettingScope == SystemLevel ||\r
+        (Selection->FormEditable && gFunctionKeySetting != NONE_FUNCTION_KEY_SETTING)) {\r
+      PrintHotKeyHelpString ();\r
+    }\r
     if ((gClassOfVfr & FORMSET_CLASS_PLATFORM_SETUP) == 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
@@ -792,11 +846,14 @@ UpdateKeyHelp (
     ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
 \r
     if (!Selected) {\r
+      //\r
+      // On system setting, HotKey will show on every form.\r
+      //\r
+      if (gBrowserSettingScope == SystemLevel ||\r
+          (Selection->FormEditable && gFunctionKeySetting != NONE_FUNCTION_KEY_SETTING)) {\r
+        PrintHotKeyHelpString ();\r
+      }\r
       if ((gClassOfVfr & FORMSET_CLASS_PLATFORM_SETUP) == 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
@@ -941,7 +998,7 @@ FindNextMenu (
   CHAR16                  YesResponse;\r
   CHAR16                  NoResponse;\r
   EFI_INPUT_KEY           Key;\r
-  EFI_STATUS              Status;\r
+  BROWSER_SETTING_SCOPE   Scope;\r
   \r
   CurrentMenu = Selection->CurrentMenu;\r
 \r
@@ -954,9 +1011,64 @@ FindNextMenu (
       // The parent menu and current menu are in the same formset\r
       //\r
       Selection->Action = UI_ACTION_REFRESH_FORM;\r
+      Scope             = FormLevel;\r
     } else {\r
       Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+      CopyMem (&Selection->FormSetGuid, &CurrentMenu->Parent->FormSetGuid, sizeof (EFI_GUID));\r
+      Selection->Handle = CurrentMenu->Parent->HiiHandle;\r
+      Scope             = FormSetLevel;\r
+    }\r
+\r
+    //\r
+    // Form Level Check whether the data is changed.\r
+    //\r
+    if ((gBrowserSettingScope == FormLevel && Selection->Form->NvUpdateRequired) ||\r
+        (gBrowserSettingScope == FormSetLevel && IsNvUpdateRequired(Selection->FormSet) && Scope == FormSetLevel)) {\r
+      gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+  \r
+      YesResponse = gYesResponse[0];\r
+      NoResponse  = gNoResponse[0];\r
+  \r
+      //\r
+      // If NV flag is up, prompt user\r
+      //\r
+      do {\r
+        CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gSaveChanges, gAreYouSure, 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
+      if (Key.ScanCode == SCAN_ESC) {\r
+        //\r
+        // User hits the ESC key, Ingore. \r
+        //\r
+        if (Repaint != NULL) {\r
+          *Repaint = TRUE;\r
+        }\r
+        if (NewLine != NULL) {\r
+          *NewLine = TRUE;\r
+        }\r
+\r
+        Selection->Action = UI_ACTION_NONE;\r
+        return FALSE;\r
+      }\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, Scope);\r
+      } else {\r
+        //\r
+        // If the user hits the NoResponse key\r
+        //\r
+        DiscardForm (Selection->FormSet, Selection->Form, Scope);\r
+      }\r
     }\r
+\r
     Selection->Statement = NULL;\r
 \r
     Selection->FormId = CurrentMenu->Parent->FormId;\r
@@ -980,8 +1092,8 @@ FindNextMenu (
   //\r
   // We are going to leave current FormSet, so check uncommited data in this FormSet\r
   //\r
-  if (IsNvUpdateRequired(Selection->FormSet)) {\r
-    Status      = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+  if (gBrowserSettingScope != SystemLevel && IsNvUpdateRequired(Selection->FormSet)) {\r
+    gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
 \r
     YesResponse = gYesResponse[0];\r
     NoResponse  = gNoResponse[0];\r
@@ -1014,16 +1126,23 @@ FindNextMenu (
       return FALSE;\r
     }\r
 \r
-    //\r
-    // If the user hits the YesResponse key\r
-    //\r
     if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse | UPPER_LOWER_CASE_OFFSET)) {\r
-      Status = SubmitForm (Selection->FormSet, Selection->Form, FALSE);\r
+      //\r
+      // If the user hits the YesResponse key\r
+      //\r
+      SubmitForm (Selection->FormSet, Selection->Form, FormSetLevel);\r
+    } else {\r
+      //\r
+      // If the user hits the NoResponse key\r
+      //\r
+      DiscardForm (Selection->FormSet, Selection->Form, FormSetLevel);\r
     }\r
   }\r
 \r
   Selection->Statement = NULL;\r
-  CurrentMenu->QuestionId = 0;  \r
+  if (CurrentMenu != NULL) {\r
+    CurrentMenu->QuestionId = 0;\r
+  }\r
 \r
   Selection->Action = UI_ACTION_EXIT;\r
   return TRUE;\r
@@ -1058,14 +1177,14 @@ ProcessCallBackFunction (
   EFI_IFR_TYPE_VALUE              *TypeValue;\r
   FORM_BROWSER_STATEMENT          *Statement;\r
   BOOLEAN                         SubmitFormIsRequired;\r
-  BOOLEAN                         SingleForm;\r
   BOOLEAN                         DiscardFormIsRequired;\r
   BOOLEAN                         NeedExit;\r
   LIST_ENTRY                      *Link;\r
+  BROWSER_SETTING_SCOPE           SettingLevel;\r
 \r
   ConfigAccess = Selection->FormSet->ConfigAccess;\r
   SubmitFormIsRequired  = FALSE;\r
-  SingleForm            = FALSE;\r
+  SettingLevel          = FormSetLevel;\r
   DiscardFormIsRequired = FALSE;\r
   NeedExit              = FALSE;\r
   Status                = EFI_SUCCESS;\r
@@ -1094,11 +1213,8 @@ ProcessCallBackFunction (
     //\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
+    if (Statement->Expression != NULL) {\r
+      if (EvaluateExpressionList(Statement->Expression, TRUE, Selection->FormSet, Selection->Form) == ExpressDisable) {\r
         continue;\r
       }\r
     }\r
@@ -1122,58 +1238,85 @@ ProcessCallBackFunction (
                              &ActionRequest\r
                              );\r
     if (!EFI_ERROR (Status)) {\r
-      switch (ActionRequest) {\r
-      case EFI_BROWSER_ACTION_REQUEST_RESET:\r
-        gResetRequired = TRUE;\r
-        break;\r
+      //\r
+      // Only for EFI_BROWSER_ACTION_CHANGED need to handle this ActionRequest.\r
+      //\r
+      if (Action == EFI_BROWSER_ACTION_CHANGED) {\r
+        switch (ActionRequest) {\r
+        case EFI_BROWSER_ACTION_REQUEST_RESET:\r
+          DiscardFormIsRequired = TRUE;\r
+          gResetRequired = TRUE;\r
+          Selection->Action = UI_ACTION_EXIT;\r
+          break;\r
 \r
-      case EFI_BROWSER_ACTION_REQUEST_SUBMIT:\r
-        SubmitFormIsRequired = TRUE;\r
-        break;\r
+        case EFI_BROWSER_ACTION_REQUEST_SUBMIT:\r
+          SubmitFormIsRequired = TRUE;\r
+          Selection->Action = UI_ACTION_EXIT;\r
+          break;\r
 \r
-      case EFI_BROWSER_ACTION_REQUEST_EXIT:\r
-        Selection->Action = UI_ACTION_EXIT;\r
-        break;\r
+        case EFI_BROWSER_ACTION_REQUEST_EXIT:\r
+          DiscardFormIsRequired = TRUE;\r
+          Selection->Action = UI_ACTION_EXIT;\r
+          break;\r
 \r
-      case EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT:\r
-        SubmitFormIsRequired  = TRUE;\r
-        SingleForm            = TRUE;\r
-        NeedExit              = TRUE;\r
-        break;\r
+        case EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT:\r
+          SubmitFormIsRequired  = TRUE;\r
+          SettingLevel          = FormLevel;\r
+          NeedExit              = TRUE;\r
+          break;\r
 \r
-      case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT:\r
-        DiscardFormIsRequired = TRUE;\r
-        SingleForm            = TRUE;      \r
-        NeedExit              = TRUE;\r
-        break;\r
+        case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT:\r
+          DiscardFormIsRequired = TRUE;\r
+          SettingLevel          = FormLevel;      \r
+          NeedExit              = TRUE;\r
+          break;\r
 \r
-      case EFI_BROWSER_ACTION_REQUEST_FORM_APPLY:\r
-        SubmitFormIsRequired  = TRUE;\r
-        SingleForm            = TRUE;\r
-        break;\r
+        case EFI_BROWSER_ACTION_REQUEST_FORM_APPLY:\r
+          SubmitFormIsRequired  = TRUE;\r
+          SettingLevel          = FormLevel;\r
+          break;\r
 \r
-      case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD:\r
-        DiscardFormIsRequired = TRUE;\r
-        SingleForm            = TRUE;\r
-        break;\r
+        case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD:\r
+          DiscardFormIsRequired = TRUE;\r
+          SettingLevel          = FormLevel;\r
+          break;\r
 \r
-      default:\r
-        break;\r
+        default:\r
+          break;\r
+        }\r
       }\r
-    } else if (Status == EFI_UNSUPPORTED) {\r
+\r
       //\r
-      // If return EFI_UNSUPPORTED, also consider Hii driver suceess deal with it.\r
+      // According the spec, return value from call back of "changing" and \r
+      // "retrieve" should update to the question's temp buffer.\r
+      //\r
+      if (Action == EFI_BROWSER_ACTION_CHANGING || Action == EFI_BROWSER_ACTION_RETRIEVE) {\r
+        SetQuestionValue(Selection->FormSet, Selection->Form, Statement, GetSetValueWithEditBuffer);\r
+      }\r
+    } else {\r
       //\r
-      Status = EFI_SUCCESS;\r
+      // According the spec, return fail from call back of "changing" and \r
+      // "retrieve", should restore the question's value.\r
+      //\r
+      if (Action  == EFI_BROWSER_ACTION_CHANGING || Action == EFI_BROWSER_ACTION_RETRIEVE) {\r
+        GetQuestionValue(Selection->FormSet, Selection->Form, Statement, GetSetValueWithEditBuffer);\r
+      }\r
+\r
+      if (Status == EFI_UNSUPPORTED) {\r
+        //\r
+        // If return EFI_UNSUPPORTED, also consider Hii driver suceess deal with it.\r
+        //\r
+        Status = EFI_SUCCESS;\r
+      }\r
     }\r
   }\r
 \r
   if (SubmitFormIsRequired && !SkipSaveOrDiscard) {\r
-    SubmitForm (Selection->FormSet, Selection->Form, SingleForm);\r
+    SubmitForm (Selection->FormSet, Selection->Form, SettingLevel);\r
   }\r
 \r
   if (DiscardFormIsRequired && !SkipSaveOrDiscard) {\r
-    DiscardForm (Selection->FormSet, Selection->Form, SingleForm);\r
+    DiscardForm (Selection->FormSet, Selection->Form, SettingLevel);\r
   }\r
 \r
   if (NeedExit) {\r
@@ -1183,6 +1326,57 @@ ProcessCallBackFunction (
   return Status;\r
 }\r
 \r
+/**\r
+  Call the retrieve type call back function for one question to get the initialize data.\r
+  \r
+  This function only used when in the initialize stage, because in this stage, the \r
+  Selection->Form is not ready. For other case, use the ProcessCallBackFunction instead.\r
+\r
+  @param ConfigAccess          The config access protocol produced by the hii driver.\r
+  @param Statement             The Question which need to call.\r
+\r
+  @retval EFI_SUCCESS          The call back function excutes successfully.\r
+  @return Other value if the call back function failed to excute.  \r
+**/\r
+EFI_STATUS \r
+ProcessRetrieveForQuestion (\r
+  IN     EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess,\r
+  IN     FORM_BROWSER_STATEMENT          *Statement\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  EFI_BROWSER_ACTION_REQUEST      ActionRequest;\r
+  EFI_HII_VALUE                   *HiiValue;\r
+  EFI_IFR_TYPE_VALUE              *TypeValue;\r
+\r
+  Status                = EFI_SUCCESS;\r
+  ActionRequest         = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+    \r
+  if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  HiiValue  = &Statement->HiiValue;\r
+  TypeValue = &HiiValue->Value;\r
+  if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
+    //\r
+    // For OrderedList, passing in the value buffer to Callback()\r
+    //\r
+    TypeValue = (EFI_IFR_TYPE_VALUE *) Statement->BufferValue;\r
+  }\r
+    \r
+  ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+  Status = ConfigAccess->Callback (\r
+                           ConfigAccess,\r
+                           EFI_BROWSER_ACTION_RETRIEVE,\r
+                           Statement->QuestionId,\r
+                           HiiValue->Type,\r
+                           TypeValue,\r
+                           &ActionRequest\r
+                           );\r
+  return Status;\r
+}\r
+\r
 /**\r
   The worker function that send the displays to the screen. On output,\r
   the selection made by user is returned.\r
@@ -1206,12 +1400,9 @@ SetupBrowser (
   EFI_HANDLE                      NotifyHandle;\r
   FORM_BROWSER_STATEMENT          *Statement;\r
   EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess;\r
-  FORM_BROWSER_FORMSET            *FormSet;\r
   EFI_INPUT_KEY                   Key;\r
 \r
   gMenuRefreshHead = NULL;\r
-  gResetRequired = FALSE;\r
-  FormSet = Selection->FormSet;\r
   ConfigAccess = Selection->FormSet->ConfigAccess;\r
 \r
   //\r
@@ -1237,7 +1428,27 @@ SetupBrowser (
     goto Done;\r
   }\r
 \r
+  //\r
+  // Update gOldFormSet on maintain back up FormSet list.\r
+  // And, make gOldFormSet point to current FormSet. \r
+  //\r
+  if (gOldFormSet != NULL) {\r
+    RemoveEntryList (&gOldFormSet->Link);\r
+    DestroyFormSet (gOldFormSet);\r
+  }\r
+  gOldFormSet = Selection->FormSet;\r
+  InsertTailList (&gBrowserFormSetList, &gOldFormSet->Link);\r
+\r
   do {\r
+    //\r
+    // IFR is updated, force to reparse the IFR binary\r
+    //\r
+    if (mHiiPackageListUpdated) {\r
+      Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+      mHiiPackageListUpdated = FALSE;\r
+      break;\r
+    }\r
+\r
     //\r
     // Initialize Selection->Form\r
     //\r
@@ -1265,13 +1476,7 @@ SetupBrowser (
     // Check Form is suppressed.\r
     //\r
     if (Selection->Form->SuppressExpression != NULL) {\r
-      Status = EvaluateExpression (Selection->FormSet, Selection->Form, Selection->Form->SuppressExpression);\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
+      if (EvaluateExpressionList(Selection->Form->SuppressExpression, TRUE, Selection->FormSet, Selection->Form) == ExpressSuppress) {\r
         //\r
         // Form is suppressed. \r
         //\r
@@ -1284,11 +1489,6 @@ SetupBrowser (
       }\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
@@ -1323,7 +1523,7 @@ SetupBrowser (
       if (mHiiPackageListUpdated) {\r
         Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
         mHiiPackageListUpdated = FALSE;\r
-        goto Done;\r
+        break;\r
       }\r
     }\r
 \r
@@ -1347,7 +1547,7 @@ SetupBrowser (
     if (mHiiPackageListUpdated) {\r
       Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
       mHiiPackageListUpdated = FALSE;\r
-      goto Done;\r
+      break;\r
     }\r
 \r
     //\r
@@ -1372,21 +1572,22 @@ SetupBrowser (
         gResetRequired = TRUE;\r
       }\r
 \r
-      //\r
-      // Reset FormPackage update flag\r
-      //\r
-      mHiiPackageListUpdated = FALSE;\r
-\r
       if ((ConfigAccess != NULL) && \r
           ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) && \r
           (Statement->Operand != EFI_IFR_PASSWORD_OP)) {\r
-\r
         Status = ProcessCallBackFunction(Selection, Statement, EFI_BROWSER_ACTION_CHANGING, FALSE);         \r
-        if ((EFI_ERROR (Status)) && (Status != EFI_UNSUPPORTED)) {\r
+        if (Statement->Operand == EFI_IFR_REF_OP && Selection->Action != UI_ACTION_EXIT) {\r
           //\r
-          // Callback return error status other than EFI_UNSUPPORTED\r
+          // Process dynamic update ref opcode.\r
           //\r
-          if (Statement->Operand == EFI_IFR_REF_OP) {\r
+          if (!EFI_ERROR (Status)) {\r
+            Status = ProcessGotoOpCode(Statement, Selection, NULL, NULL);\r
+          }\r
+          \r
+          //\r
+          // Callback return error status or status return from process goto opcode.\r
+          //\r
+          if (EFI_ERROR (Status)) {\r
             //\r
             // Cross reference will not be taken\r
             //\r
@@ -1394,17 +1595,10 @@ SetupBrowser (
             Selection->QuestionId = 0;\r
           }\r
         }\r
-      }\r
 \r
-      //\r
-      // Check whether Form Package has been updated during Callback\r
-      //\r
-      if (mHiiPackageListUpdated && (Selection->Action == UI_ACTION_REFRESH_FORM)) {\r
-        //\r
-        // Force to reparse IFR binary of target Formset\r
-        //\r
-        mHiiPackageListUpdated = FALSE;\r
-        Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+        if (!EFI_ERROR (Status) && Statement->Operand != EFI_IFR_REF_OP) {\r
+          ProcessCallBackFunction(Selection, Statement, EFI_BROWSER_ACTION_CHANGED, FALSE);\r
+        }\r
       }\r
     }\r
 \r
@@ -1425,14 +1619,6 @@ SetupBrowser (
     }\r
   } while (Selection->Action == UI_ACTION_REFRESH_FORM);\r
 \r
-  //\r
-  // Record the old formset\r
-  //\r
-  if (gOldFormSet != NULL) {\r
-    DestroyFormSet (gOldFormSet);\r
-  }\r
-  gOldFormSet = FormSet;\r
-\r
 Done:\r
   //\r
   // Reset current form information to the initial setting when error happens or form exit.\r