]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Universal / DisplayEngineDxe / FormDisplay.c
index fffc67d6954899e8a58a5c239f596762f6a84006..3b034a1c82688700601910d5a4fff8a55677f535 100644 (file)
@@ -1,14 +1,9 @@
 /** @file\r
 Entry and initialization module for the browser.\r
 \r
-Copyright (c) 2007 - 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
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2014, Hewlett-Packard Development Company, L.P.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -48,7 +43,7 @@ SCAN_CODE_TO_SCREEN_OPERATION     gScanCodeToOperation[] = {
   }\r
 };\r
 \r
-UINTN mScanCodeNumber = sizeof (gScanCodeToOperation) / sizeof (gScanCodeToOperation[0]);\r
+UINTN mScanCodeNumber = ARRAY_SIZE (gScanCodeToOperation);\r
 \r
 SCREEN_OPERATION_T0_CONTROL_FLAG  gScreenOperationToControlFlag[] = {\r
   {\r
@@ -86,7 +81,7 @@ SCREEN_OPERATION_T0_CONTROL_FLAG  gScreenOperationToControlFlag[] = {
   {\r
     UiPageDown,\r
     CfUiPageDown\r
-  }, \r
+  },\r
   {\r
     UiHotKey,\r
     CfUiHotKey\r
@@ -97,8 +92,7 @@ EFI_GUID  gDisplayEngineGuid = {
   0xE38C1029, 0xE38F, 0x45b9, {0x8F, 0x0D, 0xE2, 0xE6, 0x0B, 0xC9, 0xB2, 0x62}\r
 };\r
 \r
-FORM_ENTRY_INFO               gFormEntryInfo;\r
-UINTN                         gSequence;\r
+BOOLEAN                       gMisMatch;\r
 EFI_SCREEN_DESCRIPTOR         gStatementDimensions;\r
 BOOLEAN                       mStatementLayoutIsChanged = TRUE;\r
 USER_INPUT                    *gUserInput;\r
@@ -113,10 +107,20 @@ FORM_ENTRY_INFO               gOldFormEntry = {0};
 //\r
 // Browser Global Strings\r
 //\r
+CHAR16            *gReconnectConfirmChanges;\r
+CHAR16            *gReconnectFail;\r
+CHAR16            *gReconnectRequired;\r
+CHAR16            *gChangesOpt;\r
 CHAR16            *gFormNotFound;\r
 CHAR16            *gNoSubmitIf;\r
-CHAR16            *gBrwoserError;\r
+CHAR16            *gBrowserError;\r
 CHAR16            *gSaveFailed;\r
+CHAR16            *gNoSubmitIfFailed;\r
+CHAR16            *gSaveProcess;\r
+CHAR16            *gSaveNoSubmitProcess;\r
+CHAR16            *gDiscardChange;\r
+CHAR16            *gJumpToFormSet;\r
+CHAR16            *gCheckError;\r
 CHAR16            *gPromptForData;\r
 CHAR16            *gPromptForPassword;\r
 CHAR16            *gPromptForNewPassword;\r
@@ -129,7 +133,30 @@ CHAR16            *gMiniString;
 CHAR16            *gOptionMismatch;\r
 CHAR16            *gFormSuppress;\r
 CHAR16            *gProtocolNotFound;\r
-\r
+CHAR16            *gConfirmDefaultMsg;\r
+CHAR16            *gConfirmSubmitMsg;\r
+CHAR16            *gConfirmDiscardMsg;\r
+CHAR16            *gConfirmResetMsg;\r
+CHAR16            *gConfirmExitMsg;\r
+CHAR16            *gConfirmSubmitMsg2nd;\r
+CHAR16            *gConfirmDefaultMsg2nd;\r
+CHAR16            *gConfirmResetMsg2nd;\r
+CHAR16            *gConfirmExitMsg2nd;\r
+CHAR16            *gConfirmOpt;\r
+CHAR16            *gConfirmOptYes;\r
+CHAR16            *gConfirmOptNo;\r
+CHAR16            *gConfirmOptOk;\r
+CHAR16            *gConfirmOptCancel;\r
+CHAR16            *gYesOption;\r
+CHAR16            *gNoOption;\r
+CHAR16            *gOkOption;\r
+CHAR16            *gCancelOption;\r
+CHAR16            *gErrorPopup;\r
+CHAR16            *gWarningPopup;\r
+CHAR16            *gInfoPopup;\r
+CHAR16            *gConfirmMsgConnect;\r
+CHAR16            *gConfirmMsgEnd;\r
+CHAR16            *gPasswordUnsupported;\r
 CHAR16            gModalSkipColumn;\r
 CHAR16            gPromptBlockWidth;\r
 CHAR16            gOptionBlockWidth;\r
@@ -143,6 +170,10 @@ FORM_DISPLAY_DRIVER_PRIVATE_DATA  mPrivateData = {
     FormDisplay,\r
     DriverClearDisplayPage,\r
     ConfirmDataChange\r
+  },\r
+  {\r
+    EFI_HII_POPUP_PROTOCOL_REVISION,\r
+    CreatePopup\r
   }\r
 };\r
 \r
@@ -184,8 +215,18 @@ InitializeDisplayStrings (
   VOID\r
   )\r
 {\r
+  gReconnectConfirmChanges = GetToken (STRING_TOKEN (RECONNECT_CONFIRM_CHANGES), gHiiHandle);\r
   mUnknownString        = GetToken (STRING_TOKEN (UNKNOWN_STRING), gHiiHandle);\r
   gSaveFailed           = GetToken (STRING_TOKEN (SAVE_FAILED), gHiiHandle);\r
+  gNoSubmitIfFailed     = GetToken (STRING_TOKEN (NO_SUBMIT_IF_CHECK_FAILED), gHiiHandle);\r
+  gReconnectFail        = GetToken (STRING_TOKEN (RECONNECT_FAILED), gHiiHandle);\r
+  gReconnectRequired    = GetToken (STRING_TOKEN (RECONNECT_REQUIRED), gHiiHandle);\r
+  gChangesOpt           = GetToken (STRING_TOKEN (RECONNECT_CHANGES_OPTIONS), gHiiHandle);\r
+  gSaveProcess          = GetToken (STRING_TOKEN (DISCARD_OR_JUMP), gHiiHandle);\r
+  gSaveNoSubmitProcess  = GetToken (STRING_TOKEN (DISCARD_OR_CHECK), gHiiHandle);\r
+  gDiscardChange        = GetToken (STRING_TOKEN (DISCARD_OR_JUMP_DISCARD), gHiiHandle);\r
+  gJumpToFormSet        = GetToken (STRING_TOKEN (DISCARD_OR_JUMP_JUMP), gHiiHandle);\r
+  gCheckError           = GetToken (STRING_TOKEN (DISCARD_OR_CHECK_CHECK), gHiiHandle);\r
   gPromptForData        = GetToken (STRING_TOKEN (PROMPT_FOR_DATA), gHiiHandle);\r
   gPromptForPassword    = GetToken (STRING_TOKEN (PROMPT_FOR_PASSWORD), gHiiHandle);\r
   gPromptForNewPassword = GetToken (STRING_TOKEN (PROMPT_FOR_NEW_PASSWORD), gHiiHandle);\r
@@ -200,7 +241,31 @@ InitializeDisplayStrings (
   gProtocolNotFound     = GetToken (STRING_TOKEN (PROTOCOL_NOT_FOUND), gHiiHandle);\r
   gFormNotFound         = GetToken (STRING_TOKEN (STATUS_BROWSER_FORM_NOT_FOUND), gHiiHandle);\r
   gNoSubmitIf           = GetToken (STRING_TOKEN (STATUS_BROWSER_NO_SUBMIT_IF), gHiiHandle);\r
-  gBrwoserError         = GetToken (STRING_TOKEN (STATUS_BROWSER_ERROR), gHiiHandle);\r
+  gBrowserError         = GetToken (STRING_TOKEN (STATUS_BROWSER_ERROR), gHiiHandle);\r
+  gConfirmDefaultMsg    = GetToken (STRING_TOKEN (CONFIRM_DEFAULT_MESSAGE), gHiiHandle);\r
+  gConfirmDiscardMsg    = GetToken (STRING_TOKEN (CONFIRM_DISCARD_MESSAGE), gHiiHandle);\r
+  gConfirmSubmitMsg     = GetToken (STRING_TOKEN (CONFIRM_SUBMIT_MESSAGE), gHiiHandle);\r
+  gConfirmResetMsg      = GetToken (STRING_TOKEN (CONFIRM_RESET_MESSAGE), gHiiHandle);\r
+  gConfirmExitMsg       = GetToken (STRING_TOKEN (CONFIRM_EXIT_MESSAGE), gHiiHandle);\r
+  gConfirmDefaultMsg2nd = GetToken (STRING_TOKEN (CONFIRM_DEFAULT_MESSAGE_2ND), gHiiHandle);\r
+  gConfirmSubmitMsg2nd  = GetToken (STRING_TOKEN (CONFIRM_SUBMIT_MESSAGE_2ND), gHiiHandle);\r
+  gConfirmResetMsg2nd   = GetToken (STRING_TOKEN (CONFIRM_RESET_MESSAGE_2ND), gHiiHandle);\r
+  gConfirmExitMsg2nd    = GetToken (STRING_TOKEN (CONFIRM_EXIT_MESSAGE_2ND), gHiiHandle);\r
+  gConfirmOpt           = GetToken (STRING_TOKEN (CONFIRM_OPTION), gHiiHandle);\r
+  gConfirmOptYes        = GetToken (STRING_TOKEN (CONFIRM_OPTION_YES), gHiiHandle);\r
+  gConfirmOptNo         = GetToken (STRING_TOKEN (CONFIRM_OPTION_NO), gHiiHandle);\r
+  gConfirmOptOk         = GetToken (STRING_TOKEN (CONFIRM_OPTION_OK), gHiiHandle);\r
+  gConfirmOptCancel     = GetToken (STRING_TOKEN (CONFIRM_OPTION_CANCEL), gHiiHandle);\r
+  gYesOption            = GetToken (STRING_TOKEN (YES_SELECTABLE_OPTION), gHiiHandle);\r
+  gNoOption             = GetToken (STRING_TOKEN (NO_SELECTABLE_OPTION), gHiiHandle);\r
+  gOkOption             = GetToken (STRING_TOKEN (OK_SELECTABLE_OPTION), gHiiHandle);\r
+  gCancelOption         = GetToken (STRING_TOKEN (CANCEL_SELECTABLE_OPTION), gHiiHandle);\r
+  gErrorPopup           = GetToken (STRING_TOKEN (ERROR_POPUP_STRING), gHiiHandle);\r
+  gWarningPopup         = GetToken (STRING_TOKEN (WARNING_POPUP_STRING), gHiiHandle);\r
+  gInfoPopup            = GetToken (STRING_TOKEN (INFO_POPUP_STRING), gHiiHandle);\r
+  gConfirmMsgConnect    = GetToken (STRING_TOKEN (CONFIRM_OPTION_CONNECT), gHiiHandle);\r
+  gConfirmMsgEnd        = GetToken (STRING_TOKEN (CONFIRM_OPTION_END), gHiiHandle);\r
+  gPasswordUnsupported  = GetToken (STRING_TOKEN (PASSWORD_NOT_SUPPORTED ), gHiiHandle);\r
 }\r
 \r
 /**\r
@@ -216,6 +281,16 @@ FreeDisplayStrings (
   FreePool (mUnknownString);\r
   FreePool (gEmptyString);\r
   FreePool (gSaveFailed);\r
+  FreePool (gNoSubmitIfFailed);\r
+  FreePool (gReconnectFail);\r
+  FreePool (gReconnectRequired);\r
+  FreePool (gChangesOpt);\r
+  FreePool (gReconnectConfirmChanges);\r
+  FreePool (gSaveProcess);\r
+  FreePool (gSaveNoSubmitProcess);\r
+  FreePool (gDiscardChange);\r
+  FreePool (gJumpToFormSet);\r
+  FreePool (gCheckError);\r
   FreePool (gPromptForData);\r
   FreePool (gPromptForPassword);\r
   FreePool (gPromptForNewPassword);\r
@@ -227,9 +302,33 @@ FreeDisplayStrings (
   FreePool (gOptionMismatch);\r
   FreePool (gFormSuppress);\r
   FreePool (gProtocolNotFound);\r
-  FreePool (gBrwoserError);\r
+  FreePool (gBrowserError);\r
   FreePool (gNoSubmitIf);\r
   FreePool (gFormNotFound);\r
+  FreePool (gConfirmDefaultMsg);\r
+  FreePool (gConfirmSubmitMsg);\r
+  FreePool (gConfirmDiscardMsg);\r
+  FreePool (gConfirmResetMsg);\r
+  FreePool (gConfirmExitMsg);\r
+  FreePool (gConfirmDefaultMsg2nd);\r
+  FreePool (gConfirmSubmitMsg2nd);\r
+  FreePool (gConfirmResetMsg2nd);\r
+  FreePool (gConfirmExitMsg2nd);\r
+  FreePool (gConfirmOpt);\r
+  FreePool (gConfirmOptYes);\r
+  FreePool (gConfirmOptNo);\r
+  FreePool (gConfirmOptOk);\r
+  FreePool (gConfirmOptCancel);\r
+  FreePool (gYesOption);\r
+  FreePool (gNoOption);\r
+  FreePool (gOkOption);\r
+  FreePool (gCancelOption);\r
+  FreePool (gErrorPopup);\r
+  FreePool (gWarningPopup);\r
+  FreePool (gInfoPopup);\r
+  FreePool (gConfirmMsgConnect);\r
+  FreePool (gConfirmMsgEnd);\r
+  FreePool (gPasswordUnsupported);\r
 }\r
 \r
 /**\r
@@ -313,10 +412,10 @@ GetWidth (
       //\r
       ((Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) && (Size == 0))\r
       ) {\r
-    \r
+\r
     //\r
     // Return the space width.\r
-    // \r
+    //\r
     if (AdjustWidth != NULL) {\r
       *AdjustWidth = 2;\r
     }\r
@@ -357,7 +456,7 @@ GetWidth (
   @param  Index                  Where in InputString to start the copy process\r
   @param  OutputString           Buffer to copy the string into\r
 \r
-  @return Returns the number of CHAR16 characters that were copied into the OutputString \r
+  @return Returns the number of CHAR16 characters that were copied into the OutputString\r
   buffer, include extra glyph info and '\0' info.\r
 \r
 **/\r
@@ -436,7 +535,7 @@ GetLineByWidth (
     if (ReturnFlag) {\r
       break;\r
     }\r
-  } \r
+  }\r
 \r
   //\r
   // Rewind the string from the maximum size until we see a space to break the line\r
@@ -466,7 +565,7 @@ GetLineByWidth (
   //\r
   // Need extra glyph info and '\0' info, so +2.\r
   //\r
-  *OutputString = AllocateZeroPool (((UINTN) (StrOffset + 2) * sizeof(CHAR16)));\r
+  *OutputString = AllocateZeroPool ((StrOffset + 2) * sizeof(CHAR16));\r
   if (*OutputString == NULL) {\r
     return 0;\r
   }\r
@@ -485,7 +584,7 @@ GetLineByWidth (
   if (InputString[*Index + StrOffset] == CHAR_SPACE) {\r
     //\r
     // Skip the space info at the begin of next line.\r
-    //  \r
+    //\r
     *Index = (UINT16) (*Index + StrOffset + 1);\r
   } else if (InputString[*Index + StrOffset] == CHAR_LINEFEED) {\r
     //\r
@@ -499,7 +598,7 @@ GetLineByWidth (
   } else if (InputString[*Index + StrOffset] == CHAR_CARRIAGE_RETURN) {\r
     //\r
     // Skip the /r or /r/n info.\r
-    //  \r
+    //\r
     if (InputString[*Index + StrOffset + 1] == CHAR_LINEFEED) {\r
       *Index = (UINT16) (*Index + StrOffset + 2);\r
     } else {\r
@@ -533,7 +632,6 @@ UiAddMenuOption (
   UI_MENU_OPTION   *MenuOption;\r
   UINTN            Index;\r
   UINTN            Count;\r
-  CHAR16           *String;\r
   UINT16           NumberOfLines;\r
   UINT16           GlyphWidth;\r
   UINT16           Width;\r
@@ -550,9 +648,6 @@ UiAddMenuOption (
   PromptId = GetPrompt (Statement->OpCode);\r
   ASSERT (PromptId != 0);\r
 \r
-  String = GetToken (PromptId, gFormData->HiiHandle);\r
-  ASSERT (String != NULL);\r
-\r
   if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP || Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {\r
     Count = 3;\r
   }\r
@@ -562,7 +657,7 @@ UiAddMenuOption (
     ASSERT (MenuOption);\r
 \r
     MenuOption->Signature   = UI_MENU_OPTION_SIGNATURE;\r
-    MenuOption->Description = String;\r
+    MenuOption->Description = GetToken (PromptId, gFormData->HiiHandle);\r
     MenuOption->Handle      = gFormData->HiiHandle;\r
     MenuOption->ThisTag     = Statement;\r
     MenuOption->NestInStatement = NestIn;\r
@@ -604,7 +699,7 @@ UiAddMenuOption (
     case EFI_IFR_TEXT_OP:\r
       if (FeaturePcdGet (PcdBrowserGrayOutTextStatement)) {\r
         //\r
-        // Initializing GrayOut option as TRUE for Text setup options \r
+        // Initializing GrayOut option as TRUE for Text setup options\r
         // so that those options will be Gray in colour and un selectable.\r
         //\r
         MenuOption->GrayOut = TRUE;\r
@@ -622,15 +717,15 @@ UiAddMenuOption (
       }\r
     }\r
 \r
-    if (Index == 0 && \r
-      (Statement->OpCode->OpCode != EFI_IFR_DATE_OP) && \r
+    if (Index == 0 &&\r
+      (Statement->OpCode->OpCode != EFI_IFR_DATE_OP) &&\r
       (Statement->OpCode->OpCode != EFI_IFR_TIME_OP)) {\r
       Width  = GetWidth (MenuOption, NULL);\r
-      for (; GetLineByWidth (String, Width, &GlyphWidth,&ArrayEntry, &OutputString) != 0x0000;) {\r
+      for (; GetLineByWidth (MenuOption->Description, 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
-        if (StrLen (&String[ArrayEntry]) != 0) {\r
+        if (StrLen (&MenuOption->Description[ArrayEntry]) != 0) {\r
           NumberOfLines++;\r
         }\r
         FreePool (OutputString);\r
@@ -640,7 +735,7 @@ UiAddMenuOption (
       // Add three MenuOptions for Date/Time\r
       // Data format :      [01/02/2004]      [11:22:33]\r
       // Line number :        0  0    1         0  0  1\r
-      //    \r
+      //\r
       NumberOfLines = 0;\r
     }\r
 \r
@@ -699,6 +794,13 @@ ConvertStatementToMenu (
       NestStatement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (NestLink);\r
       NestLink = GetNextNode (&Statement->NestStatementList, NestLink);\r
 \r
+      //\r
+      // Skip the opcode not recognized by Display core.\r
+      //\r
+      if (NestStatement->OpCode->OpCode == EFI_IFR_GUID_OP) {\r
+        continue;\r
+      }\r
+\r
       UiAddMenuOption (NestStatement, &MenuItemCount, TRUE);\r
     }\r
   }\r
@@ -800,7 +902,7 @@ UpdateSkipInfoForMenu (
   CHAR16  *OutputString;\r
   UINT16  GlyphWidth;\r
 \r
-  Width         = (UINT16) gOptionBlockWidth;\r
+  Width         = (UINT16) gOptionBlockWidth - 1;\r
   GlyphWidth    = 1;\r
   Row           = 1;\r
 \r
@@ -812,8 +914,8 @@ UpdateSkipInfoForMenu (
     FreePool (OutputString);\r
   }\r
 \r
-  if ((Row > MenuOption->Skip) && \r
-      (MenuOption->ThisTag->OpCode->OpCode != EFI_IFR_DATE_OP) && \r
+  if ((Row > MenuOption->Skip) &&\r
+      (MenuOption->ThisTag->OpCode->OpCode != EFI_IFR_DATE_OP) &&\r
       (MenuOption->ThisTag->OpCode->OpCode != EFI_IFR_TIME_OP)) {\r
     MenuOption->Skip = Row;\r
   }\r
@@ -852,6 +954,54 @@ UpdateOptionSkipLines (
   }\r
 }\r
 \r
+/**\r
+  Check whether this Menu Option could be print.\r
+\r
+  Check Prompt string, option string or text two string not NULL.\r
+\r
+  This is an internal function.\r
+\r
+  @param  MenuOption             The MenuOption to be checked.\r
+\r
+  @retval TRUE                   This Menu Option is printable.\r
+  @retval FALSE                  This Menu Option could not be printable.\r
+\r
+**/\r
+BOOLEAN\r
+PrintableMenu (\r
+  UI_MENU_OPTION   *MenuOption\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+  EFI_STRING    OptionString;\r
+\r
+  OptionString = NULL;\r
+\r
+  if (MenuOption->Description[0] != '\0') {\r
+    return TRUE;\r
+  }\r
+\r
+  Status = ProcessOptions (MenuOption, FALSE, &OptionString, FALSE);\r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\r
+  if (OptionString != NULL && OptionString[0] != '\0') {\r
+    FreePool (OptionString);\r
+    return TRUE;\r
+  }\r
+\r
+  if ((MenuOption->ThisTag->OpCode->OpCode  == EFI_IFR_TEXT_OP) && (((EFI_IFR_TEXT*)MenuOption->ThisTag->OpCode)->TextTwo != 0)) {\r
+    OptionString   = GetToken (((EFI_IFR_TEXT*)MenuOption->ThisTag->OpCode)->TextTwo, gFormData->HiiHandle);\r
+    ASSERT (OptionString != NULL);\r
+    if (OptionString[0] != '\0'){\r
+      FreePool (OptionString);\r
+      return TRUE;\r
+    }\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
 /**\r
   Check whether this Menu Option could be highlighted.\r
 \r
@@ -869,7 +1019,7 @@ IsSelectable (
   )\r
 {\r
   if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) ||\r
-      MenuOption->GrayOut || MenuOption->ReadOnly) {\r
+      MenuOption->GrayOut || MenuOption->ReadOnly || !PrintableMenu (MenuOption)) {\r
     return FALSE;\r
   } else {\r
     return TRUE;\r
@@ -884,19 +1034,24 @@ IsSelectable (
   @param  GoUp                   The navigation direction. TRUE: up, FALSE: down.\r
   @param  CurrentPosition        Current position.\r
   @param  GapToTop               Gap position to top or bottom.\r
+  @param  FindInForm             Whether find menu in current form or beyond.\r
 \r
   @return The row distance from current MenuOption to next selectable MenuOption.\r
 \r
   @retval -1       Reach the begin of the menu, still can't find the selectable menu.\r
-  @retval Value    Find the selectable menu, maybe the truly selectable, maybe the l\r
-                   last menu showing at current form.\r
+  @retval Value    Find the selectable menu, maybe the truly selectable, maybe the\r
+                   first menu showing beyond current form or last menu showing in\r
+                   current form.\r
+                   The value is the line number between the new selected menu and the\r
+                   current select menu, not include the new selected menu.\r
 \r
 **/\r
 INTN\r
 MoveToNextStatement (\r
   IN     BOOLEAN                   GoUp,\r
   IN OUT LIST_ENTRY                **CurrentPosition,\r
-  IN     UINTN                     GapToTop\r
+  IN     UINTN                     GapToTop,\r
+  IN     BOOLEAN                   FindInForm\r
   )\r
 {\r
   INTN             Distance;\r
@@ -906,6 +1061,11 @@ MoveToNextStatement (
 \r
   Distance      = 0;\r
   Pos           = *CurrentPosition;\r
+\r
+  if (Pos == &gMenuOption) {\r
+    return -1;\r
+  }\r
+\r
   PreMenuOption = MENU_OPTION_FROM_LINK (Pos);\r
 \r
   while (TRUE) {\r
@@ -917,28 +1077,27 @@ MoveToNextStatement (
     if (NextMenuOption->Row == 0) {\r
       UpdateOptionSkipLines (NextMenuOption);\r
     }\r
-    \r
-    if (GoUp && (PreMenuOption != NextMenuOption)) {\r
-      //\r
-      // In this case, still can't find the selectable menu,\r
-      // return the last one in the showing form.\r
-      //\r
-      if ((UINTN) Distance + NextMenuOption->Skip > GapToTop) {\r
+\r
+    //\r
+    // Check whether the menu is beyond current showing form,\r
+    // return the first one beyond the showing form.\r
+    //\r
+    if ((UINTN) Distance + NextMenuOption->Skip > GapToTop) {\r
+      if (FindInForm) {\r
         NextMenuOption = PreMenuOption;\r
-        break;\r
       }\r
-\r
-      //\r
-      // Current Position doesn't need to be caculated when go up.\r
-      // Caculate distanct at first when go up\r
-      //      \r
-      Distance += NextMenuOption->Skip;\r
+      break;\r
     }\r
 \r
+    //\r
+    // return the selectable menu in the showing form.\r
+    //\r
     if (IsSelectable (NextMenuOption)) {\r
       break;\r
     }\r
 \r
+    Distance += NextMenuOption->Skip;\r
+\r
     //\r
     // Arrive at begin of the menu list.\r
     //\r
@@ -947,21 +1106,8 @@ MoveToNextStatement (
       break;\r
     }\r
 \r
-    if (!GoUp) {\r
-      //\r
-      // In this case, still can't find the selectable menu,\r
-      // return the last one in the showing form.\r
-      //\r
-      if ((UINTN) Distance + NextMenuOption->Skip > GapToTop) {\r
-        NextMenuOption = PreMenuOption;\r
-        break;\r
-      }\r
-\r
-      Distance += NextMenuOption->Skip;\r
-    }\r
-\r
-    PreMenuOption = NextMenuOption;\r
     Pos = (GoUp ? Pos->BackLink : Pos->ForwardLink);\r
+    PreMenuOption = NextMenuOption;\r
   }\r
 \r
   *CurrentPosition = &NextMenuOption->Link;\r
@@ -974,10 +1120,10 @@ MoveToNextStatement (
 \r
   @param  MenuOption              Menu option point to date/time.\r
   @param  OptionString            Option string input for process.\r
-  @param  AddOptCol               Whether need to update MenuOption->OptCol. \r
+  @param  AddOptCol               Whether need to update MenuOption->OptCol.\r
 \r
 **/\r
-VOID \r
+VOID\r
 ProcessStringForDateTime (\r
   UI_MENU_OPTION                  *MenuOption,\r
   CHAR16                          *OptionString,\r
@@ -991,7 +1137,7 @@ ProcessStringForDateTime (
   EFI_IFR_TIME                           *Time;\r
 \r
   ASSERT (MenuOption != NULL && OptionString != NULL);\r
-  \r
+\r
   Statement = MenuOption->ThisTag;\r
   Date      = NULL;\r
   Time      = NULL;\r
@@ -1000,7 +1146,7 @@ ProcessStringForDateTime (
   } else if (Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {\r
     Time = (EFI_IFR_TIME *) Statement->OpCode;\r
   }\r
-  \r
+\r
   //\r
   // If leading spaces on OptionString - remove the spaces\r
   //\r
@@ -1012,13 +1158,13 @@ ProcessStringForDateTime (
       MenuOption->OptCol++;\r
     }\r
   }\r
-  \r
+\r
   for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) {\r
     OptionString[Count] = OptionString[Index];\r
     Count++;\r
   }\r
   OptionString[Count] = CHAR_NULL;\r
-  \r
+\r
   //\r
   // Enable to suppress field in the opcode base on the flag.\r
   //\r
@@ -1030,21 +1176,21 @@ ProcessStringForDateTime (
     //\r
     if ((Date->Flags & EFI_QF_DATE_MONTH_SUPPRESS) && (MenuOption->Sequence == 0)) {\r
       //\r
-      // At this point, only "<**:" in the optionstring. \r
+      // At this point, only "<**:" in the optionstring.\r
       // Clean the day's ** field, after clean, the format is "<  :"\r
       //\r
       SetUnicodeMem (&OptionString[1], 2, L' ');\r
     } else if ((Date->Flags & EFI_QF_DATE_DAY_SUPPRESS) && (MenuOption->Sequence == 1)) {\r
       //\r
-      // At this point, only "**:" in the optionstring. \r
+      // At this point, only "**:" in the optionstring.\r
       // Clean the month's "**" field, after clean, the format is "  :"\r
-      //                \r
+      //\r
       SetUnicodeMem (&OptionString[0], 2, L' ');\r
     } else if ((Date->Flags & EFI_QF_DATE_YEAR_SUPPRESS) && (MenuOption->Sequence == 2)) {\r
       //\r
-      // At this point, only "****>" in the optionstring. \r
+      // At this point, only "****>" in the optionstring.\r
       // Clean the year's "****" field, after clean, the format is "  >"\r
-      //                \r
+      //\r
       SetUnicodeMem (&OptionString[0], 4, L' ');\r
     }\r
   } else if (Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {\r
@@ -1055,21 +1201,21 @@ ProcessStringForDateTime (
     //\r
     if ((Time->Flags & QF_TIME_HOUR_SUPPRESS) && (MenuOption->Sequence == 0)) {\r
       //\r
-      // At this point, only "<**:" in the optionstring. \r
+      // At this point, only "<**:" in the optionstring.\r
       // Clean the hour's ** field, after clean, the format is "<  :"\r
       //\r
       SetUnicodeMem (&OptionString[1], 2, L' ');\r
     } else if ((Time->Flags & QF_TIME_MINUTE_SUPPRESS) && (MenuOption->Sequence == 1)) {\r
       //\r
-      // At this point, only "**:" in the optionstring. \r
+      // At this point, only "**:" in the optionstring.\r
       // Clean the minute's "**" field, after clean, the format is "  :"\r
-      //                \r
+      //\r
       SetUnicodeMem (&OptionString[0], 2, L' ');\r
     } else if ((Time->Flags & QF_TIME_SECOND_SUPPRESS) && (MenuOption->Sequence == 2)) {\r
       //\r
-      // At this point, only "**>" in the optionstring. \r
+      // At this point, only "**>" in the optionstring.\r
       // Clean the second's "**" field, after clean, the format is "  >"\r
-      //                \r
+      //\r
       SetUnicodeMem (&OptionString[0], 2, L' ');\r
     }\r
   }\r
@@ -1152,7 +1298,7 @@ AdjustDateAndTimePosition (
 \r
 /**\r
   Get step info from numeric opcode.\r
-  \r
+\r
   @param[in] OpCode     The input numeric op code.\r
 \r
   @return step info for this opcode.\r
@@ -1166,24 +1312,24 @@ GetFieldFromNum (
   UINT64                Step;\r
 \r
   NumericOp = (EFI_IFR_NUMERIC *) OpCode;\r
-  \r
+\r
   switch (NumericOp->Flags & EFI_IFR_NUMERIC_SIZE) {\r
   case EFI_IFR_NUMERIC_SIZE_1:\r
     Step    = NumericOp->data.u8.Step;\r
     break;\r
-  \r
+\r
   case EFI_IFR_NUMERIC_SIZE_2:\r
     Step    = NumericOp->data.u16.Step;\r
     break;\r
-  \r
+\r
   case EFI_IFR_NUMERIC_SIZE_4:\r
     Step    = NumericOp->data.u32.Step;\r
     break;\r
-  \r
+\r
   case EFI_IFR_NUMERIC_SIZE_8:\r
     Step    = NumericOp->data.u64.Step;\r
     break;\r
-  \r
+\r
   default:\r
     Step = 0;\r
     break;\r
@@ -1194,7 +1340,7 @@ GetFieldFromNum (
 \r
 /**\r
   Find the registered HotKey based on KeyData.\r
-  \r
+\r
   @param[in] KeyData     A pointer to a buffer that describes the keystroke\r
                          information for the hot key.\r
 \r
@@ -1211,14 +1357,14 @@ GetHotKeyFromRegisterList (
   Link = GetFirstNode (&gFormData->HotKeyListHead);\r
   while (!IsNull (&gFormData->HotKeyListHead, Link)) {\r
     HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);\r
-    \r
+\r
     if (HotKey->KeyData->ScanCode == KeyData->ScanCode) {\r
       return HotKey;\r
     }\r
 \r
     Link = GetNextNode (&gFormData->HotKeyListHead, Link);\r
   }\r
-  \r
+\r
   return NULL;\r
 }\r
 \r
@@ -1288,13 +1434,13 @@ UiWaitForEvent (
           Timeout\r
           );\r
   }\r
-  \r
+\r
   WaitList[0] = Event;\r
   EventNum    = 1;\r
   if (gFormData->FormRefreshEvent != NULL) {\r
     WaitList[EventNum] = gFormData->FormRefreshEvent;\r
     EventNum ++;\r
-  } \r
+  }\r
 \r
   if (Timeout != 0) {\r
     WaitList[EventNum] = TimerEvent;\r
@@ -1327,7 +1473,7 @@ UiWaitForEvent (
   if (Timeout != 0) {\r
     gBS->CloseEvent (TimerEvent);\r
   }\r
-  \r
+\r
   return EventType;\r
 }\r
 \r
@@ -1355,250 +1501,656 @@ GetQuestionIdInfo (
   return QuestionHeader->QuestionId;\r
 }\r
 \r
+\r
 /**\r
-  Find the first menu which will be show at the top.\r
+  Find the top of screen menu base on the current menu.\r
 \r
-  @param  FormData               The data info for this form.\r
-  @param  TopOfScreen            The link_entry pointer to top menu.\r
-  @param  HighlightMenu          The menu which will be highlight.\r
-  @param  SkipValue              The skip value for the top menu.\r
+  @param  CurPos                 Current input menu.\r
+  @param  Rows                   Totol screen rows.\r
+  @param  SkipValue              SkipValue for this new form.\r
+\r
+  @retval TopOfScreen            Top of screen menu for the new form.\r
 \r
 **/\r
-VOID\r
-FindTopMenu (\r
-  IN  FORM_DISPLAY_ENGINE_FORM  *FormData,\r
-  OUT LIST_ENTRY                **TopOfScreen,\r
-  OUT LIST_ENTRY                **HighlightMenu,\r
-  OUT INTN                      *SkipValue\r
+LIST_ENTRY *\r
+FindTopOfScreenMenu (\r
+  IN  LIST_ENTRY                      *CurPos,\r
+  IN  UINTN                           Rows,\r
+  OUT UINTN                           *SkipValue\r
   )\r
 {\r
-  LIST_ENTRY                      *Link;\r
-  LIST_ENTRY                      *NewPos;\r
-  UINTN                           TopRow;\r
-  UINTN                           BottomRow;\r
-  UINTN                           Index;\r
-  UI_MENU_OPTION                  *SavedMenuOption;\r
-  UINTN                           EndRow;\r
+  LIST_ENTRY        *Link;\r
+  LIST_ENTRY        *TopOfScreen;\r
+  UI_MENU_OPTION    *PreviousMenuOption;\r
 \r
-  TopRow    = gStatementDimensions.TopRow    + SCROLL_ARROW_HEIGHT;\r
-  BottomRow = gStatementDimensions.BottomRow - SCROLL_ARROW_HEIGHT;\r
+  Link = CurPos;\r
+  PreviousMenuOption = NULL;\r
 \r
-  //\r
-  // If not has input highlight statement, just return the first one in this form.\r
-  //\r
-  if (FormData->HighLightedStatement == NULL) {\r
-    *TopOfScreen   = gMenuOption.ForwardLink;\r
-    *HighlightMenu = gMenuOption.ForwardLink;\r
-    if (!IsListEmpty (&gMenuOption)) {\r
-      MoveToNextStatement (FALSE, HighlightMenu, BottomRow - TopRow);\r
+  while (Link->BackLink != &gMenuOption) {\r
+    Link = Link->BackLink;\r
+    PreviousMenuOption = MENU_OPTION_FROM_LINK (Link);\r
+    if (PreviousMenuOption->Row == 0) {\r
+      UpdateOptionSkipLines (PreviousMenuOption);\r
     }\r
-    *SkipValue     = 0;\r
-    return;\r
-  }\r
-\r
-  //\r
-  // Now base on the input highlight menu to find the top menu in this page.\r
-  // Will base on the highlight menu show at the bottom to find the top menu.\r
-  //\r
-  NewPos = gMenuOption.ForwardLink;\r
-  SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
-\r
-  while ((SavedMenuOption->ThisTag != FormData->HighLightedStatement) ||\r
-         (SavedMenuOption->Sequence != gSequence)) {\r
-    NewPos     = NewPos->ForwardLink;\r
-    if (NewPos == &gMenuOption) {\r
-      //\r
-      // Not Found it, break\r
-      //\r
+    if (Rows <= PreviousMenuOption->Skip) {\r
       break;\r
     }\r
-    SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
-  }\r
-  ASSERT (SavedMenuOption->ThisTag == FormData->HighLightedStatement);\r
-\r
-  *HighlightMenu = NewPos;\r
-\r
-  AdjustDateAndTimePosition(FALSE, &NewPos);\r
-  SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
-  UpdateOptionSkipLines (SavedMenuOption);\r
-\r
-  //\r
-  // If highlight opcode is date/time, keep the highlight row info not change.\r
-  //\r
-  if ((SavedMenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP || SavedMenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP) &&\r
-      (gHighligthMenuInfo.QuestionId != 0) && \r
-      (gHighligthMenuInfo.QuestionId == GetQuestionIdInfo(SavedMenuOption->ThisTag->OpCode))) {\r
-    //\r
-    // Still show the highlight menu before exit from display engine.\r
-    //\r
-    EndRow = gHighligthMenuInfo.DisplayRow + SavedMenuOption->Skip;\r
-  } else {\r
-    EndRow = BottomRow;\r
-  }\r
-\r
-  //\r
-  // Base on the selected menu will show at the bottome of next page, \r
-  // select the menu show at the top of the next page. \r
-  //\r
-  Link    = NewPos;\r
-  for (Index = TopRow + SavedMenuOption->Skip; Index <= EndRow; ) {\r
-    Link = Link->BackLink;\r
-    //\r
-    // Already find the first menu in this form, means highlight menu \r
-    // will show in first page of this form.\r
-    //\r
-    if (Link == &gMenuOption) {\r
-      *TopOfScreen   = gMenuOption.ForwardLink;\r
-      *SkipValue     = 0;\r
-      return;\r
-    }\r
-    SavedMenuOption = MENU_OPTION_FROM_LINK (Link);\r
-    UpdateOptionSkipLines (SavedMenuOption);\r
-    Index += SavedMenuOption->Skip;\r
+    Rows = Rows - PreviousMenuOption->Skip;\r
   }\r
 \r
-  //\r
-  // Found the menu which will show at the top of the page.\r
-  //\r
-  if (Link == NewPos) {\r
-    //\r
-    // The menu can show more than one pages, just show the menu at the top of the page.\r
-    //\r
-    *SkipValue    = 0;\r
-    *TopOfScreen  = Link;\r
-  } else {\r
-    //\r
-    // Check whether need to skip some line for menu shows at the top of the page.\r
-    //\r
-    *SkipValue = Index - EndRow;\r
-    if (*SkipValue > 0 && *SkipValue < (INTN) SavedMenuOption->Skip) {\r
-      *TopOfScreen     = Link;\r
+  if (Link->BackLink == &gMenuOption) {\r
+    TopOfScreen = gMenuOption.ForwardLink;\r
+    if (PreviousMenuOption != NULL && Rows < PreviousMenuOption->Skip) {\r
+      *SkipValue = PreviousMenuOption->Skip - Rows;\r
     } else {\r
-      *SkipValue       = 0;\r
-      *TopOfScreen     = Link->ForwardLink;\r
+      *SkipValue = 0;\r
     }\r
+  } else {\r
+    TopOfScreen = Link;\r
+    *SkipValue = PreviousMenuOption->Skip - Rows;\r
   }\r
+\r
+  return TopOfScreen;\r
 }\r
 \r
 /**\r
-  Update highlight menu info.\r
+  Get the index info for this opcode.\r
 \r
-  @param  MenuOption               The menu opton which is highlight.\r
+  @param  OpCode      The input opcode for the statement.\r
+\r
+  @retval  The index of this statement.\r
 \r
 **/\r
-VOID\r
-UpdateHighlightMenuInfo (\r
-  IN UI_MENU_OPTION            *MenuOption\r
+UINTN\r
+GetIndexInfoForOpcode (\r
+  IN EFI_IFR_OP_HEADER  *OpCode\r
   )\r
 {\r
-  FORM_DISPLAY_ENGINE_STATEMENT   *Statement;\r
+  LIST_ENTRY                      *NewPos;\r
+  UI_MENU_OPTION                  *MenuOption;\r
+  UINTN                           Index;\r
 \r
-  //\r
-  // This is the current selected statement\r
-  //\r
-  Statement = MenuOption->ThisTag;\r
+  NewPos = gMenuOption.ForwardLink;\r
+  Index  = 0;\r
 \r
-  //\r
-  // Get the highlight statement.\r
-  //\r
-  gUserInput->SelectedStatement = Statement;\r
-  gSequence = (UINT16) MenuOption->Sequence;\r
+  for (NewPos = gMenuOption.ForwardLink; NewPos != &gMenuOption; NewPos = NewPos->ForwardLink){\r
+    MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
 \r
-  //\r
-  // Record highlight row info for date/time opcode.\r
-  //\r
-  if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP || Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {\r
-    gHighligthMenuInfo.QuestionId = GetQuestionIdInfo(Statement->OpCode);\r
-    gHighligthMenuInfo.DisplayRow = (UINT16) MenuOption->Row;\r
-  } else {\r
-    gHighligthMenuInfo.QuestionId = 0;\r
-    gHighligthMenuInfo.DisplayRow = 0;\r
+    if (CompareMem (MenuOption->ThisTag->OpCode, OpCode, OpCode->Length) == 0) {\r
+      if (MenuOption->ThisTag->OpCode == OpCode) {\r
+        return Index;\r
+      }\r
+\r
+      Index ++;\r
+    }\r
   }\r
 \r
-  RefreshKeyHelp(gFormData, Statement, FALSE);\r
+  return Index;\r
 }\r
 \r
 /**\r
-  Update attribut for this menu.\r
+  Is this the saved highlight statement.\r
 \r
-  @param  MenuOption               The menu opton which this attribut used to.\r
-  @param  Highlight                Whether this menu will be highlight.\r
+  @param  HighLightedStatement      The input highlight statement.\r
+\r
+  @retval  TRUE   This is the highlight statement.\r
+  @retval  FALSE  This is not the highlight statement.\r
 \r
 **/\r
-VOID\r
-SetDisplayAttribute (\r
-  IN UI_MENU_OPTION                  *MenuOption,\r
-  IN BOOLEAN                         Highlight\r
+BOOLEAN\r
+IsSavedHighlightStatement (\r
+  IN FORM_DISPLAY_ENGINE_STATEMENT  *HighLightedStatement\r
   )\r
 {\r
-  FORM_DISPLAY_ENGINE_STATEMENT   *Statement;\r
-  \r
-  Statement = MenuOption->ThisTag;\r
-\r
-  if (Highlight) {\r
-    gST->ConOut->SetAttribute (gST->ConOut, GetHighlightTextColor ());\r
-    return;\r
-  }\r
-\r
-  if (MenuOption->GrayOut) {\r
-    gST->ConOut->SetAttribute (gST->ConOut, GetGrayedTextColor ());\r
-  } else {\r
-    if (Statement->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) {\r
-      gST->ConOut->SetAttribute (gST->ConOut, GetSubTitleTextColor ());\r
+  if ((gFormData->HiiHandle == gHighligthMenuInfo.HiiHandle) &&\r
+      (gFormData->FormId == gHighligthMenuInfo.FormId)) {\r
+    if (gHighligthMenuInfo.HLTQuestionId != 0) {\r
+      return (BOOLEAN) (gHighligthMenuInfo.HLTQuestionId == GetQuestionIdInfo (HighLightedStatement->OpCode));\r
     } else {\r
-      gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());\r
+      if (CompareMem (gHighligthMenuInfo.HLTOpCode, HighLightedStatement->OpCode, gHighligthMenuInfo.HLTOpCode->Length) == 0) {\r
+        if (gHighligthMenuInfo.HLTIndex == 0 || gHighligthMenuInfo.HLTIndex == GetIndexInfoForOpcode(HighLightedStatement->OpCode)) {\r
+          return TRUE;\r
+        } else {\r
+          return FALSE;\r
+        }\r
+      }\r
     }\r
   }\r
+\r
+  return FALSE;\r
 }\r
 \r
 /**\r
-  Print string for this menu option.\r
+  Is this the highlight menu.\r
 \r
-  @param  MenuOption               The menu opton which this attribut used to.\r
-  @param  Col                      The column that this string will be print at.\r
-  @param  Row                      The row that this string will be print at.\r
-  @param  String                   The string which need to print.\r
-  @param  Width                    The width need to print, if string is less than the\r
-                                   width, the block space will be used.\r
-  @param  Highlight                Whether this menu will be highlight.\r
+  @param  MenuOption      The input Menu option.\r
+\r
+  @retval  TRUE   This is the highlight menu option.\r
+  @retval  FALSE  This is not the highlight menu option.\r
 \r
 **/\r
-VOID\r
-DisplayMenuString (\r
-  IN UI_MENU_OPTION         *MenuOption,\r
-  IN UINTN                  Col,\r
-  IN UINTN                  Row,\r
-  IN CHAR16                 *String,\r
-  IN UINTN                  Width,\r
-  IN BOOLEAN                Highlight\r
+BOOLEAN\r
+IsHighLightMenuOption (\r
+  IN UI_MENU_OPTION     *MenuOption\r
   )\r
 {\r
-  UINTN            Length;\r
-\r
-  //\r
-  // Print string with normal color.\r
-  //\r
-  if (!Highlight) {\r
-    PrintStringAtWithWidth (Col, Row, String, Width);\r
-    return;\r
+  if (gHighligthMenuInfo.HLTQuestionId != 0) {\r
+    if (GetQuestionIdInfo(MenuOption->ThisTag->OpCode) == gHighligthMenuInfo.HLTQuestionId) {\r
+      return (BOOLEAN) (MenuOption->Sequence == gHighligthMenuInfo.HLTSequence);\r
+    }\r
+  } else {\r
+    if(CompareMem (gHighligthMenuInfo.HLTOpCode, MenuOption->ThisTag->OpCode, gHighligthMenuInfo.HLTOpCode->Length) == 0) {\r
+      if (gHighligthMenuInfo.HLTIndex == 0 || gHighligthMenuInfo.HLTIndex == GetIndexInfoForOpcode(MenuOption->ThisTag->OpCode)) {\r
+        return (BOOLEAN) (MenuOption->Sequence == gHighligthMenuInfo.HLTSequence);\r
+      } else {\r
+        return FALSE;\r
+      }\r
+    }\r
   }\r
-  \r
-  //\r
-  // Print the highlight menu string.\r
-  // First print the highlight string.\r
-  // \r
-  SetDisplayAttribute(MenuOption, TRUE);\r
-  Length = PrintStringAt (Col, Row, String);\r
 \r
-  //\r
-  // Second, clean the empty after the string.\r
-  //\r
-  SetDisplayAttribute(MenuOption, FALSE);\r
-  PrintStringAtWithWidth (Col + Length, Row, L"", Width - Length);\r
+  return FALSE;\r
 }\r
 \r
 /**\r
-  Check whether this menu can has option string.\r
+  Find the highlight menu.\r
+\r
+  If the input is NULL, base on the record highlight info in\r
+  gHighligthMenuInfo to find the last highlight menu.\r
+\r
+  @param  HighLightedStatement      The input highlight statement.\r
+\r
+  @retval  The highlight menu index.\r
+\r
+**/\r
+LIST_ENTRY *\r
+FindHighLightMenuOption (\r
+ IN FORM_DISPLAY_ENGINE_STATEMENT  *HighLightedStatement\r
+ )\r
+{\r
+  LIST_ENTRY                      *NewPos;\r
+  UI_MENU_OPTION                  *MenuOption;\r
+\r
+  NewPos = gMenuOption.ForwardLink;\r
+  MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+\r
+  if (HighLightedStatement != NULL) {\r
+    while (MenuOption->ThisTag != HighLightedStatement) {\r
+      NewPos     = NewPos->ForwardLink;\r
+      if (NewPos == &gMenuOption) {\r
+        //\r
+        // Not Found it, break\r
+        //\r
+        break;\r
+      }\r
+      MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+    }\r
+\r
+    //\r
+    // Must find the highlight statement.\r
+    //\r
+    ASSERT (NewPos != &gMenuOption);\r
+\r
+  } else {\r
+    while (!IsHighLightMenuOption (MenuOption)) {\r
+      NewPos     = NewPos->ForwardLink;\r
+      if (NewPos == &gMenuOption) {\r
+        //\r
+        // Not Found it, break\r
+        //\r
+        break;\r
+      }\r
+      MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+    }\r
+\r
+    //\r
+    // Highlight statement has disappear (suppressed/disableed)\r
+    //\r
+    if (NewPos == &gMenuOption) {\r
+      NewPos = NULL;\r
+    }\r
+  }\r
+\r
+  return NewPos;\r
+}\r
+\r
+/**\r
+  Is this the Top of screen menu.\r
+\r
+  @param  MenuOption      The input Menu option.\r
+\r
+  @retval  TRUE   This is the Top of screen menu option.\r
+  @retval  FALSE  This is not the Top of screen menu option.\r
+\r
+**/\r
+BOOLEAN\r
+IsTopOfScreeMenuOption (\r
+  IN UI_MENU_OPTION     *MenuOption\r
+  )\r
+{\r
+  if (gHighligthMenuInfo.TOSQuestionId != 0) {\r
+    return (BOOLEAN) (GetQuestionIdInfo(MenuOption->ThisTag->OpCode) == gHighligthMenuInfo.TOSQuestionId);\r
+  }\r
+\r
+  if(CompareMem (gHighligthMenuInfo.TOSOpCode, MenuOption->ThisTag->OpCode, gHighligthMenuInfo.TOSOpCode->Length) == 0) {\r
+    if (gHighligthMenuInfo.TOSIndex == 0 || gHighligthMenuInfo.TOSIndex == GetIndexInfoForOpcode(MenuOption->ThisTag->OpCode)) {\r
+      return TRUE;\r
+    } else {\r
+      return FALSE;\r
+    }\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Calculate the distance between two menus and include the skip value of StartMenu.\r
+\r
+  @param  StartMenu             The link_entry pointer to start menu.\r
+  @param  EndMenu               The link_entry pointer to end menu.\r
+\r
+**/\r
+UINTN\r
+GetDistanceBetweenMenus(\r
+  IN LIST_ENTRY  *StartMenu,\r
+  IN LIST_ENTRY  *EndMenu\r
+)\r
+{\r
+  LIST_ENTRY                 *Link;\r
+  UI_MENU_OPTION             *MenuOption;\r
+  UINTN                      Distance;\r
+\r
+  Distance = 0;\r
+\r
+  Link = StartMenu;\r
+  while (Link != EndMenu) {\r
+    MenuOption = MENU_OPTION_FROM_LINK (Link);\r
+    if (MenuOption->Row == 0) {\r
+      UpdateOptionSkipLines (MenuOption);\r
+    }\r
+    Distance += MenuOption->Skip;\r
+    Link = Link->BackLink;\r
+  }\r
+  return Distance;\r
+}\r
+\r
+/**\r
+  Find the top of screen menu base on the previous record menu info.\r
+\r
+  @param  HighLightMenu      The link_entry pointer to highlight menu.\r
+\r
+  @retval  Return the the link_entry pointer top of screen menu.\r
+\r
+**/\r
+LIST_ENTRY *\r
+FindTopOfScreenMenuOption (\r
+  IN LIST_ENTRY                   *HighLightMenu\r
+  )\r
+{\r
+  LIST_ENTRY                      *NewPos;\r
+  UI_MENU_OPTION                  *MenuOption;\r
+  UINTN                           TopRow;\r
+  UINTN                           BottomRow;\r
+\r
+  TopRow    = gStatementDimensions.TopRow    + SCROLL_ARROW_HEIGHT;\r
+  BottomRow = gStatementDimensions.BottomRow - SCROLL_ARROW_HEIGHT;\r
+\r
+  NewPos = gMenuOption.ForwardLink;\r
+  MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+\r
+  while (!IsTopOfScreeMenuOption(MenuOption)) {\r
+    NewPos     = NewPos->ForwardLink;\r
+    if (NewPos == &gMenuOption) {\r
+      //\r
+      // Not Found it, break\r
+      //\r
+      break;\r
+    }\r
+    MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+  }\r
+\r
+  //\r
+  // Last time top of screen menu has disappeared.\r
+  //\r
+  if (NewPos == &gMenuOption) {\r
+    return NULL;\r
+  }\r
+  //\r
+  // Check whether highlight menu and top of screen menu can be shown within one page,\r
+  // if can't, return NULL to re-calcaulate the top of scrren menu. Because some new menus\r
+  // may be dynamically inserted between highlightmenu and previous top of screen menu,\r
+  // So previous record top of screen menu is not appropriate for current display.\r
+  //\r
+  if (GetDistanceBetweenMenus (HighLightMenu, NewPos) + 1 > BottomRow - TopRow) {\r
+    return NULL;\r
+  }\r
+\r
+  return NewPos;\r
+}\r
+\r
+/**\r
+  Find the first menu which will be show at the top.\r
+\r
+  @param  FormData               The data info for this form.\r
+  @param  TopOfScreen            The link_entry pointer to top menu.\r
+  @param  HighlightMenu          The menu which will be highlight.\r
+  @param  SkipValue              The skip value for the top menu.\r
+\r
+**/\r
+VOID\r
+FindTopMenu (\r
+  IN  FORM_DISPLAY_ENGINE_FORM  *FormData,\r
+  OUT LIST_ENTRY                **TopOfScreen,\r
+  OUT LIST_ENTRY                **HighlightMenu,\r
+  OUT UINTN                     *SkipValue\r
+  )\r
+{\r
+  UINTN                           TopRow;\r
+  UINTN                           BottomRow;\r
+  UI_MENU_OPTION                  *MenuOption;\r
+  UINTN                           TmpValue;\r
+\r
+  TopRow    = gStatementDimensions.TopRow    + SCROLL_ARROW_HEIGHT;\r
+  BottomRow = gStatementDimensions.BottomRow - SCROLL_ARROW_HEIGHT;\r
+  //\r
+  // When option mismatch happens,there exist two cases,one is reenter the form, just like the if case below,\r
+  // and the other is exit current form and enter last form, it can be covered by the else case.\r
+  //\r
+  if (gMisMatch && gFormData->HiiHandle == gHighligthMenuInfo.HiiHandle && gFormData->FormId == gHighligthMenuInfo.FormId) {\r
+    //\r
+    // Reenter caused by option mismatch or auto exit caused by refresh form(refresh interval/guid),\r
+    // base on the record highlight info to find the highlight menu.\r
+    //\r
+\r
+    *HighlightMenu = FindHighLightMenuOption(NULL);\r
+    if (*HighlightMenu != NULL) {\r
+      //\r
+      // Update skip info for this highlight menu.\r
+      //\r
+      MenuOption = MENU_OPTION_FROM_LINK (*HighlightMenu);\r
+      UpdateOptionSkipLines (MenuOption);\r
+\r
+      //\r
+      // Found the last time highlight menu.\r
+      //\r
+      *TopOfScreen = FindTopOfScreenMenuOption(*HighlightMenu);\r
+      if (*TopOfScreen != NULL) {\r
+        //\r
+        // Found the last time selectable top of screen menu.\r
+        //\r
+        AdjustDateAndTimePosition(TRUE, TopOfScreen);\r
+        MenuOption = MENU_OPTION_FROM_LINK (*TopOfScreen);\r
+        UpdateOptionSkipLines (MenuOption);\r
+\r
+        *SkipValue = gHighligthMenuInfo.SkipValue;\r
+      } else {\r
+        //\r
+        // Not found last time top of screen menu, so base on current highlight menu\r
+        // to find the new top of screen menu.\r
+        // Make the current highlight menu at the bottom of the form to calculate the\r
+        // top of screen menu.\r
+        //\r
+        if (MenuOption->Skip >= BottomRow - TopRow) {\r
+          *TopOfScreen = *HighlightMenu;\r
+          TmpValue     = 0;\r
+        } else {\r
+          *TopOfScreen = FindTopOfScreenMenu(*HighlightMenu, BottomRow - TopRow - MenuOption->Skip, &TmpValue);\r
+        }\r
+\r
+        *SkipValue   = TmpValue;\r
+      }\r
+    } else {\r
+      //\r
+      // Last time highlight menu has disappear, find the first highlightable menu as the default one.\r
+      //\r
+      *HighlightMenu = gMenuOption.ForwardLink;\r
+      if (!IsListEmpty (&gMenuOption)) {\r
+        MoveToNextStatement (FALSE, HighlightMenu, BottomRow - TopRow, TRUE);\r
+      }\r
+      *TopOfScreen   = gMenuOption.ForwardLink;\r
+      *SkipValue = 0;\r
+    }\r
+\r
+  } else if (FormData->HighLightedStatement != NULL) {\r
+    if (IsSavedHighlightStatement (FormData->HighLightedStatement)) {\r
+      //\r
+      // Input highlight menu is same as last time highlight menu.\r
+      // Base on last time highlight menu to set the top of screen menu and highlight menu.\r
+      //\r
+      *HighlightMenu = FindHighLightMenuOption(NULL);\r
+      ASSERT (*HighlightMenu != NULL);\r
+\r
+      //\r
+      // Update skip info for this highlight menu.\r
+      //\r
+      MenuOption = MENU_OPTION_FROM_LINK (*HighlightMenu);\r
+      UpdateOptionSkipLines (MenuOption);\r
+\r
+      *TopOfScreen = FindTopOfScreenMenuOption(*HighlightMenu);\r
+      if (*TopOfScreen == NULL) {\r
+        //\r
+        // Not found last time top of screen menu, so base on current highlight menu\r
+        // to find the new top of screen menu.\r
+        // Make the current highlight menu at the bottom of the form to calculate the\r
+        // top of screen menu.\r
+        //\r
+        if (MenuOption->Skip >= BottomRow - TopRow) {\r
+          *TopOfScreen = *HighlightMenu;\r
+          TmpValue     = 0;\r
+        } else {\r
+          *TopOfScreen = FindTopOfScreenMenu(*HighlightMenu, BottomRow - TopRow - MenuOption->Skip, &TmpValue);\r
+        }\r
+\r
+        *SkipValue   = TmpValue;\r
+      } else {\r
+        AdjustDateAndTimePosition(TRUE, TopOfScreen);\r
+        MenuOption = MENU_OPTION_FROM_LINK (*TopOfScreen);\r
+        UpdateOptionSkipLines (MenuOption);\r
+\r
+        *SkipValue = gHighligthMenuInfo.SkipValue;\r
+      }\r
+      AdjustDateAndTimePosition(TRUE, TopOfScreen);\r
+    } else {\r
+      //\r
+      // Input highlight menu is not save as last time highlight menu.\r
+      //\r
+      *HighlightMenu = FindHighLightMenuOption(FormData->HighLightedStatement);\r
+      MenuOption = MENU_OPTION_FROM_LINK (*HighlightMenu);\r
+      UpdateOptionSkipLines (MenuOption);\r
+\r
+      //\r
+      // Make the current highlight menu at the bottom of the form to calculate the\r
+      // top of screen menu.\r
+      //\r
+      if (MenuOption->Skip >= BottomRow - TopRow) {\r
+        *TopOfScreen = *HighlightMenu;\r
+        TmpValue     = 0;\r
+      } else {\r
+        *TopOfScreen = FindTopOfScreenMenu(*HighlightMenu, BottomRow - TopRow - MenuOption->Skip, &TmpValue);\r
+      }\r
+\r
+      *SkipValue   = TmpValue;\r
+    }\r
+    AdjustDateAndTimePosition(TRUE, TopOfScreen);\r
+  } else {\r
+    //\r
+    // If not has input highlight statement, just return the first one in this form.\r
+    //\r
+    *TopOfScreen   = gMenuOption.ForwardLink;\r
+    *HighlightMenu = gMenuOption.ForwardLink;\r
+    if (!IsListEmpty (&gMenuOption)) {\r
+      MoveToNextStatement (FALSE, HighlightMenu, BottomRow - TopRow, TRUE);\r
+    }\r
+    *SkipValue     = 0;\r
+  }\r
+\r
+  gMisMatch = FALSE;\r
+\r
+  //\r
+  // First enter to show the menu, update highlight info.\r
+  //\r
+  UpdateHighlightMenuInfo (*HighlightMenu, *TopOfScreen, *SkipValue);\r
+}\r
+\r
+/**\r
+  Record the highlight menu and top of screen menu info.\r
+\r
+  @param  Highlight               The menu opton which is highlight.\r
+  @param  TopOfScreen             The menu opton which is at the top of the form.\r
+  @param  SkipValue               The skip line info for the top of screen menu.\r
+\r
+**/\r
+VOID\r
+UpdateHighlightMenuInfo (\r
+  IN  LIST_ENTRY                      *Highlight,\r
+  IN  LIST_ENTRY                      *TopOfScreen,\r
+  IN  UINTN                           SkipValue\r
+  )\r
+{\r
+  UI_MENU_OPTION                  *MenuOption;\r
+  FORM_DISPLAY_ENGINE_STATEMENT   *Statement;\r
+\r
+  gHighligthMenuInfo.HiiHandle  = gFormData->HiiHandle;\r
+  gHighligthMenuInfo.FormId     = gFormData->FormId;\r
+  gHighligthMenuInfo.SkipValue  = (UINT16)SkipValue;\r
+\r
+  if (!IsListEmpty (&gMenuOption)) {\r
+    MenuOption = MENU_OPTION_FROM_LINK (Highlight);\r
+    Statement  = MenuOption->ThisTag;\r
+\r
+    gUserInput->SelectedStatement = Statement;\r
+\r
+    gHighligthMenuInfo.HLTSequence   = MenuOption->Sequence;\r
+    gHighligthMenuInfo.HLTQuestionId = GetQuestionIdInfo(Statement->OpCode);\r
+    if (gHighligthMenuInfo.HLTQuestionId == 0) {\r
+      //\r
+      // if question id == 0, save the opcode buffer..\r
+      //\r
+      if (gHighligthMenuInfo.HLTOpCode != NULL) {\r
+        FreePool (gHighligthMenuInfo.HLTOpCode);\r
+      }\r
+      gHighligthMenuInfo.HLTOpCode = AllocateCopyPool (Statement->OpCode->Length, Statement->OpCode);\r
+      ASSERT (gHighligthMenuInfo.HLTOpCode != NULL);\r
+\r
+      gHighligthMenuInfo.HLTIndex = GetIndexInfoForOpcode(Statement->OpCode);\r
+    }\r
+\r
+    MenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
+    Statement  = MenuOption->ThisTag;\r
+\r
+    gHighligthMenuInfo.TOSQuestionId = GetQuestionIdInfo(Statement->OpCode);\r
+    if (gHighligthMenuInfo.TOSQuestionId == 0) {\r
+      //\r
+      // if question id == 0, save the opcode buffer..\r
+      //\r
+      if (gHighligthMenuInfo.TOSOpCode != NULL) {\r
+        FreePool (gHighligthMenuInfo.TOSOpCode);\r
+      }\r
+      gHighligthMenuInfo.TOSOpCode = AllocateCopyPool (Statement->OpCode->Length, Statement->OpCode);\r
+      ASSERT (gHighligthMenuInfo.TOSOpCode != NULL);\r
+\r
+      gHighligthMenuInfo.TOSIndex = GetIndexInfoForOpcode(Statement->OpCode);\r
+    }\r
+  } else {\r
+    gUserInput->SelectedStatement    = NULL;\r
+\r
+    gHighligthMenuInfo.HLTSequence   = 0;\r
+    gHighligthMenuInfo.HLTQuestionId = 0;\r
+    if (gHighligthMenuInfo.HLTOpCode != NULL) {\r
+      FreePool (gHighligthMenuInfo.HLTOpCode);\r
+    }\r
+    gHighligthMenuInfo.HLTOpCode     = NULL;\r
+    gHighligthMenuInfo.HLTIndex      = 0;\r
+\r
+    gHighligthMenuInfo.TOSQuestionId = 0;\r
+    if (gHighligthMenuInfo.TOSOpCode != NULL) {\r
+      FreePool (gHighligthMenuInfo.TOSOpCode);\r
+    }\r
+    gHighligthMenuInfo.TOSOpCode     = NULL;\r
+    gHighligthMenuInfo.TOSIndex      = 0;\r
+  }\r
+}\r
+\r
+/**\r
+  Update attribut for this menu.\r
+\r
+  @param  MenuOption               The menu opton which this attribut used to.\r
+  @param  Highlight                Whether this menu will be highlight.\r
+\r
+**/\r
+VOID\r
+SetDisplayAttribute (\r
+  IN UI_MENU_OPTION                  *MenuOption,\r
+  IN BOOLEAN                         Highlight\r
+  )\r
+{\r
+  FORM_DISPLAY_ENGINE_STATEMENT   *Statement;\r
+\r
+  Statement = MenuOption->ThisTag;\r
+\r
+  if (Highlight) {\r
+    gST->ConOut->SetAttribute (gST->ConOut, GetHighlightTextColor ());\r
+    return;\r
+  }\r
+\r
+  if (MenuOption->GrayOut) {\r
+    gST->ConOut->SetAttribute (gST->ConOut, GetGrayedTextColor ());\r
+  } else {\r
+    if (Statement->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) {\r
+      gST->ConOut->SetAttribute (gST->ConOut, GetSubTitleTextColor ());\r
+    } else {\r
+      gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  Print string for this menu option.\r
+\r
+  @param  MenuOption               The menu opton which this attribut used to.\r
+  @param  Col                      The column that this string will be print at.\r
+  @param  Row                      The row that this string will be print at.\r
+  @param  String                   The string which need to print.\r
+  @param  Width                    The width need to print, if string is less than the\r
+                                   width, the block space will be used.\r
+  @param  Highlight                Whether this menu will be highlight.\r
+\r
+**/\r
+VOID\r
+DisplayMenuString (\r
+  IN UI_MENU_OPTION         *MenuOption,\r
+  IN UINTN                  Col,\r
+  IN UINTN                  Row,\r
+  IN CHAR16                 *String,\r
+  IN UINTN                  Width,\r
+  IN BOOLEAN                Highlight\r
+  )\r
+{\r
+  UINTN            Length;\r
+\r
+  //\r
+  // Print string with normal color.\r
+  //\r
+  if (!Highlight) {\r
+    PrintStringAtWithWidth (Col, Row, String, Width);\r
+    return;\r
+  }\r
+\r
+  //\r
+  // Print the highlight menu string.\r
+  // First print the highlight string.\r
+  //\r
+  SetDisplayAttribute(MenuOption, TRUE);\r
+  Length = PrintStringAt (Col, Row, String);\r
+\r
+  //\r
+  // Second, clean the empty after the string.\r
+  //\r
+  SetDisplayAttribute(MenuOption, FALSE);\r
+  PrintStringAtWithWidth (Col + Length, Row, L"", Width - Length);\r
+}\r
+\r
+/**\r
+  Check whether this menu can has option string.\r
 \r
   @param  MenuOption               The menu opton which this attribut used to.\r
 \r
@@ -1606,7 +2158,7 @@ DisplayMenuString (
   @retval FALSE                    This menu option can't have option string.\r
 \r
 **/\r
-BOOLEAN \r
+BOOLEAN\r
 HasOptionString (\r
   IN UI_MENU_OPTION                  *MenuOption\r
   )\r
@@ -1648,6 +2200,149 @@ HasOptionString (
   return TRUE;\r
 }\r
 \r
+/**\r
+  Double confirm with user about the action.\r
+\r
+  @param  Action               The user input action.\r
+\r
+  @retval TRUE                 User confirm with the input or not need user confirm.\r
+  @retval FALSE                User want ignore this input.\r
+\r
+**/\r
+BOOLEAN\r
+FxConfirmPopup (\r
+  IN UINT32   Action\r
+  )\r
+{\r
+  EFI_INPUT_KEY                   Key;\r
+  CHAR16                          *CfmStr;\r
+  UINTN                           CfmStrLen;\r
+  UINT32                          CheckFlags;\r
+  BOOLEAN                         RetVal;\r
+  UINTN                           CatLen;\r
+  UINTN                           MaxLen;\r
+\r
+  CfmStrLen = 0;\r
+  CatLen    = StrLen (gConfirmMsgConnect);\r
+\r
+  //\r
+  // Below action need extra popup dialog to confirm.\r
+  //\r
+  CheckFlags = BROWSER_ACTION_DISCARD |\r
+               BROWSER_ACTION_DEFAULT |\r
+               BROWSER_ACTION_SUBMIT |\r
+               BROWSER_ACTION_RESET |\r
+               BROWSER_ACTION_EXIT;\r
+\r
+  //\r
+  // Not need to confirm with user, just return TRUE.\r
+  //\r
+  if ((Action & CheckFlags) == 0) {\r
+    return TRUE;\r
+  }\r
+\r
+  if ((Action & BROWSER_ACTION_DISCARD) == BROWSER_ACTION_DISCARD) {\r
+    CfmStrLen += StrLen (gConfirmDiscardMsg);\r
+  }\r
+\r
+  if ((Action & BROWSER_ACTION_DEFAULT) == BROWSER_ACTION_DEFAULT) {\r
+    if (CfmStrLen != 0) {\r
+      CfmStrLen += CatLen;\r
+    }\r
+\r
+    CfmStrLen += StrLen (gConfirmDefaultMsg);\r
+  }\r
+\r
+  if ((Action & BROWSER_ACTION_SUBMIT)  == BROWSER_ACTION_SUBMIT) {\r
+    if (CfmStrLen != 0) {\r
+      CfmStrLen += CatLen;\r
+    }\r
+\r
+    CfmStrLen += StrLen (gConfirmSubmitMsg);\r
+  }\r
+\r
+  if ((Action & BROWSER_ACTION_RESET)  == BROWSER_ACTION_RESET) {\r
+    if (CfmStrLen != 0) {\r
+      CfmStrLen += CatLen;\r
+    }\r
+\r
+    CfmStrLen += StrLen (gConfirmResetMsg);\r
+  }\r
+\r
+  if ((Action & BROWSER_ACTION_EXIT)  == BROWSER_ACTION_EXIT) {\r
+    if (CfmStrLen != 0) {\r
+      CfmStrLen += CatLen;\r
+    }\r
+\r
+    CfmStrLen += StrLen (gConfirmExitMsg);\r
+  }\r
+\r
+  //\r
+  // Allocate buffer to save the string.\r
+  // String + "?" + "\0"\r
+  //\r
+  MaxLen = CfmStrLen + 1 + 1;\r
+  CfmStr = AllocateZeroPool (MaxLen * sizeof (CHAR16));\r
+  ASSERT (CfmStr != NULL);\r
+\r
+  if ((Action & BROWSER_ACTION_DISCARD) == BROWSER_ACTION_DISCARD) {\r
+    StrCpyS (CfmStr, MaxLen, gConfirmDiscardMsg);\r
+  }\r
+\r
+  if ((Action & BROWSER_ACTION_DEFAULT) == BROWSER_ACTION_DEFAULT) {\r
+    if (CfmStr[0] != 0) {\r
+      StrCatS (CfmStr, MaxLen, gConfirmMsgConnect);\r
+      StrCatS (CfmStr, MaxLen, gConfirmDefaultMsg2nd);\r
+    } else {\r
+      StrCpyS (CfmStr, MaxLen, gConfirmDefaultMsg);\r
+    }\r
+  }\r
+\r
+  if ((Action & BROWSER_ACTION_SUBMIT)  == BROWSER_ACTION_SUBMIT) {\r
+    if (CfmStr[0] != 0) {\r
+      StrCatS (CfmStr, MaxLen, gConfirmMsgConnect);\r
+      StrCatS (CfmStr, MaxLen, gConfirmSubmitMsg2nd);\r
+    } else {\r
+      StrCpyS (CfmStr, MaxLen, gConfirmSubmitMsg);\r
+    }\r
+  }\r
+\r
+  if ((Action & BROWSER_ACTION_RESET)  == BROWSER_ACTION_RESET) {\r
+    if (CfmStr[0] != 0) {\r
+      StrCatS (CfmStr, MaxLen, gConfirmMsgConnect);\r
+      StrCatS (CfmStr, MaxLen, gConfirmResetMsg2nd);\r
+    } else {\r
+      StrCpyS (CfmStr, MaxLen, gConfirmResetMsg);\r
+    }\r
+  }\r
+\r
+  if ((Action & BROWSER_ACTION_EXIT)  == BROWSER_ACTION_EXIT) {\r
+    if (CfmStr[0] != 0) {\r
+      StrCatS (CfmStr, MaxLen, gConfirmMsgConnect);\r
+      StrCatS (CfmStr, MaxLen, gConfirmExitMsg2nd);\r
+    } else {\r
+      StrCpyS (CfmStr, MaxLen, gConfirmExitMsg);\r
+    }\r
+  }\r
+\r
+  StrCatS (CfmStr, MaxLen, gConfirmMsgEnd);\r
+\r
+  do {\r
+    CreateDialog (&Key, gEmptyString, CfmStr, gConfirmOpt, gEmptyString, NULL);\r
+  } while (((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (gConfirmOptYes[0] | UPPER_LOWER_CASE_OFFSET)) &&\r
+           ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (gConfirmOptNo[0] | UPPER_LOWER_CASE_OFFSET)) &&\r
+           (Key.ScanCode != SCAN_ESC));\r
+\r
+  if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (gConfirmOptYes[0] | UPPER_LOWER_CASE_OFFSET)) {\r
+    RetVal = TRUE;\r
+  } else {\r
+    RetVal = FALSE;\r
+  }\r
+\r
+  FreePool (CfmStr);\r
+\r
+  return RetVal;\r
+}\r
 \r
 /**\r
   Print string for this menu option.\r
@@ -1655,9 +2350,10 @@ HasOptionString (
   @param  MenuOption               The menu opton which this attribut used to.\r
   @param  SkipWidth                The skip width between the left to the start of the prompt.\r
   @param  BeginCol                 The begin column for one menu.\r
-  @param  SkipLine                 The skip line for this menu. \r
+  @param  SkipLine                 The skip line for this menu.\r
   @param  BottomRow                The bottom row for this form.\r
   @param  Highlight                Whether this menu will be highlight.\r
+  @param  UpdateCol                Whether need to update the column info for Date/Time.\r
 \r
   @retval EFI_SUCESSS              Process the user selection success.\r
 \r
@@ -1669,7 +2365,8 @@ DisplayOneMenu (
   IN UINTN                           BeginCol,\r
   IN UINTN                           SkipLine,\r
   IN UINTN                           BottomRow,\r
-  IN BOOLEAN                         Highlight\r
+  IN BOOLEAN                         Highlight,\r
+  IN BOOLEAN                         UpdateCol\r
   )\r
 {\r
   FORM_DISPLAY_ENGINE_STATEMENT   *Statement;\r
@@ -1685,6 +2382,7 @@ DisplayOneMenu (
   UINTN                           Temp3;\r
   EFI_STATUS                      Status;\r
   UINTN                           Row;\r
+  BOOLEAN                         IsProcessingFirstRow;\r
   UINTN                           Col;\r
   UINTN                           PromptLineNum;\r
   UINTN                           OptionLineNum;\r
@@ -1699,6 +2397,7 @@ DisplayOneMenu (
   PromptLineNum = 0;\r
   OptionLineNum = 0;\r
   MaxRow        = 0;\r
+  IsProcessingFirstRow = TRUE;\r
 \r
   //\r
   // Set default color.\r
@@ -1718,14 +2417,14 @@ DisplayOneMenu (
       //\r
       // Adjust option string for date/time opcode.\r
       //\r
-      ProcessStringForDateTime(MenuOption, OptionString, TRUE);\r
+      ProcessStringForDateTime(MenuOption, OptionString, UpdateCol);\r
     }\r
-  \r
+\r
     Width       = (UINT16) gOptionBlockWidth - 1;\r
     Row         = MenuOption->Row;\r
     GlyphWidth  = 1;\r
     OptionLineNum = 0;\r
-  \r
+\r
     for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
       if (((Temp2 == 0)) && (Row <= BottomRow)) {\r
         if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP || Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {\r
@@ -1743,15 +2442,16 @@ DisplayOneMenu (
           } else {\r
             //\r
             // For date/ time, print the first and second past (year for date and second for time)\r
-            //                \r
-            DisplayMenuString (MenuOption, MenuOption->OptCol, Row, OutputString, StrLen (OutputString), Highlight);\r
+            // The OutputString has a NARROW_CHAR or WIDE_CHAR at the begin of the string,\r
+            // so need to - 1 to remove it, otherwise, it will clean 1 extr char follow it.\r
+            DisplayMenuString (MenuOption, MenuOption->OptCol, Row, OutputString, StrLen (OutputString) - 1, Highlight);\r
           }\r
         } else {\r
           DisplayMenuString (MenuOption, MenuOption->OptCol, Row, OutputString, Width + 1, Highlight);\r
         }\r
         OptionLineNum++;\r
       }\r
-      \r
+\r
       //\r
       // If there is more string to process print on the next row and increment the Skip value\r
       //\r
@@ -1770,13 +2470,13 @@ DisplayOneMenu (
           }\r
         }\r
       }\r
-  \r
+\r
       FreePool (OutputString);\r
       if (Temp2 != 0) {\r
         Temp2--;\r
       }\r
     }\r
-  \r
+\r
     Highlight = FALSE;\r
 \r
     FreePool (OptionString);\r
@@ -1794,14 +2494,14 @@ DisplayOneMenu (
     PrintStringAtWithWidth (BeginCol, Row, L"", PromptWidth + AdjustValue + SkipWidth);\r
     PromptLineNum++;\r
   } else {\r
-    for (Index = 0; GetLineByWidth (MenuOption->Description, PromptWidth, &GlyphWidth, &Index, &OutputString) != 0x0000;) {      \r
-      if ((Temp == 0) && (Row <= BottomRow)) { \r
+    for (Index = 0; GetLineByWidth (MenuOption->Description, PromptWidth, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
+      if ((Temp == 0) && (Row <= BottomRow)) {\r
         //\r
-        // 1.Clean the start LEFT_SKIPPED_COLUMNS \r
+        // 1.Clean the start LEFT_SKIPPED_COLUMNS\r
         //\r
         PrintStringAtWithWidth (BeginCol, Row, L"", SkipWidth);\r
-        \r
-        if (Statement->OpCode->OpCode == EFI_IFR_REF_OP && MenuOption->Col >= 2) {\r
+\r
+        if (Statement->OpCode->OpCode == EFI_IFR_REF_OP && MenuOption->Col >= 2 && IsProcessingFirstRow) {\r
           //\r
           // Print Arrow for Goto button.\r
           //\r
@@ -1810,6 +2510,7 @@ DisplayOneMenu (
             Row,\r
             GEOMETRICSHAPE_RIGHT_TRIANGLE\r
             );\r
+          IsProcessingFirstRow = FALSE;\r
         }\r
         DisplayMenuString (MenuOption, MenuOption->Col, Row, OutputString, PromptWidth + AdjustValue, Highlight);\r
         PromptLineNum ++;\r
@@ -1838,13 +2539,13 @@ DisplayOneMenu (
   //\r
   if ((Statement->OpCode->OpCode  == EFI_IFR_TEXT_OP) && (((EFI_IFR_TEXT*)Statement->OpCode)->TextTwo != 0)) {\r
     StringPtr   = GetToken (((EFI_IFR_TEXT*)Statement->OpCode)->TextTwo, gFormData->HiiHandle);\r
-  \r
+\r
     Width       = (UINT16) gOptionBlockWidth - 1;\r
     Row         = MenuOption->Row;\r
     GlyphWidth  = 1;\r
     OptionLineNum = 0;\r
 \r
-    for (Index = 0; GetLineByWidth (StringPtr, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) { \r
+    for (Index = 0; GetLineByWidth (StringPtr, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
       if ((Temp3 == 0) && (Row <= BottomRow)) {\r
         DisplayMenuString (MenuOption, MenuOption->OptCol, Row, OutputString, Width + 1, Highlight);\r
         OptionLineNum++;\r
@@ -1855,9 +2556,15 @@ DisplayOneMenu (
       if (StrLen (&StringPtr[Index]) != 0) {\r
         if (Temp3 == 0) {\r
           Row++;\r
+          //\r
+          // If the rows for text two is greater than or equal to the skip value, increase the skip value\r
+          //\r
+          if ((Row - MenuOption->Row) >= MenuOption->Skip) {\r
+            MenuOption->Skip++;\r
+          }\r
         }\r
       }\r
-  \r
+\r
       FreePool (OutputString);\r
       if (Temp3 != 0) {\r
         Temp3--;\r
@@ -1876,7 +2583,7 @@ DisplayOneMenu (
     Row    = (OptionLineNum < PromptLineNum ? OptionLineNum : PromptLineNum) + MenuOption->Row;\r
     Width  = (UINT16) (OptionLineNum < PromptLineNum ? gOptionBlockWidth : PromptWidth + AdjustValue + SkipWidth);\r
     MaxRow = (OptionLineNum < PromptLineNum ? PromptLineNum : OptionLineNum) + MenuOption->Row - 1;\r
-    \r
+\r
     while (Row <= MaxRow) {\r
       DisplayMenuString (MenuOption, Col, Row++, L"", Width, FALSE);\r
     }\r
@@ -1901,7 +2608,7 @@ UiDisplayMenu (
   IN  FORM_DISPLAY_ENGINE_FORM  *FormData\r
   )\r
 {\r
-  INTN                            SkipValue;\r
+  UINTN                           SkipValue;\r
   INTN                            Difference;\r
   UINTN                           DistanceValue;\r
   UINTN                           Row;\r
@@ -1910,12 +2617,11 @@ UiDisplayMenu (
   UINTN                           Temp2;\r
   UINTN                           TopRow;\r
   UINTN                           BottomRow;\r
-  UINTN                           OriginalRow;\r
   UINTN                           Index;\r
-  UINT16                          Width;\r
   CHAR16                          *StringPtr;\r
+  CHAR16                          *StringRightPtr;\r
+  CHAR16                          *StringErrorPtr;\r
   CHAR16                          *OptionString;\r
-  CHAR16                          *OutputString;\r
   CHAR16                          *HelpString;\r
   CHAR16                          *HelpHeaderString;\r
   CHAR16                          *HelpBottomString;\r
@@ -1932,10 +2638,8 @@ UiDisplayMenu (
   UI_MENU_OPTION                  *MenuOption;\r
   UI_MENU_OPTION                  *NextMenuOption;\r
   UI_MENU_OPTION                  *SavedMenuOption;\r
-  UI_MENU_OPTION                  *PreviousMenuOption;\r
   UI_CONTROL_FLAG                 ControlFlag;\r
   UI_SCREEN_OPERATION             ScreenOperation;\r
-  UINT16                          DefaultId;\r
   FORM_DISPLAY_ENGINE_STATEMENT   *Statement;\r
   BROWSER_HOT_KEY                 *HotKey;\r
   UINTN                           HelpPageIndex;\r
@@ -1945,14 +2649,13 @@ UiDisplayMenu (
   UINTN                           HelpHeaderLine;\r
   UINTN                           HelpBottomLine;\r
   BOOLEAN                         MultiHelpPage;\r
-  UINT16                          GlyphWidth;\r
   UINT16                          EachLineWidth;\r
   UINT16                          HeaderLineWidth;\r
   UINT16                          BottomLineWidth;\r
   EFI_STRING_ID                   HelpInfo;\r
   UI_EVENT_TYPE                   EventType;\r
-  FORM_DISPLAY_ENGINE_STATEMENT   *InitialHighlight;\r
   BOOLEAN                         SkipHighLight;\r
+  EFI_HII_VALUE                   *StatementValue;\r
 \r
   EventType           = UIEventNone;\r
   Status              = EFI_SUCCESS;\r
@@ -1962,7 +2665,6 @@ UiDisplayMenu (
   OptionString        = NULL;\r
   ScreenOperation     = UiNoOperation;\r
   NewLine             = TRUE;\r
-  DefaultId           = 0;\r
   HelpPageCount       = 0;\r
   HelpLine            = 0;\r
   RowCount            = 0;\r
@@ -1973,33 +2675,20 @@ UiDisplayMenu (
   EachLineWidth       = 0;\r
   HeaderLineWidth     = 0;\r
   BottomLineWidth     = 0;\r
-  OutputString        = NULL;\r
   UpArrow             = FALSE;\r
   DownArrow           = FALSE;\r
   SkipValue           = 0;\r
   SkipHighLight       = FALSE;\r
 \r
   NextMenuOption      = NULL;\r
-  PreviousMenuOption  = NULL;\r
   SavedMenuOption     = NULL;\r
   HotKey              = NULL;\r
   Repaint             = TRUE;\r
   MenuOption          = NULL;\r
   gModalSkipColumn    = (CHAR16) (gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn) / 6;\r
-  InitialHighlight    = gFormData->HighLightedStatement;\r
 \r
   ZeroMem (&Key, sizeof (EFI_INPUT_KEY));\r
 \r
-  //\r
-  //  Left                                              right\r
-  //   |<-.->|<-.........->|<- .........->|<-...........->|\r
-  //     Skip    Prompt         Option         Help \r
-  //\r
-  Width             = (CHAR16) ((gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn) / 3);\r
-  gOptionBlockWidth = Width + 1; \r
-  gHelpBlockWidth   = (CHAR16) (Width - LEFT_SKIPPED_COLUMNS);\r
-  gPromptBlockWidth = (CHAR16) (gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn - 2 * Width - 1);\r
-\r
   TopRow    = gStatementDimensions.TopRow    + SCROLL_ARROW_HEIGHT;\r
   BottomRow = gStatementDimensions.BottomRow - SCROLL_ARROW_HEIGHT - 1;\r
 \r
@@ -2011,6 +2700,10 @@ UiDisplayMenu (
   }\r
 \r
   FindTopMenu(FormData, &TopOfScreen, &NewPos, &SkipValue);\r
+  if (!IsListEmpty (&gMenuOption)) {\r
+    NextMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+    gUserInput->SelectedStatement = NextMenuOption->ThisTag;\r
+  }\r
 \r
   gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
 \r
@@ -2018,7 +2711,7 @@ UiDisplayMenu (
   while (TRUE) {\r
     switch (ControlFlag) {\r
     case CfInitialization:\r
-      if ((gOldFormEntry.HiiHandle != FormData->HiiHandle) || \r
+      if ((gOldFormEntry.HiiHandle != FormData->HiiHandle) ||\r
           (!CompareGuid (&gOldFormEntry.FormSetGuid, &FormData->FormSetGuid))) {\r
         //\r
         // Clear Statement range if different formset is painted.\r
@@ -2047,7 +2740,7 @@ UiDisplayMenu (
         Row             = TopRow;\r
 \r
         gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());\r
-        \r
+\r
         //\r
         // 1. Check whether need to print the arrow up.\r
         //\r
@@ -2096,25 +2789,31 @@ UiDisplayMenu (
           }\r
 \r
           if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {\r
-            Status = DisplayOneMenu (MenuOption, \r
+            Status = DisplayOneMenu (MenuOption,\r
                             MenuOption->Col - gStatementDimensions.LeftColumn,\r
-                            gStatementDimensions.LeftColumn + gModalSkipColumn, \r
-                            Link == TopOfScreen ? SkipValue : 0, \r
+                            gStatementDimensions.LeftColumn + gModalSkipColumn,\r
+                            Link == TopOfScreen ? SkipValue : 0,\r
                             BottomRow,\r
-                            (BOOLEAN) ((Link == NewPos) && IsSelectable(MenuOption))\r
+                            (BOOLEAN) ((Link == NewPos) && IsSelectable(MenuOption)),\r
+                            TRUE\r
                             );\r
           } else {\r
-            Status = DisplayOneMenu (MenuOption, \r
+            Status = DisplayOneMenu (MenuOption,\r
                             MenuOption->Col - gStatementDimensions.LeftColumn,\r
-                            gStatementDimensions.LeftColumn, \r
-                            Link == TopOfScreen ? SkipValue : 0, \r
+                            gStatementDimensions.LeftColumn,\r
+                            Link == TopOfScreen ? SkipValue : 0,\r
                             BottomRow,\r
-                            (BOOLEAN) ((Link == NewPos) && IsSelectable(MenuOption))\r
-                            );         \r
+                            (BOOLEAN) ((Link == NewPos) && IsSelectable(MenuOption)),\r
+                            TRUE\r
+                            );\r
           }\r
 \r
           if (EFI_ERROR (Status)) {\r
-            return Status;\r
+            if (gMisMatch) {\r
+              return EFI_SUCCESS;\r
+            } else {\r
+              return Status;\r
+            }\r
           }\r
           //\r
           // 3. Update the row info which will be used by next menu.\r
@@ -2177,10 +2876,13 @@ UiDisplayMenu (
       //\r
       ControlFlag = CfUpdateHelpString;\r
 \r
+      ASSERT (NewPos != NULL);\r
+      UpdateHighlightMenuInfo(NewPos, TopOfScreen, SkipValue);\r
+\r
       if (SkipHighLight) {\r
-        MenuOption    = SavedMenuOption;\r
         SkipHighLight = FALSE;\r
-        UpdateHighlightMenuInfo (MenuOption);\r
+        MenuOption    = SavedMenuOption;\r
+        RefreshKeyHelp(gFormData, SavedMenuOption->ThisTag, FALSE);\r
         break;\r
       }\r
 \r
@@ -2203,169 +2905,39 @@ UiDisplayMenu (
         Temp2 = 0;\r
       }\r
 \r
-      if (NewPos != NULL && (MenuOption == NULL || NewPos != &MenuOption->Link)) {\r
+      if (MenuOption == NULL || NewPos != &MenuOption->Link) {\r
         if (MenuOption != NULL) {\r
           //\r
-          // Remove highlight on last Menu Option\r
+          // Remove the old highlight menu.\r
           //\r
-          gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row);\r
-          ProcessOptions (MenuOption, FALSE, &OptionString, TRUE);\r
-          gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());\r
-          if (OptionString != NULL) {\r
-            if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP) ||\r
-                (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP)\r
-               ) {\r
-              ProcessStringForDateTime(MenuOption, OptionString, FALSE);\r
-            }\r
-\r
-            Width               = (UINT16) gOptionBlockWidth - 1;\r
-            OriginalRow         = MenuOption->Row;\r
-            GlyphWidth          = 1;\r
-\r
-            for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
-              if ((Temp == 0) && (MenuOption->Row >= TopRow) && (MenuOption->Row <= BottomRow)) {\r
-                PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString);\r
-              }\r
-              //\r
-              // If there is more string to process print on the next row and increment the Skip value\r
-              //\r
-              if (StrLen (&OptionString[Index]) != 0) {\r
-                if (Temp == 0) {\r
-                  MenuOption->Row++;\r
-                }\r
-              }\r
-\r
-              FreePool (OutputString);\r
-              if (Temp != 0) {\r
-                Temp--;\r
-              }\r
-            }\r
-\r
-            MenuOption->Row = OriginalRow;\r
-\r
-            FreePool (OptionString);\r
-          } else {\r
-            if (NewLine) {\r
-              if (MenuOption->GrayOut) {\r
-                gST->ConOut->SetAttribute (gST->ConOut, GetGrayedTextColor ());\r
-              } else if (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) {\r
-                gST->ConOut->SetAttribute (gST->ConOut, GetSubTitleTextColor ());\r
-              }\r
-\r
-              OriginalRow = MenuOption->Row;\r
-              Width       = GetWidth (MenuOption, NULL);\r
-              GlyphWidth  = 1;\r
-\r
-              for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
-                if ((Temp == 0) && (MenuOption->Row >= TopRow) && (MenuOption->Row <= BottomRow)) {\r
-                  PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString);\r
-                }\r
-                //\r
-                // If there is more string to process print on the next row and increment the Skip value\r
-                //\r
-                if (StrLen (&MenuOption->Description[Index]) != 0) {\r
-                  if (Temp == 0) {\r
-                    MenuOption->Row++;\r
-                  }\r
-                }\r
-\r
-                FreePool (OutputString);\r
-                if (Temp != 0) {\r
-                  Temp--;\r
-                }\r
-              }\r
-\r
-              MenuOption->Row = OriginalRow;\r
-              gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());\r
-            }\r
-          }\r
+          Status = DisplayOneMenu (MenuOption,\r
+                          MenuOption->Col - gStatementDimensions.LeftColumn,\r
+                          gStatementDimensions.LeftColumn,\r
+                          Temp,\r
+                          BottomRow,\r
+                          FALSE,\r
+                          FALSE\r
+                          );\r
         }\r
 \r
         //\r
         // This is the current selected statement\r
         //\r
         MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
-        Statement = MenuOption->ThisTag;\r
-\r
-        UpdateHighlightMenuInfo (MenuOption);\r
+        RefreshKeyHelp(gFormData, MenuOption->ThisTag, FALSE);\r
 \r
         if (!IsSelectable (MenuOption)) {\r
           break;\r
         }\r
 \r
-        //\r
-        // Set reverse attribute\r
-        //\r
-        gST->ConOut->SetAttribute (gST->ConOut, GetHighlightTextColor ());\r
-        gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row);\r
-\r
-        ProcessOptions (MenuOption, FALSE, &OptionString, TRUE);\r
-        if (OptionString != NULL) {\r
-          if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP || Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {\r
-            ProcessStringForDateTime(MenuOption, OptionString, FALSE);\r
-          }\r
-          Width               = (UINT16) gOptionBlockWidth - 1;\r
-\r
-          OriginalRow         = MenuOption->Row;\r
-          GlyphWidth          = 1;\r
-\r
-          for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
-            if ((Temp2 == 0) && (MenuOption->Row >= TopRow) && (MenuOption->Row <= BottomRow) ) {\r
-              PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString);\r
-            }\r
-            //\r
-            // If there is more string to process print on the next row and increment the Skip value\r
-            //\r
-            if (StrLen (&OptionString[Index]) != 0) {\r
-              if (Temp2 == 0) {\r
-              MenuOption->Row++;\r
-              }\r
-            }\r
-\r
-            FreePool (OutputString);\r
-            if (Temp2 != 0) {\r
-              Temp2--;\r
-            }\r
-          }\r
-\r
-          MenuOption->Row = OriginalRow;\r
-\r
-          FreePool (OptionString);\r
-        } else {\r
-          if (NewLine) {\r
-            OriginalRow = MenuOption->Row;\r
-\r
-            Width       = GetWidth (MenuOption, NULL);\r
-            GlyphWidth          = 1;\r
-\r
-            for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
-              if ((Temp2 == 0) && (MenuOption->Row >= TopRow) && (MenuOption->Row <= BottomRow) ) {\r
-                PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString);\r
-              }\r
-              //\r
-              // If there is more string to process print on the next row and increment the Skip value\r
-              //\r
-              if (StrLen (&MenuOption->Description[Index]) != 0) {\r
-                if (Temp2 == 0) {\r
-                  MenuOption->Row++;\r
-                }\r
-              }\r
-\r
-              FreePool (OutputString);\r
-              if (Temp2 != 0) {\r
-                Temp2--;\r
-              }\r
-            }\r
-\r
-            MenuOption->Row = OriginalRow;\r
-\r
-          }\r
-        }\r
-\r
-        //\r
-        // Clear reverse attribute\r
-        //\r
-        gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());\r
+        Status = DisplayOneMenu (MenuOption,\r
+                        MenuOption->Col - gStatementDimensions.LeftColumn,\r
+                        gStatementDimensions.LeftColumn,\r
+                        Temp2,\r
+                        BottomRow,\r
+                        TRUE,\r
+                        FALSE\r
+                        );\r
       }\r
       break;\r
 \r
@@ -2375,6 +2947,10 @@ UiDisplayMenu (
         break;\r
       }\r
 \r
+      //\r
+      // NewLine means only update highlight menu (remove old highlight and highlith\r
+      // the new one), not need to full repain the form.\r
+      //\r
       if (Repaint || NewLine) {\r
         if (IsListEmpty (&gMenuOption)) {\r
           //\r
@@ -2387,10 +2963,26 @@ UiDisplayMenu (
           //\r
           ASSERT(MenuOption != NULL);\r
           HelpInfo = ((EFI_IFR_STATEMENT_HEADER *) ((CHAR8 *)MenuOption->ThisTag->OpCode + sizeof (EFI_IFR_OP_HEADER)))->Help;\r
+          Statement = MenuOption->ThisTag;\r
+          StatementValue = &Statement->CurrentValue;\r
           if (HelpInfo == 0 || !IsSelectable (MenuOption)) {\r
-            StringPtr = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
+            if ((Statement->OpCode->OpCode == EFI_IFR_DATE_OP && StatementValue->Value.date.Month== 0xff)||(Statement->OpCode->OpCode == EFI_IFR_TIME_OP && StatementValue->Value.time.Hour == 0xff)){\r
+              StringPtr = GetToken (STRING_TOKEN (GET_TIME_FAIL), gHiiHandle);\r
+            } else {\r
+              StringPtr = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
+            }\r
           } else {\r
-            StringPtr = GetToken (HelpInfo, gFormData->HiiHandle);\r
+            if ((Statement->OpCode->OpCode == EFI_IFR_DATE_OP && StatementValue->Value.date.Month== 0xff)||(Statement->OpCode->OpCode == EFI_IFR_TIME_OP && StatementValue->Value.time.Hour == 0xff)){\r
+              StringRightPtr = GetToken (HelpInfo, gFormData->HiiHandle);\r
+              StringErrorPtr = GetToken (STRING_TOKEN (GET_TIME_FAIL), gHiiHandle);\r
+              StringPtr = AllocateZeroPool ((StrLen (StringRightPtr) + StrLen (StringErrorPtr)+ 1 ) * sizeof (CHAR16));\r
+              StrCpyS (StringPtr, StrLen (StringRightPtr) + StrLen (StringErrorPtr) + 1, StringRightPtr);\r
+              StrCatS (StringPtr, StrLen (StringRightPtr) + StrLen (StringErrorPtr) + 1, StringErrorPtr);\r
+              FreePool (StringRightPtr);\r
+              FreePool (StringErrorPtr);\r
+            } else {\r
+              StringPtr = GetToken (HelpInfo, gFormData->HiiHandle);\r
+            }\r
           }\r
         }\r
 \r
@@ -2427,7 +3019,7 @@ UiDisplayMenu (
           //\r
           if (HelpLine > 2 * RowCount - 2) {\r
             HelpPageCount = (HelpLine - RowCount + 1) / (RowCount - 2) + 1;\r
-            if ((HelpLine - RowCount + 1) % (RowCount - 2) > 1) {\r
+            if ((HelpLine - RowCount + 1) % (RowCount - 2) != 0) {\r
               HelpPageCount += 1;\r
             }\r
           } else {\r
@@ -2441,14 +3033,14 @@ UiDisplayMenu (
       //\r
       // Check whether need to show the 'More(U/u)' at the begin.\r
       // Base on current direct info, here shows aligned to the right side of the column.\r
-      // If the direction is multi line and aligned to right side may have problem, so \r
+      // If the direction is multi line and aligned to right side may have problem, so\r
       // add ASSERT code here.\r
       //\r
       if (HelpPageIndex > 0) {\r
         gST->ConOut->SetAttribute (gST->ConOut, GetInfoTextColor ());\r
         for (Index = 0; Index < HelpHeaderLine; Index++) {\r
           ASSERT (HelpHeaderLine == 1);\r
-          ASSERT (GetStringWidth (HelpHeaderString) / 2 < (UINTN) (gHelpBlockWidth - 1));\r
+          ASSERT (GetStringWidth (HelpHeaderString) / 2 < ((UINT32) gHelpBlockWidth - 1));\r
           PrintStringAtWithWidth (\r
             gStatementDimensions.RightColumn - gHelpBlockWidth,\r
             Index + TopRow,\r
@@ -2496,7 +3088,7 @@ UiDisplayMenu (
               );\r
           }\r
         } else {\r
-          for (Index = 0; (Index < RowCount - HelpBottomLine - HelpHeaderLine) && \r
+          for (Index = 0; (Index < RowCount - HelpBottomLine - HelpHeaderLine) &&\r
               (Index + HelpPageIndex * (RowCount - 2) + 1 < HelpLine); Index++) {\r
             PrintStringAtWithWidth (\r
               gStatementDimensions.RightColumn - gHelpBlockWidth,\r
@@ -2516,20 +3108,20 @@ UiDisplayMenu (
             }\r
             gST->ConOut->SetCursorPosition(gST->ConOut, gStatementDimensions.RightColumn-1, BottomRow);\r
           }\r
-        } \r
+        }\r
       }\r
 \r
       //\r
       // Check whether need to print the 'More(D/d)' at the bottom.\r
       // Base on current direct info, here shows aligned to the right side of the column.\r
-      // If the direction is multi line and aligned to right side may have problem, so \r
+      // If the direction is multi line and aligned to right side may have problem, so\r
       // add ASSERT code here.\r
       //\r
       if (HelpPageIndex < HelpPageCount - 1 && MultiHelpPage) {\r
         gST->ConOut->SetAttribute (gST->ConOut, GetInfoTextColor ());\r
         for (Index = 0; Index < HelpBottomLine; Index++) {\r
           ASSERT (HelpBottomLine == 1);\r
-          ASSERT (GetStringWidth (HelpBottomString) / 2 < (UINTN) (gHelpBlockWidth - 1)); \r
+          ASSERT (GetStringWidth (HelpBottomString) / 2 < ((UINT32) gHelpBlockWidth - 1));\r
           PrintStringAtWithWidth (\r
             gStatementDimensions.RightColumn - gHelpBlockWidth,\r
             BottomRow + Index - HelpBottomLine + 1,\r
@@ -2574,7 +3166,7 @@ UiDisplayMenu (
         if (Status != EFI_NOT_READY) {\r
           continue;\r
         }\r
-        \r
+\r
         EventType = UiWaitForEvent(gST->ConIn->WaitForKey);\r
         if (EventType == UIEventKey) {\r
           gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
@@ -2583,11 +3175,12 @@ UiDisplayMenu (
       }\r
 \r
       if (EventType == UIEventDriver) {\r
+        gMisMatch = TRUE;\r
         gUserInput->Action = BROWSER_ACTION_NONE;\r
         ControlFlag = CfExit;\r
         break;\r
       }\r
-      \r
+\r
       if (EventType == UIEventTimeOut) {\r
         gUserInput->Action = BROWSER_ACTION_FORM_EXIT;\r
         ControlFlag = CfExit;\r
@@ -2615,12 +3208,12 @@ UiDisplayMenu (
         // If the screen has no menu items, and the user didn't select UiReset\r
         // ignore the selection and go back to reading keys.\r
         //\r
+        ASSERT(MenuOption != NULL);\r
         if(IsListEmpty (&gMenuOption) || MenuOption->GrayOut || MenuOption->ReadOnly) {\r
           ControlFlag = CfReadKey;\r
           break;\r
         }\r
 \r
-        ASSERT(MenuOption != NULL);\r
         Statement = MenuOption->ThisTag;\r
         if ((Statement->OpCode->OpCode == EFI_IFR_DATE_OP)\r
           || (Statement->OpCode->OpCode == EFI_IFR_TIME_OP)\r
@@ -2631,7 +3224,7 @@ UiDisplayMenu (
           } else {\r
             gDirection = SCAN_LEFT;\r
           }\r
-          \r
+\r
           Status = ProcessOptions (MenuOption, TRUE, &OptionString, TRUE);\r
           if (OptionString != NULL) {\r
             FreePool (OptionString);\r
@@ -2662,7 +3255,7 @@ UiDisplayMenu (
           ControlFlag = CfReadKey;\r
           break;\r
         }\r
-        \r
+\r
         ASSERT(MenuOption != NULL);\r
         if (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_CHECKBOX_OP && !MenuOption->GrayOut && !MenuOption->ReadOnly) {\r
           ScreenOperation = UiSelect;\r
@@ -2696,7 +3289,7 @@ UiDisplayMenu (
             break;\r
           }\r
         }\r
-        \r
+\r
         if (((FormData->Attribute & HII_DISPLAY_MODAL) != 0) && (Key.ScanCode == SCAN_ESC || Index == mScanCodeNumber)) {\r
           //\r
           // ModalForm has no ESC key and Hot Key.\r
@@ -2729,7 +3322,7 @@ UiDisplayMenu (
       }\r
 \r
       for (Index = 0;\r
-           Index < sizeof (gScreenOperationToControlFlag) / sizeof (gScreenOperationToControlFlag[0]);\r
+           Index < ARRAY_SIZE (gScreenOperationToControlFlag);\r
            Index++\r
           ) {\r
         if (ScreenOperation == gScreenOperationToControlFlag[Index].ScreenOperation) {\r
@@ -2761,11 +3354,11 @@ UiDisplayMenu (
         //\r
         RefreshKeyHelp (gFormData, Statement, TRUE);\r
         Status = ProcessOptions (MenuOption, TRUE, &OptionString, TRUE);\r
-        \r
+\r
         if (OptionString != NULL) {\r
           FreePool (OptionString);\r
         }\r
-        \r
+\r
         if (EFI_ERROR (Status)) {\r
           Repaint = TRUE;\r
           NewLine = TRUE;\r
@@ -2790,22 +3383,27 @@ UiDisplayMenu (
         break;\r
       }\r
 \r
-      //\r
-      // When user press ESC, it will try to show another menu, should clean the gSequence info.\r
-      //\r
-      if (gSequence != 0) {\r
-        gSequence = 0;\r
-      }\r
-\r
       gUserInput->Action = BROWSER_ACTION_FORM_EXIT;\r
       ControlFlag = CfExit;\r
       break;\r
 \r
     case CfUiHotKey:\r
       ControlFlag = CfRepaint;\r
-      \r
-      gUserInput->Action = HotKey->Action;\r
-      ControlFlag = CfExit;\r
+\r
+      ASSERT (HotKey != NULL);\r
+\r
+      if (FxConfirmPopup(HotKey->Action)) {\r
+        gUserInput->Action = HotKey->Action;\r
+        if ((HotKey->Action & BROWSER_ACTION_DEFAULT) == BROWSER_ACTION_DEFAULT) {\r
+          gUserInput->DefaultId = HotKey->DefaultId;\r
+        }\r
+        ControlFlag = CfExit;\r
+      } else {\r
+        Repaint     = TRUE;\r
+        NewLine     = TRUE;\r
+        ControlFlag = CfRepaint;\r
+      }\r
+\r
       break;\r
 \r
     case CfUiLeft:\r
@@ -2838,230 +3436,129 @@ UiDisplayMenu (
 \r
     case CfUiUp:\r
       ControlFlag = CfRepaint;\r
+      NewLine     = TRUE;\r
 \r
       SavedListEntry = NewPos;\r
-\r
-      ASSERT(NewPos != NULL);\r
-      //\r
-      // Adjust Date/Time position before we advance forward.\r
-      //\r
-      AdjustDateAndTimePosition (TRUE, &NewPos);\r
-      if (NewPos->BackLink != &gMenuOption) {\r
-        MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
-        ASSERT (MenuOption != NULL);\r
-        NewLine    = TRUE;\r
-        NewPos     = NewPos->BackLink;\r
-\r
-        PreviousMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
-        if (PreviousMenuOption->Row == 0) {\r
-          UpdateOptionSkipLines (PreviousMenuOption);\r
-        }\r
-        DistanceValue = PreviousMenuOption->Skip;\r
-        Difference    = 0;\r
-        if (MenuOption->Row >= DistanceValue + TopRow) {\r
-          Difference = MoveToNextStatement (TRUE, &NewPos, MenuOption->Row - TopRow - DistanceValue);\r
-        }\r
-        NextMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
-       \r
-        if (Difference < 0) {\r
-          //\r
-          // We hit the begining MenuOption that can be focused\r
-          // so we simply scroll to the top.\r
-          //\r
-          if (TopOfScreen != gMenuOption.ForwardLink) {\r
-            TopOfScreen = gMenuOption.ForwardLink;\r
-            Repaint     = TRUE;\r
-          } else {\r
-            //\r
-            // Scroll up to the last page when we have arrived at top page.\r
-            //\r
-            NewPos          = &gMenuOption;\r
-            TopOfScreen     = &gMenuOption;\r
-            MenuOption      = MENU_OPTION_FROM_LINK (SavedListEntry);\r
-            ScreenOperation = UiPageUp;\r
-            ControlFlag     = CfScreenOperation;\r
-            break;\r
-          }\r
-        } else if (MenuOption->Row < TopRow + DistanceValue + Difference) {\r
-          //\r
-          // Previous focus MenuOption is above the TopOfScreen, so we need to scroll\r
-          //\r
-          TopOfScreen = NewPos;\r
-          Repaint     = TRUE;\r
-          SkipValue = 0;\r
-        } else if (!IsSelectable (NextMenuOption)) {\r
-          //\r
-          // Continue to go up until scroll to next page or the selectable option is found.\r
-          //\r
-          ScreenOperation = UiUp;\r
-          ControlFlag     = CfScreenOperation;\r
-        }\r
-\r
-        //\r
-        // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.\r
-        //\r
-        AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
-        AdjustDateAndTimePosition (TRUE, &NewPos);\r
-        MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
-        UpdateStatusBar (INPUT_ERROR, FALSE);\r
-      } else {\r
-        if (NewPos->ForwardLink == &gMenuOption) {\r
-          NewLine   = FALSE;\r
-          Repaint   = FALSE;\r
-          break;\r
-        }\r
-        //\r
-        // Scroll up to the last page.\r
-        //\r
-        NewPos          = &gMenuOption;\r
-        TopOfScreen     = &gMenuOption;\r
-        MenuOption      = MENU_OPTION_FROM_LINK (SavedListEntry);\r
-        ScreenOperation = UiPageUp;\r
-        ControlFlag     = CfScreenOperation;\r
-        SkipValue       = 0;\r
-      }\r
-      break;\r
-\r
-    case CfUiPageUp:\r
-      //\r
-      // SkipValue means lines is skipped when show the top menu option.\r
-      //\r
-      ControlFlag     = CfRepaint;\r
-\r
       ASSERT(NewPos != NULL);\r
-      //\r
-      // Already at the first menu option, Check the skip value.\r
-      //\r
-      if (NewPos->BackLink == &gMenuOption) {\r
-        if (SkipValue == 0) {\r
-          NewLine = FALSE;\r
-          Repaint = FALSE;\r
-        } else {\r
-          NewLine = TRUE;\r
-          Repaint = TRUE;\r
-          SkipValue = 0;\r
-        }\r
-        break;\r
-      }\r
 \r
-      NewLine   = TRUE;\r
-      Repaint   = TRUE;\r
+      MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+      ASSERT (MenuOption != NULL);\r
 \r
       //\r
-      // SkipValue > (BottomRow - TopRow + 1) means current menu has more than one\r
-      // form of options to be show, so just update the SkipValue to show the next\r
-      // parts of options.\r
+      // Adjust Date/Time position before we advance forward.\r
       //\r
-      if (SkipValue > (INTN) (BottomRow - TopRow + 1)) {\r
-        SkipValue -= BottomRow - TopRow + 1;\r
-        break;\r
-      }\r
+      AdjustDateAndTimePosition (TRUE, &NewPos);\r
 \r
-      Link      = TopOfScreen;\r
+      NewPos     = NewPos->BackLink;\r
       //\r
-      // First minus the menu of the top screen, it's value is SkipValue.\r
+      // Find next selectable menu or the first menu beyond current form.\r
       //\r
-      Index     = (BottomRow + 1) - SkipValue;\r
-      while ((Index > TopRow) && (Link->BackLink != &gMenuOption)) {\r
-        Link = Link->BackLink;\r
-        PreviousMenuOption = MENU_OPTION_FROM_LINK (Link);\r
-        if (PreviousMenuOption->Row == 0) {\r
-          UpdateOptionSkipLines (PreviousMenuOption);\r
-        }        \r
-        if (Index < PreviousMenuOption->Skip) {\r
-          break;\r
-        }\r
-        Index = Index - PreviousMenuOption->Skip;\r
-      }\r
-      \r
-      if ((Link->BackLink == &gMenuOption) && (Index >= TopRow)) {\r
-        if (TopOfScreen == &gMenuOption) {\r
+      Difference = MoveToNextStatement (TRUE, &NewPos, MenuOption->Row - TopRow, FALSE);\r
+      if (Difference < 0) {\r
+        //\r
+        // We hit the begining MenuOption that can be focused\r
+        // so we simply scroll to the top.\r
+        //\r
+        Repaint     = TRUE;\r
+        if (TopOfScreen != gMenuOption.ForwardLink || SkipValue != 0) {\r
           TopOfScreen = gMenuOption.ForwardLink;\r
-          NewPos      = gMenuOption.BackLink;\r
-          MoveToNextStatement (TRUE, &NewPos, BottomRow - TopRow);\r
-          if (Index < PreviousMenuOption->Skip) {\r
-            Repaint = TRUE;\r
-            SkipValue = PreviousMenuOption->Skip - (Index - TopRow);\r
-          } else {\r
-            Repaint = FALSE;\r
-            SkipValue = 0;\r
-          }\r
-        } else if (TopOfScreen != Link) {\r
-          TopOfScreen = Link;\r
-          NewPos      = Link;\r
-          MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow);\r
+          NewPos      = SavedListEntry;\r
           SkipValue = 0;\r
         } else {\r
           //\r
-          // Finally we know that NewPos is the last MenuOption can be focused.\r
+          // Scroll up to the last page when we have arrived at top page.\r
           //\r
-          if (SkipValue == 0) {\r
-            Repaint = FALSE;\r
-          }\r
-          NewPos  = Link;\r
-          MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow);\r
-          SkipValue = 0;\r
+          TopOfScreen = FindTopOfScreenMenu (gMenuOption.BackLink, BottomRow - TopRow, &SkipValue);\r
+          NewPos = gMenuOption.BackLink;\r
+          MoveToNextStatement (TRUE, &NewPos, BottomRow - TopRow, TRUE);\r
         }\r
       } else {\r
-        if (Index > TopRow) {\r
+        NextMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+\r
+        if (MenuOption->Row < TopRow + Difference + NextMenuOption->Skip) {\r
           //\r
-          // At here, only case "Index < PreviousMenuOption->Skip" can reach here.\r
+          // Previous focus MenuOption is above the TopOfScreen, so we need to scroll\r
           //\r
-          SkipValue = PreviousMenuOption->Skip - (Index - TopRow);\r
-        } else if (Index == TopRow) {\r
-          SkipValue = 0;\r
-        } else {\r
-          SkipValue = TopRow - Index;\r
+          TopOfScreen = NewPos;\r
+          Repaint     = TRUE;\r
+          SkipValue   = 0;\r
         }\r
 \r
         //\r
-        // Move to the option in Next page.\r
+        // Check whether new highlight menu is selectable, if not, keep highlight on the old one.\r
         //\r
-        if (TopOfScreen == &gMenuOption) {\r
-          NewPos = gMenuOption.BackLink;\r
-          MoveToNextStatement (TRUE, &NewPos, BottomRow - TopRow);\r
-        } else {\r
-          NewPos = Link;\r
-          MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow);\r
+        // BottomRow - TopRow + 1 means the total rows current forms supported.\r
+        // Difference + NextMenuOption->Skip + 1 means the distance between last highlight menu\r
+        // and new top menu. New top menu will all shows in next form, but last highlight menu\r
+        // may only shows 1 line. + 1 at right part means at least need to keep 1 line for the\r
+        // last highlight menu.\r
+        //\r
+        if (!IsSelectable(NextMenuOption) && IsSelectable(MenuOption) &&\r
+            (BottomRow - TopRow + 1 >= Difference + NextMenuOption->Skip + 1)) {\r
+          NewPos = SavedListEntry;\r
         }\r
+      }\r
+\r
+      UpdateStatusBar (INPUT_ERROR, FALSE);\r
+\r
+      //\r
+      // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.\r
+      //\r
+      AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
+      AdjustDateAndTimePosition (TRUE, &NewPos);\r
+\r
+      UpdateHighlightMenuInfo(NewPos, TopOfScreen, SkipValue);\r
+      break;\r
+\r
+    case CfUiPageUp:\r
+      //\r
+      // SkipValue means lines is skipped when show the top menu option.\r
+      //\r
+      ControlFlag = CfRepaint;\r
+      NewLine     = TRUE;\r
+      Repaint     = TRUE;\r
 \r
+      Link      = TopOfScreen;\r
+      //\r
+      // First minus the menu of the top screen, it's value is SkipValue.\r
+      //\r
+      if (SkipValue >= BottomRow - TopRow + 1) {\r
         //\r
-        // There are more MenuOption needing scrolling up.\r
+        // SkipValue > (BottomRow - TopRow + 1) means current menu has more than one\r
+        // form of options to be show, so just update the SkipValue to show the next\r
+        // parts of options.\r
         //\r
-        TopOfScreen = Link;\r
-        MenuOption  = NULL;\r
+        SkipValue -= BottomRow - TopRow + 1;\r
+        NewPos     = TopOfScreen;\r
+        break;\r
+      } else {\r
+        Index     = (BottomRow + 1) - SkipValue - TopRow;\r
       }\r
 \r
+      TopOfScreen = FindTopOfScreenMenu(TopOfScreen, Index, &SkipValue);\r
+      NewPos = TopOfScreen;\r
+      MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow, FALSE);\r
+\r
+      UpdateStatusBar (INPUT_ERROR, FALSE);\r
+\r
       //\r
       // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.\r
       // Don't do this when we are already in the first page.\r
       //\r
       AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
       AdjustDateAndTimePosition (TRUE, &NewPos);\r
+\r
+      UpdateHighlightMenuInfo(NewPos, TopOfScreen, SkipValue);\r
       break;\r
 \r
     case CfUiPageDown:\r
       //\r
       // SkipValue means lines is skipped when show the top menu option.\r
       //\r
-      ControlFlag     = CfRepaint;\r
-\r
-      ASSERT (NewPos != NULL);\r
-      if (NewPos->ForwardLink == &gMenuOption) {\r
-        MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
-        if (SkipValue + BottomRow - TopRow + 1 < MenuOption->Skip) {\r
-          SkipValue += BottomRow - TopRow + 1;\r
-          NewLine = TRUE;\r
-          Repaint = TRUE;\r
-          break;\r
-        }\r
-        NewLine = FALSE;\r
-        Repaint = FALSE;\r
-        break;\r
-      }\r
+      ControlFlag = CfRepaint;\r
+      NewLine     = TRUE;\r
+      Repaint     = TRUE;\r
 \r
-      NewLine = TRUE;\r
-      Repaint = TRUE;\r
       Link    = TopOfScreen;\r
       NextMenuOption = MENU_OPTION_FROM_LINK (Link);\r
       Index = TopRow + NextMenuOption->Skip - SkipValue;\r
@@ -3076,10 +3573,10 @@ UiDisplayMenu (
 \r
       if ((Link->ForwardLink == &gMenuOption) && (Index <= BottomRow + 1)) {\r
         //\r
-        // Finally we know that NewPos is the last MenuOption can be focused.\r
+        // Highlight on the last menu which can be highlight.\r
         //\r
         Repaint = FALSE;\r
-        MoveToNextStatement (TRUE, &Link, Index - TopRow);\r
+        MoveToNextStatement (TRUE, &Link, Index - TopRow, TRUE);\r
       } else {\r
         //\r
         // Calculate the skip line for top of screen menu.\r
@@ -3092,13 +3589,12 @@ UiDisplayMenu (
         } else {\r
           SkipValue = NextMenuOption->Skip - (Index - (BottomRow + 1));\r
         }\r
-\r
         TopOfScreen = Link;\r
         MenuOption = NULL;\r
         //\r
         // Move to the Next selectable menu.\r
         //\r
-        MoveToNextStatement (FALSE, &Link, BottomRow - TopRow);\r
+        MoveToNextStatement (FALSE, &Link, BottomRow - TopRow, TRUE);\r
       }\r
 \r
       //\r
@@ -3106,12 +3602,16 @@ UiDisplayMenu (
       //\r
       NewPos  = Link;\r
 \r
+      UpdateStatusBar (INPUT_ERROR, FALSE);\r
+\r
       //\r
       // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.\r
       // Don't do this when we are already in the last page.\r
       //\r
       AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
       AdjustDateAndTimePosition (TRUE, &NewPos);\r
+\r
+      UpdateHighlightMenuInfo(NewPos, TopOfScreen, SkipValue);\r
       break;\r
 \r
     case CfUiDown:\r
@@ -3120,7 +3620,15 @@ UiDisplayMenu (
       // NewPos  points to the menu which is highlighted now.\r
       //\r
       ControlFlag = CfRepaint;\r
+      NewLine     = TRUE;\r
+\r
+      if (NewPos == TopOfScreen) {\r
+        Temp2 = SkipValue;\r
+      } else {\r
+        Temp2 = 0;\r
+      }\r
 \r
+      SavedListEntry = NewPos;\r
       //\r
       // Since the behavior of hitting the down arrow on a Date/Time op-code is intended\r
       // to be one that progresses to the next set of op-codes, we need to advance to the last\r
@@ -3129,187 +3637,143 @@ UiDisplayMenu (
       // op-code is the last entry in the menu, we need to rewind back to the first op-code of\r
       // the Date/Time op-code.\r
       //\r
-      SavedListEntry = NewPos;\r
       AdjustDateAndTimePosition (FALSE, &NewPos);\r
 \r
-      if (NewPos->ForwardLink != &gMenuOption) {\r
-        if (NewPos == TopOfScreen) {\r
-          Temp2 = SkipValue;\r
+      MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+      NewPos     = NewPos->ForwardLink;\r
+      //\r
+      // Find the next selectable menu.\r
+      //\r
+      if (MenuOption->Row + MenuOption->Skip - Temp2 > BottomRow + 1) {\r
+        if (gMenuOption.ForwardLink == NewPos || &gMenuOption == NewPos) {\r
+          Difference = -1;\r
+        } else {\r
+          Difference = 0;\r
+        }\r
+      } else {\r
+        Difference = MoveToNextStatement (FALSE, &NewPos, BottomRow + 1 - (MenuOption->Row + MenuOption->Skip - Temp2), FALSE);\r
+      }\r
+      if (Difference < 0) {\r
+        //\r
+        // Scroll to the first page.\r
+        //\r
+        if (TopOfScreen != gMenuOption.ForwardLink || SkipValue != 0) {\r
+          TopOfScreen = gMenuOption.ForwardLink;\r
+          Repaint     = TRUE;\r
+          MenuOption  = NULL;\r
         } else {\r
-          Temp2 = 0;\r
+          MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
         }\r
+        NewPos        = gMenuOption.ForwardLink;\r
+        MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow, TRUE);\r
+\r
+        SkipValue = 0;\r
+        //\r
+        // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.\r
+        //\r
+        AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
+        AdjustDateAndTimePosition (TRUE, &NewPos);\r
 \r
-        MenuOption      = MENU_OPTION_FROM_LINK (NewPos);\r
-        NewLine         = TRUE;\r
-        NewPos          = NewPos->ForwardLink;\r
+        UpdateHighlightMenuInfo(NewPos, TopOfScreen, SkipValue);\r
+        break;\r
+      }\r
+\r
+      //\r
+      // Get next selected menu info.\r
+      //\r
+      AdjustDateAndTimePosition (FALSE, &NewPos);\r
+      NextMenuOption  = MENU_OPTION_FROM_LINK (NewPos);\r
+      if (NextMenuOption->Row == 0) {\r
+        UpdateOptionSkipLines (NextMenuOption);\r
+      }\r
+\r
+      //\r
+      // Calculate new highlight menu end row.\r
+      //\r
+      Temp = (MenuOption->Row + MenuOption->Skip - Temp2) + Difference + NextMenuOption->Skip - 1;\r
+      if (Temp > BottomRow) {\r
+        //\r
+        // Get the top screen menu info.\r
+        //\r
+        AdjustDateAndTimePosition (FALSE, &TopOfScreen);\r
+        SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
 \r
-        Difference      = 0;\r
         //\r
-        // Current menu not at the bottom of the form.\r
+        // Current Top screen menu occupy (SavedMenuOption->Skip - SkipValue) rows.\r
+        // Full shows the new selected menu need to skip (Temp - BottomRow - 1) rows.\r
         //\r
-        if (BottomRow >= MenuOption->Row + MenuOption->Skip - Temp2) {\r
+        if ((Temp - BottomRow) >= (SavedMenuOption->Skip - SkipValue)) {\r
           //\r
-          // Find the next selectable menu.\r
+          // Skip the top op-code\r
           //\r
-          Difference = MoveToNextStatement (FALSE, &NewPos, BottomRow - MenuOption->Row - MenuOption->Skip + Temp2);\r
-          //\r
-          // We hit the end of MenuOption that can be focused\r
-          // so we simply scroll to the first page.\r
-          //\r
-          if (Difference < 0) {\r
-            //\r
-            // Scroll to the first page.\r
-            //\r
-            if (TopOfScreen != gMenuOption.ForwardLink) {\r
-              TopOfScreen = gMenuOption.ForwardLink;\r
-              Repaint     = TRUE;\r
-              MenuOption  = NULL;\r
-            } else {\r
-              MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
-            }\r
-            NewPos        = gMenuOption.ForwardLink;\r
-            MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow);\r
+          TopOfScreen   = TopOfScreen->ForwardLink;\r
+          DistanceValue = (Temp - BottomRow) - (SavedMenuOption->Skip - SkipValue);\r
 \r
-            SkipValue = 0;\r
-            //\r
-            // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.\r
-            //\r
-            AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
-            AdjustDateAndTimePosition (TRUE, &NewPos);\r
-            break;\r
-          }\r
-        }\r
-        NextMenuOption  = MENU_OPTION_FROM_LINK (NewPos);\r
-        if (NextMenuOption->Row == 0) {\r
-          UpdateOptionSkipLines (NextMenuOption);\r
-        }\r
-        DistanceValue  = Difference + NextMenuOption->Skip - Temp2;\r
-\r
-        Temp = MenuOption->Row + MenuOption->Skip + DistanceValue - 1;\r
-        if ((MenuOption->Row + MenuOption->Skip - Temp2 == BottomRow + 1) &&\r
-            (NextMenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP ||\r
-             NextMenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP)\r
-            ) {\r
-          Temp ++;\r
-        }\r
+          SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
 \r
-        //\r
-        // If we are going to scroll, update TopOfScreen\r
-        //\r
-        if (Temp > BottomRow) {\r
-          do {\r
+          //\r
+          // If we have a remainder, skip that many more op-codes until we drain the remainder\r
+          // Special case is the selected highlight menu has more than one form of menus.\r
+          //\r
+          while (DistanceValue >= SavedMenuOption->Skip && TopOfScreen != NewPos) {\r
             //\r
-            // Is the current top of screen a zero-advance op-code?\r
-            // If so, keep moving forward till we hit a >0 advance op-code\r
+            // Since the Difference is greater than or equal to this op-code's skip value, skip it\r
             //\r
+            DistanceValue   = DistanceValue - (INTN) SavedMenuOption->Skip;\r
+            TopOfScreen     = TopOfScreen->ForwardLink;\r
             SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
-\r
-            //\r
-            // If bottom op-code is more than one line or top op-code is more than one line\r
-            //\r
-            if ((DistanceValue > 1) || (SavedMenuOption->Skip > 1)) {\r
-              //\r
-              // Is the bottom op-code greater than or equal in size to the top op-code?\r
-              //\r
-              if ((Temp - BottomRow) >= (SavedMenuOption->Skip - SkipValue)) {\r
-                //\r
-                // Skip the top op-code\r
-                //\r
-                TopOfScreen     = TopOfScreen->ForwardLink;\r
-                Difference      = (Temp - BottomRow) - (SavedMenuOption->Skip - SkipValue);\r
-\r
-                SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
-\r
-                //\r
-                // If we have a remainder, skip that many more op-codes until we drain the remainder\r
-                //\r
-                while (Difference >= (INTN) SavedMenuOption->Skip) {\r
-                  //\r
-                  // Since the Difference is greater than or equal to this op-code's skip value, skip it\r
-                  //\r
-                  Difference      = Difference - (INTN) SavedMenuOption->Skip;\r
-                  TopOfScreen     = TopOfScreen->ForwardLink;\r
-                  SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
-                }\r
-                //\r
-                // Since we will act on this op-code in the next routine, and increment the\r
-                // SkipValue, set the skips to one less than what is required.\r
-                //\r
-                SkipValue = Difference - 1;\r
-              } else {\r
-                //\r
-                // Since we will act on this op-code in the next routine, and increment the\r
-                // SkipValue, set the skips to one less than what is required.\r
-                //\r
-                SkipValue += (Temp - BottomRow) - 1;\r
-              }\r
-            } else {\r
-              if ((SkipValue + 1) == (INTN) SavedMenuOption->Skip) {\r
-                TopOfScreen = TopOfScreen->ForwardLink;\r
-                break;\r
-              }\r
-            }\r
-            //\r
-            // If the op-code at the top of the screen is more than one line, let's not skip it yet\r
-            // Let's set a skip flag to smoothly scroll the top of the screen.\r
-            //\r
-            if (SavedMenuOption->Skip > 1) {\r
-              if (SavedMenuOption == NextMenuOption) {\r
-                SkipValue = 0;\r
-              } else {\r
-                SkipValue++;\r
-              }\r
-            } else if (SavedMenuOption->Skip == 1) {\r
-              SkipValue   = 0;\r
-            } else {\r
-              SkipValue   = 0;\r
-              TopOfScreen = TopOfScreen->ForwardLink;\r
-            }\r
-          } while (SavedMenuOption->Skip == 0);\r
-\r
-          Repaint       = TRUE;\r
-        } else if (!IsSelectable (NextMenuOption)) {\r
+          }\r
           //\r
-          // Continue to go down until scroll to next page or the selectable option is found.\r
+          // Since we will act on this op-code in the next routine, and increment the\r
+          // SkipValue, set the skips to one less than what is required.\r
           //\r
-          ScreenOperation = UiDown;\r
-          ControlFlag     = CfScreenOperation;\r
-        }\r
-\r
-        MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
-\r
-        UpdateStatusBar (INPUT_ERROR, FALSE);\r
-\r
-      } else {\r
-        //\r
-        // Scroll to the first page.\r
-        //\r
-        if (TopOfScreen != gMenuOption.ForwardLink || SkipValue != 0) {\r
-          TopOfScreen = gMenuOption.ForwardLink;\r
-          Repaint     = TRUE;\r
-          MenuOption  = NULL;\r
+          if (TopOfScreen != NewPos) {\r
+            SkipValue = DistanceValue;\r
+          } else {\r
+            SkipValue = 0;\r
+          }\r
         } else {\r
           //\r
-          // Need to remove the current highlight menu.\r
-          // MenuOption saved the last highlight menu info.\r
+          // Since we will act on this op-code in the next routine, and increment the\r
+          // SkipValue, set the skips to one less than what is required.\r
           //\r
-          MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
+          SkipValue += Temp - BottomRow;\r
         }\r
-\r
-        SkipValue     = 0;\r
-        NewLine       = TRUE;\r
+        Repaint       = TRUE;\r
+      } else if (!IsSelectable (NextMenuOption)) {\r
         //\r
-        // Get the next highlight menu.\r
+        // Continue to go down until scroll to next page or the selectable option is found.\r
         //\r
-        NewPos        = gMenuOption.ForwardLink;\r
-        MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow);\r
+        ScreenOperation = UiDown;\r
+        ControlFlag     = CfScreenOperation;\r
+        break;\r
+      }\r
+\r
+      MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
+\r
+      //\r
+      // Check whether new highlight menu is selectable, if not, keep highlight on the old one.\r
+      //\r
+      // BottomRow - TopRow + 1 means the total rows current forms supported.\r
+      // Difference + NextMenuOption->Skip + 1 means the distance between last highlight menu\r
+      // and new top menu. New top menu will all shows in next form, but last highlight menu\r
+      // may only shows 1 line. + 1 at right part means at least need to keep 1 line for the\r
+      // last highlight menu.\r
+      //\r
+      if (!IsSelectable (NextMenuOption) && IsSelectable (MenuOption) &&\r
+         (BottomRow - TopRow + 1 >= Difference + NextMenuOption->Skip + 1)) {\r
+        NewPos = SavedListEntry;\r
       }\r
 \r
+      UpdateStatusBar (INPUT_ERROR, FALSE);\r
+\r
       //\r
       // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.\r
       //\r
       AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
       AdjustDateAndTimePosition (TRUE, &NewPos);\r
+\r
+      UpdateHighlightMenuInfo(NewPos, TopOfScreen, SkipValue);\r
       break;\r
 \r
     case CfUiNoOperation:\r
@@ -3335,6 +3799,34 @@ UiDisplayMenu (
   }\r
 }\r
 \r
+/**\r
+  Free the UI Menu Option structure data.\r
+\r
+  @param   MenuOptionList         Point to the menu option list which need to be free.\r
+\r
+**/\r
+VOID\r
+FreeMenuOptionData(\r
+  LIST_ENTRY           *MenuOptionList\r
+  )\r
+{\r
+  LIST_ENTRY           *Link;\r
+  UI_MENU_OPTION       *Option;\r
+\r
+  //\r
+  // Free menu option list\r
+  //\r
+  while (!IsListEmpty (MenuOptionList)) {\r
+    Link = GetFirstNode (MenuOptionList);\r
+    Option = MENU_OPTION_FROM_LINK (Link);\r
+    if (Option->Description != NULL){\r
+      FreePool(Option->Description);\r
+    }\r
+    RemoveEntryList (&Option->Link);\r
+    FreePool (Option);\r
+  }\r
+}\r
+\r
 /**\r
 \r
   Base on the browser status info to show an pop up message.\r
@@ -3345,14 +3837,56 @@ BrowserStatusProcess (
   VOID\r
   )\r
 {\r
-  CHAR16         *ErrorInfo;\r
-  EFI_INPUT_KEY  Key;\r
+  CHAR16             *ErrorInfo;\r
+  EFI_INPUT_KEY      Key;\r
+  EFI_EVENT          WaitList[2];\r
+  EFI_EVENT          RefreshIntervalEvent;\r
+  EFI_EVENT          TimeOutEvent;\r
+  UINT8              TimeOut;\r
+  EFI_STATUS         Status;\r
+  UINTN              Index;\r
+  WARNING_IF_CONTEXT EventContext;\r
+  EFI_IFR_OP_HEADER  *OpCodeBuf;\r
+  EFI_STRING_ID      StringToken;\r
+  CHAR16             DiscardChange;\r
+  CHAR16             JumpToFormSet;\r
+  CHAR16             *PrintString;\r
 \r
   if (gFormData->BrowserStatus == BROWSER_SUCCESS) {\r
     return;\r
   }\r
 \r
-  if (gFormData->ErrorString != NULL) {\r
+  StringToken          = 0;\r
+  TimeOutEvent         = NULL;\r
+  RefreshIntervalEvent = NULL;\r
+  OpCodeBuf            = NULL;\r
+  if (gFormData->HighLightedStatement != NULL) {\r
+    OpCodeBuf = gFormData->HighLightedStatement->OpCode;\r
+  }\r
+\r
+  if (gFormData->BrowserStatus == (BROWSER_WARNING_IF)) {\r
+    ASSERT (OpCodeBuf != NULL && OpCodeBuf->OpCode == EFI_IFR_WARNING_IF_OP);\r
+\r
+    TimeOut     = ((EFI_IFR_WARNING_IF *) OpCodeBuf)->TimeOut;\r
+    StringToken = ((EFI_IFR_WARNING_IF *) OpCodeBuf)->Warning;\r
+  } else {\r
+    TimeOut = 0;\r
+    if ((gFormData->BrowserStatus == (BROWSER_NO_SUBMIT_IF)) &&\r
+        (OpCodeBuf != NULL && OpCodeBuf->OpCode == EFI_IFR_NO_SUBMIT_IF_OP)) {\r
+      StringToken = ((EFI_IFR_NO_SUBMIT_IF *) OpCodeBuf)->Error;\r
+    } else if ((gFormData->BrowserStatus == (BROWSER_INCONSISTENT_IF)) &&\r
+               (OpCodeBuf != NULL && OpCodeBuf->OpCode == EFI_IFR_INCONSISTENT_IF_OP)) {\r
+      StringToken = ((EFI_IFR_INCONSISTENT_IF *) OpCodeBuf)->Error;\r
+    }\r
+  }\r
+\r
+  if (StringToken != 0) {\r
+    ErrorInfo = GetToken (StringToken, gFormData->HiiHandle);\r
+  } else if (gFormData->ErrorString != NULL) {\r
+    //\r
+    // Only used to compatible with old setup browser.\r
+    // Not use this field in new browser core.\r
+    //\r
     ErrorInfo = gFormData->ErrorString;\r
   } else {\r
     switch (gFormData->BrowserStatus) {\r
@@ -3360,10 +3894,6 @@ BrowserStatusProcess (
       ErrorInfo = gSaveFailed;\r
       break;\r
 \r
-    case BROWSER_NO_SUBMIT_IF:\r
-      ErrorInfo = gNoSubmitIf;\r
-      break;\r
-\r
     case BROWSER_FORM_NOT_FOUND:\r
       ErrorInfo = gFormNotFound;\r
       break;\r
@@ -3376,33 +3906,131 @@ BrowserStatusProcess (
       ErrorInfo = gProtocolNotFound;\r
       break;\r
 \r
+    case BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF:\r
+      ErrorInfo = gNoSubmitIfFailed;\r
+      break;\r
+\r
+    case BROWSER_RECONNECT_FAIL:\r
+      ErrorInfo = gReconnectFail;\r
+      break;\r
+\r
+    case BROWSER_RECONNECT_SAVE_CHANGES:\r
+      ErrorInfo = gReconnectConfirmChanges;\r
+      break;\r
+\r
+    case BROWSER_RECONNECT_REQUIRED:\r
+      ErrorInfo = gReconnectRequired;\r
+      break;\r
+\r
     default:\r
-      ErrorInfo = gBrwoserError;\r
+      ErrorInfo = gBrowserError;\r
       break;\r
     }\r
   }\r
 \r
-  //\r
-  // Error occur, prompt error message.\r
-  //\r
-  do {\r
-    CreateDialog (&Key, gEmptyString, ErrorInfo, gPressEnter, gEmptyString, NULL);\r
-  } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+  switch (gFormData->BrowserStatus) {\r
+  case BROWSER_SUBMIT_FAIL:\r
+  case BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF:\r
+  case BROWSER_RECONNECT_SAVE_CHANGES:\r
+    ASSERT (gUserInput != NULL);\r
+    if (gFormData->BrowserStatus == (BROWSER_SUBMIT_FAIL)) {\r
+      PrintString = gSaveProcess;\r
+      JumpToFormSet = gJumpToFormSet[0];\r
+      DiscardChange = gDiscardChange[0];\r
+    } else if (gFormData->BrowserStatus == (BROWSER_RECONNECT_SAVE_CHANGES)){\r
+      PrintString = gChangesOpt;\r
+      JumpToFormSet = gConfirmOptYes[0];\r
+      DiscardChange = gConfirmOptNo[0];\r
+    } else {\r
+      PrintString = gSaveNoSubmitProcess;\r
+      JumpToFormSet = gCheckError[0];\r
+      DiscardChange = gDiscardChange[0];\r
+    }\r
+\r
+    do {\r
+      CreateDialog (&Key, gEmptyString, ErrorInfo, PrintString, gEmptyString, NULL);\r
+    } while (((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (DiscardChange | UPPER_LOWER_CASE_OFFSET)) &&\r
+             ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (JumpToFormSet | UPPER_LOWER_CASE_OFFSET)));\r
+\r
+    if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (DiscardChange | UPPER_LOWER_CASE_OFFSET)) {\r
+      gUserInput->Action = BROWSER_ACTION_DISCARD;\r
+    } else {\r
+      gUserInput->Action = BROWSER_ACTION_GOTO;\r
+    }\r
+    break;\r
+\r
+  default:\r
+    if (TimeOut == 0) {\r
+      do {\r
+        CreateDialog (&Key, gEmptyString, ErrorInfo, gPressEnter, gEmptyString, NULL);\r
+      } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+    } else {\r
+      Status = gBS->CreateEvent (EVT_NOTIFY_WAIT, TPL_CALLBACK, EmptyEventProcess, NULL, &TimeOutEvent);\r
+      ASSERT_EFI_ERROR (Status);\r
+\r
+      EventContext.SyncEvent = TimeOutEvent;\r
+      EventContext.TimeOut   = &TimeOut;\r
+      EventContext.ErrorInfo = ErrorInfo;\r
+\r
+      Status = gBS->CreateEvent (EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK, RefreshTimeOutProcess, &EventContext, &RefreshIntervalEvent);\r
+      ASSERT_EFI_ERROR (Status);\r
+\r
+      //\r
+      // Show the dialog first to avoid long time not reaction.\r
+      //\r
+      gBS->SignalEvent (RefreshIntervalEvent);\r
+\r
+      Status = gBS->SetTimer (RefreshIntervalEvent, TimerPeriodic, ONE_SECOND);\r
+      ASSERT_EFI_ERROR (Status);\r
+\r
+      while (TRUE) {\r
+        Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+        if (!EFI_ERROR (Status) && Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
+          break;\r
+        }\r
+\r
+        if (Status != EFI_NOT_READY) {\r
+          continue;\r
+        }\r
+\r
+        WaitList[0] = TimeOutEvent;\r
+        WaitList[1] = gST->ConIn->WaitForKey;\r
+\r
+        Status = gBS->WaitForEvent (2, WaitList, &Index);\r
+        ASSERT_EFI_ERROR (Status);\r
+\r
+        if (Index == 0) {\r
+          //\r
+          // Timeout occur, close the hoot time out event.\r
+          //\r
+          break;\r
+        }\r
+      }\r
+\r
+      gBS->CloseEvent (TimeOutEvent);\r
+      gBS->CloseEvent (RefreshIntervalEvent);\r
+    }\r
+    break;\r
+  }\r
+\r
+  if (StringToken != 0) {\r
+    FreePool (ErrorInfo);\r
+  }\r
 }\r
 \r
 /**\r
   Display one form, and return user input.\r
-  \r
+\r
   @param FormData                Form Data to be shown.\r
   @param UserInputData           User input data.\r
-  \r
+\r
   @retval EFI_SUCCESS            1.Form Data is shown, and user input is got.\r
                                  2.Error info has show and return.\r
   @retval EFI_INVALID_PARAMETER  The input screen dimension is not valid\r
   @retval EFI_NOT_FOUND          New form data has some error.\r
 **/\r
 EFI_STATUS\r
-EFIAPI \r
+EFIAPI\r
 FormDisplay (\r
   IN  FORM_DISPLAY_ENGINE_FORM  *FormData,\r
   OUT USER_INPUT                *UserInputData\r
@@ -3422,24 +4050,37 @@ FormDisplay (
   // Process the status info first.\r
   //\r
   BrowserStatusProcess();\r
-  if (UserInputData == NULL) {\r
+  if (gFormData->BrowserStatus != BROWSER_SUCCESS) {\r
     //\r
-    // UserInputData == NULL, means only need to print the error info, return here.\r
+    // gFormData->BrowserStatus != BROWSER_SUCCESS, means only need to print the error info, return here.\r
     //\r
     return EFI_SUCCESS;\r
   }\r
 \r
-  ConvertStatementToMenu();\r
-\r
   Status = DisplayPageFrame (FormData, &gStatementDimensions);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
 \r
+  //\r
+  // Global Widths should be initialized before any MenuOption creation\r
+  // or the GetWidth() used in UiAddMenuOption() will return incorrect value.\r
+  //\r
+  //\r
+  //  Left                                              right\r
+  //   |<-.->|<-.........->|<- .........->|<-...........->|\r
+  //     Skip    Prompt         Option         Help\r
+  //\r
+  gOptionBlockWidth = (CHAR16) ((gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn) / 3) + 1;\r
+  gHelpBlockWidth   = (CHAR16) (gOptionBlockWidth - 1 - LEFT_SKIPPED_COLUMNS);\r
+  gPromptBlockWidth = (CHAR16) (gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn - 2 * (gOptionBlockWidth - 1) - 1);\r
+\r
+  ConvertStatementToMenu();\r
+\r
   //\r
   // Check whether layout is changed.\r
   //\r
-  if (mIsFirstForm \r
+  if (mIsFirstForm\r
       || (gOldFormEntry.HiiHandle != FormData->HiiHandle)\r
       || (!CompareGuid (&gOldFormEntry.FormSetGuid, &FormData->FormSetGuid))\r
       || (gOldFormEntry.FormId != FormData->FormId)) {\r
@@ -3449,7 +4090,7 @@ FormDisplay (
   }\r
 \r
   Status = UiDisplayMenu(FormData);\r
-  \r
+\r
   //\r
   // Backup last form info.\r
   //\r
@@ -3458,6 +4099,11 @@ FormDisplay (
   CopyGuid (&gOldFormEntry.FormSetGuid, &FormData->FormSetGuid);\r
   gOldFormEntry.FormId    = FormData->FormId;\r
 \r
+  //\r
+  //Free the Ui menu option list.\r
+  //\r
+  FreeMenuOptionData(&gMenuOption);\r
+\r
   return Status;\r
 }\r
 \r
@@ -3465,7 +4111,7 @@ FormDisplay (
   Clear Screen to the initial state.\r
 **/\r
 VOID\r
-EFIAPI \r
+EFIAPI\r
 DriverClearDisplayPage (\r
   VOID\r
   )\r
@@ -3541,14 +4187,25 @@ InitializeDisplayEngine (
                   );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
+  //\r
+  // Install HII Popup Protocol.\r
+  //\r
+  Status = gBS->InstallProtocolInterface (\r
+                 &mPrivateData.Handle,\r
+                 &gEfiHiiPopupProtocolGuid,\r
+                 EFI_NATIVE_INTERFACE,\r
+                 &mPrivateData.HiiPopup\r
+                );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
   InitializeDisplayStrings();\r
-  \r
+\r
   ZeroMem (&gHighligthMenuInfo, sizeof (gHighligthMenuInfo));\r
   ZeroMem (&gOldFormEntry, sizeof (gOldFormEntry));\r
 \r
   //\r
   // Use BrowserEx2 protocol to register HotKey.\r
-  // \r
+  //\r
   Status = gBS->LocateProtocol (&gEdkiiFormBrowserEx2ProtocolGuid, NULL, (VOID **) &FormBrowserEx2);\r
   if (!EFI_ERROR (Status)) {\r
     //\r
@@ -3559,11 +4216,13 @@ InitializeDisplayEngine (
     NewString         = HiiGetString (gHiiHandle, STRING_TOKEN (FUNCTION_TEN_STRING), NULL);\r
     ASSERT (NewString != NULL);\r
     FormBrowserEx2->RegisterHotKey (&HotKey, BROWSER_ACTION_SUBMIT, 0, NewString);\r
+    FreePool (NewString);\r
 \r
     HotKey.ScanCode   = SCAN_F9;\r
     NewString         = HiiGetString (gHiiHandle, STRING_TOKEN (FUNCTION_NINE_STRING), NULL);\r
     ASSERT (NewString != NULL);\r
     FormBrowserEx2->RegisterHotKey (&HotKey, BROWSER_ACTION_DEFAULT, EFI_HII_DEFAULT_CLASS_STANDARD, NewString);\r
+    FreePool (NewString);\r
   }\r
 \r
   return EFI_SUCCESS;\r
@@ -3588,5 +4247,13 @@ UnloadDisplayEngine (
 \r
   FreeDisplayStrings ();\r
 \r
+  if (gHighligthMenuInfo.HLTOpCode != NULL) {\r
+    FreePool (gHighligthMenuInfo.HLTOpCode);\r
+  }\r
+\r
+  if (gHighligthMenuInfo.TOSOpCode != NULL) {\r
+    FreePool (gHighligthMenuInfo.TOSOpCode);\r
+  }\r
+\r
   return EFI_SUCCESS;\r
 }\r