]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c
MdeModulePkg/DisplayEngineDxe: Fix small InitializeDisplayEngine leak
[mirror_edk2.git] / MdeModulePkg / Universal / DisplayEngineDxe / FormDisplay.c
index fe3d875cd994041776dd40ae970b059b017f6a91..7390f954b67f1ec13d41b3dea404964096356563 100644 (file)
@@ -1,7 +1,8 @@
 /** @file\r
 Entry and initialization module for the browser.\r
 \r
-Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2014, Hewlett-Packard Development Company, L.P.<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
@@ -48,7 +49,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 +87,7 @@ SCREEN_OPERATION_T0_CONTROL_FLAG  gScreenOperationToControlFlag[] = {
   {\r
     UiPageDown,\r
     CfUiPageDown\r
-  }, \r
+  },\r
   {\r
     UiHotKey,\r
     CfUiHotKey\r
@@ -97,8 +98,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 +113,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 +139,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 +176,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 +221,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 +247,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 +287,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 +308,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 +418,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 +462,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 +541,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 +571,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 +590,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 +604,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 +638,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 +654,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 +663,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 +705,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 +723,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 +741,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
@@ -807,7 +908,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
@@ -819,8 +920,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
@@ -944,8 +1045,8 @@ IsSelectable (
   @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 \r
-                   first menu showing beyond current form or last menu showing in \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
@@ -983,12 +1084,8 @@ MoveToNextStatement (
       UpdateOptionSkipLines (NextMenuOption);\r
     }\r
 \r
-    if (IsSelectable (NextMenuOption)) {\r
-      break;\r
-    }\r
-\r
     //\r
-    // In this case, still can't find the selectable menu,\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
@@ -998,6 +1095,13 @@ MoveToNextStatement (
       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
@@ -1022,10 +1126,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
@@ -1039,7 +1143,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
@@ -1048,7 +1152,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
@@ -1060,13 +1164,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
@@ -1078,21 +1182,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
@@ -1103,21 +1207,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
@@ -1200,7 +1304,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
@@ -1214,24 +1318,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
@@ -1242,7 +1346,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
@@ -1259,14 +1363,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
@@ -1336,13 +1440,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
@@ -1375,7 +1479,7 @@ UiWaitForEvent (
   if (Timeout != 0) {\r
     gBS->CloseEvent (TimerEvent);\r
   }\r
-  \r
+\r
   return EventType;\r
 }\r
 \r
@@ -1455,6 +1559,280 @@ FindTopOfScreenMenu (
   return TopOfScreen;\r
 }\r
 \r
+/**\r
+  Get the index info for this opcode.\r
+\r
+  @param  OpCode      The input opcode for the statement.\r
+\r
+  @retval  The index of this statement.\r
+\r
+**/\r
+UINTN\r
+GetIndexInfoForOpcode (\r
+  IN EFI_IFR_OP_HEADER  *OpCode\r
+  )\r
+{\r
+  LIST_ENTRY                      *NewPos;\r
+  UI_MENU_OPTION                  *MenuOption;\r
+  UINTN                           Index;\r
+\r
+  NewPos = gMenuOption.ForwardLink;\r
+  Index  = 0;\r
+\r
+  for (NewPos = gMenuOption.ForwardLink; NewPos != &gMenuOption; NewPos = NewPos->ForwardLink){\r
+    MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+\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
+  return Index;\r
+}\r
+\r
+/**\r
+  Is this the saved highlight statement.\r
+\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
+BOOLEAN\r
+IsSavedHighlightStatement (\r
+  IN FORM_DISPLAY_ENGINE_STATEMENT  *HighLightedStatement\r
+  )\r
+{\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
+      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
+  Is this the highlight menu.\r
+\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
+BOOLEAN\r
+IsHighLightMenuOption (\r
+  IN UI_MENU_OPTION     *MenuOption\r
+  )\r
+{\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
+  return FALSE;\r
+}\r
+\r
+/**\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
@@ -1472,160 +1850,230 @@ FindTopMenu (
   OUT UINTN                     *SkipValue\r
   )\r
 {\r
-  LIST_ENTRY                      *NewPos;\r
   UINTN                           TopRow;\r
   UINTN                           BottomRow;\r
-  UI_MENU_OPTION                  *SavedMenuOption;\r
+  UI_MENU_OPTION                  *MenuOption;\r
   UINTN                           TmpValue;\r
 \r
-  TmpValue  = 0;\r
   TopRow    = gStatementDimensions.TopRow    + SCROLL_ARROW_HEIGHT;\r
   BottomRow = gStatementDimensions.BottomRow - SCROLL_ARROW_HEIGHT;\r
-\r
   //\r
-  // If not has input highlight statement, just return the first one in this form.\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 (FormData->HighLightedStatement == NULL) {\r
-    *TopOfScreen   = gMenuOption.ForwardLink;\r
-    *HighlightMenu = gMenuOption.ForwardLink;\r
-    if (!IsListEmpty (&gMenuOption)) {\r
-      MoveToNextStatement (FALSE, HighlightMenu, BottomRow - TopRow, TRUE);\r
-    }\r
-    *SkipValue     = 0;\r
-    return;\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
-  //\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
+    *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
-  while ((SavedMenuOption->ThisTag != FormData->HighLightedStatement) ||\r
-         (SavedMenuOption->Sequence != gSequence)) {\r
-    NewPos     = NewPos->ForwardLink;\r
-    if (NewPos == &gMenuOption) {\r
       //\r
-      // Not Found it, break\r
+      // Found the last time highlight menu.\r
       //\r
-      break;\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
-    SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
-  }\r
-  ASSERT (SavedMenuOption->ThisTag == FormData->HighLightedStatement);\r
 \r
-  *HighlightMenu = NewPos;\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
-  AdjustDateAndTimePosition(FALSE, &NewPos);\r
-  SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
-  UpdateOptionSkipLines (SavedMenuOption);\r
+      //\r
+      // Update skip info for this highlight menu.\r
+      //\r
+      MenuOption = MENU_OPTION_FROM_LINK (*HighlightMenu);\r
+      UpdateOptionSkipLines (MenuOption);\r
 \r
-  //\r
-  // FormRefreshEvent != NULL means this form will auto exit at an interval, display engine \r
-  // will try to keep highlight on the current position after this form exit and re-enter.\r
-  //\r
-  // HiiHandle + QuestionId can find the only one question in the system.\r
-  //\r
-  // If this question has question id, save the question id info to find the question.\r
-  // else save the opcode buffer to find it.\r
-  //\r
-  if (gFormData->FormRefreshEvent != NULL && gFormData->HiiHandle == gHighligthMenuInfo.HiiHandle) {\r
-    if (gHighligthMenuInfo.QuestionId != 0) { \r
-      if (gHighligthMenuInfo.QuestionId == GetQuestionIdInfo(SavedMenuOption->ThisTag->OpCode)) {\r
-        BottomRow = gHighligthMenuInfo.DisplayRow + SavedMenuOption->Skip;\r
+      *TopOfScreen = FindTopOfScreenMenuOption(*HighlightMenu);\r
+      if (*TopOfScreen == NULL) {\r
         //\r
-        // SkipValue only used for menu at the top of the form.\r
-        // If Highlight menu is not at the top, this value will be update later.\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
-        TmpValue = gHighligthMenuInfo.SkipValue;\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
-    } else if (gHighligthMenuInfo.OpCode != NULL){\r
-      if (!CompareMem (gHighligthMenuInfo.OpCode, SavedMenuOption->ThisTag->OpCode, gHighligthMenuInfo.OpCode->Length)) {\r
-        BottomRow = gHighligthMenuInfo.DisplayRow + SavedMenuOption->Skip;\r
-        //\r
-        // SkipValue only used for menu at the top of the form.\r
-        // If Highlight menu is not at the top, this value will be update later.\r
-        //\r
-        TmpValue = gHighligthMenuInfo.SkipValue;\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
-  }\r
 \r
-  if (SavedMenuOption->Skip >= BottomRow - TopRow) {\r
-    *TopOfScreen = NewPos;\r
+      *SkipValue   = TmpValue;\r
+    }\r
+    AdjustDateAndTimePosition(TRUE, TopOfScreen);\r
   } else {\r
-    *TopOfScreen = FindTopOfScreenMenu(NewPos, BottomRow - TopRow - SavedMenuOption->Skip, &TmpValue);\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
-  AdjustDateAndTimePosition(TRUE, TopOfScreen);\r
 \r
-  *SkipValue   = TmpValue;\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
-  Update highlight menu info.\r
+  Record the highlight menu and top of screen menu info.\r
 \r
-  @param  MenuOption               The menu opton which is highlight.\r
-  @param  SkipValue                The skipvalue info for this menu.\r
-                                   SkipValue only used for the menu at the top of the form.\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 UI_MENU_OPTION            *MenuOption,\r
-  IN UINTN                     SkipValue\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
-  //\r
-  // This is the current selected statement\r
-  //\r
-  Statement = MenuOption->ThisTag;\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
-  //\r
-  // Get the highlight statement.\r
-  //\r
-  gUserInput->SelectedStatement = Statement;\r
-  gSequence = (UINT16) MenuOption->Sequence;\r
+      gHighligthMenuInfo.HLTIndex = GetIndexInfoForOpcode(Statement->OpCode);\r
+    }\r
 \r
-  //\r
-  // FormRefreshEvent != NULL means this form will auto exit at an interval, display engine \r
-  // will try to keep highlight on the current position after this form exit and re-enter.\r
-  //\r
-  // HiiHandle + QuestionId can find the only one question in the system.\r
-  //\r
-  // If this question has question id, base on the question id info to find the question.\r
-  // else base on the opcode buffer to find it.\r
-  //\r
-  if (gFormData->FormRefreshEvent != NULL) {\r
-    gHighligthMenuInfo.HiiHandle  = gFormData->HiiHandle;\r
-    gHighligthMenuInfo.QuestionId = GetQuestionIdInfo(Statement->OpCode);\r
+    MenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
+    Statement  = MenuOption->ThisTag;\r
 \r
-    //\r
-    // if question id == 0, save the opcode buffer for later use.\r
-    //\r
-    if (gHighligthMenuInfo.QuestionId == 0) {\r
-      if (gHighligthMenuInfo.OpCode != NULL) {\r
-        FreePool (gHighligthMenuInfo.OpCode);\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.OpCode = AllocateCopyPool (Statement->OpCode->Length, Statement->OpCode);\r
-      ASSERT (gHighligthMenuInfo.OpCode != NULL);\r
+      gHighligthMenuInfo.TOSOpCode = AllocateCopyPool (Statement->OpCode->Length, Statement->OpCode);\r
+      ASSERT (gHighligthMenuInfo.TOSOpCode != NULL);\r
+\r
+      gHighligthMenuInfo.TOSIndex = GetIndexInfoForOpcode(Statement->OpCode);\r
     }\r
-    gHighligthMenuInfo.DisplayRow = (UINT16) MenuOption->Row;\r
-    gHighligthMenuInfo.SkipValue  = (UINT16) SkipValue;\r
   } else {\r
-    gHighligthMenuInfo.HiiHandle  = NULL;\r
-    gHighligthMenuInfo.QuestionId = 0;\r
-    if (gHighligthMenuInfo.OpCode != NULL) {\r
-      FreePool (gHighligthMenuInfo.OpCode);\r
-      gHighligthMenuInfo.OpCode = NULL;\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.DisplayRow = 0;\r
-    gHighligthMenuInfo.SkipValue  = 0;\r
-  }\r
+    gHighligthMenuInfo.HLTOpCode     = NULL;\r
+    gHighligthMenuInfo.HLTIndex      = 0;\r
 \r
-  RefreshKeyHelp(gFormData, Statement, FALSE);\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
@@ -1642,7 +2090,7 @@ SetDisplayAttribute (
   )\r
 {\r
   FORM_DISPLAY_ENGINE_STATEMENT   *Statement;\r
-  \r
+\r
   Statement = MenuOption->ThisTag;\r
 \r
   if (Highlight) {\r
@@ -1692,11 +2140,11 @@ DisplayMenuString (
     PrintStringAtWithWidth (Col, Row, String, Width);\r
     return;\r
   }\r
-  \r
+\r
   //\r
   // Print the highlight menu string.\r
   // First print the highlight string.\r
-  // \r
+  //\r
   SetDisplayAttribute(MenuOption, TRUE);\r
   Length = PrintStringAt (Col, Row, String);\r
 \r
@@ -1716,7 +2164,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
@@ -1758,6 +2206,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
@@ -1765,7 +2356,7 @@ 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
@@ -1797,6 +2388,7 @@ DisplayOneMenu (
   UINTN                           Temp3;\r
   EFI_STATUS                      Status;\r
   UINTN                           Row;\r
+  BOOLEAN                         IsProcessingFirstRow;\r
   UINTN                           Col;\r
   UINTN                           PromptLineNum;\r
   UINTN                           OptionLineNum;\r
@@ -1811,6 +2403,7 @@ DisplayOneMenu (
   PromptLineNum = 0;\r
   OptionLineNum = 0;\r
   MaxRow        = 0;\r
+  IsProcessingFirstRow = TRUE;\r
 \r
   //\r
   // Set default color.\r
@@ -1832,12 +2425,12 @@ DisplayOneMenu (
       //\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
@@ -1855,7 +2448,7 @@ DisplayOneMenu (
           } else {\r
             //\r
             // For date/ time, print the first and second past (year for date and second for time)\r
-            // The OutputString has a NARROW_CHAR or WIDE_CHAR at the begin of the string, \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
@@ -1864,7 +2457,7 @@ DisplayOneMenu (
         }\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
@@ -1883,13 +2476,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
@@ -1907,14 +2500,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
@@ -1923,6 +2516,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
@@ -1951,13 +2545,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
@@ -1976,7 +2570,7 @@ DisplayOneMenu (
           }\r
         }\r
       }\r
-  \r
+\r
       FreePool (OutputString);\r
       if (Temp3 != 0) {\r
         Temp3--;\r
@@ -1995,7 +2589,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
@@ -2030,10 +2624,10 @@ UiDisplayMenu (
   UINTN                           TopRow;\r
   UINTN                           BottomRow;\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
@@ -2050,10 +2644,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
@@ -2068,8 +2660,8 @@ UiDisplayMenu (
   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
@@ -2079,7 +2671,6 @@ UiDisplayMenu (
   OptionString        = NULL;\r
   ScreenOperation     = UiNoOperation;\r
   NewLine             = TRUE;\r
-  DefaultId           = 0;\r
   HelpPageCount       = 0;\r
   HelpLine            = 0;\r
   RowCount            = 0;\r
@@ -2090,33 +2681,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
@@ -2128,6 +2706,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
@@ -2135,7 +2717,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
@@ -2164,7 +2746,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
@@ -2213,19 +2795,19 @@ 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
                             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
                             TRUE\r
@@ -2233,7 +2815,11 @@ UiDisplayMenu (
           }\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
@@ -2296,10 +2882,12 @@ UiDisplayMenu (
       //\r
       ControlFlag = CfUpdateHelpString;\r
 \r
+      UpdateHighlightMenuInfo(NewPos, TopOfScreen, SkipValue);\r
+\r
       if (SkipHighLight) {\r
-        MenuOption    = SavedMenuOption;\r
         SkipHighLight = FALSE;\r
-        UpdateHighlightMenuInfo (MenuOption, TopOfScreen == &MenuOption->Link ? SkipValue : 0);\r
+        MenuOption    = SavedMenuOption;\r
+        RefreshKeyHelp(gFormData, SavedMenuOption->ThisTag, FALSE);\r
         break;\r
       }\r
 \r
@@ -2327,10 +2915,10 @@ UiDisplayMenu (
           //\r
           // Remove the old highlight menu.\r
           //\r
-          Status = DisplayOneMenu (MenuOption, \r
+          Status = DisplayOneMenu (MenuOption,\r
                           MenuOption->Col - gStatementDimensions.LeftColumn,\r
-                          gStatementDimensions.LeftColumn, \r
-                          Temp, \r
+                          gStatementDimensions.LeftColumn,\r
+                          Temp,\r
                           BottomRow,\r
                           FALSE,\r
                           FALSE\r
@@ -2341,18 +2929,16 @@ UiDisplayMenu (
         // This is the current selected statement\r
         //\r
         MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
-        Statement = MenuOption->ThisTag;\r
-\r
-        UpdateHighlightMenuInfo (MenuOption, Temp2);\r
+        RefreshKeyHelp(gFormData, MenuOption->ThisTag, FALSE);\r
 \r
         if (!IsSelectable (MenuOption)) {\r
           break;\r
         }\r
 \r
-        Status = DisplayOneMenu (MenuOption, \r
+        Status = DisplayOneMenu (MenuOption,\r
                         MenuOption->Col - gStatementDimensions.LeftColumn,\r
-                        gStatementDimensions.LeftColumn, \r
-                        Temp2, \r
+                        gStatementDimensions.LeftColumn,\r
+                        Temp2,\r
                         BottomRow,\r
                         TRUE,\r
                         FALSE\r
@@ -2382,10 +2968,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
@@ -2422,7 +3024,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
@@ -2436,14 +3038,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
@@ -2491,7 +3093,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
@@ -2511,20 +3113,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
@@ -2569,7 +3171,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
@@ -2578,11 +3180,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
@@ -2626,7 +3229,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
@@ -2657,7 +3260,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
@@ -2691,7 +3294,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
@@ -2724,7 +3327,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
@@ -2756,11 +3359,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
@@ -2785,13 +3388,6 @@ 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
@@ -2800,8 +3396,19 @@ UiDisplayMenu (
       ControlFlag = CfRepaint;\r
 \r
       ASSERT (HotKey != NULL);\r
-      gUserInput->Action = HotKey->Action;\r
-      ControlFlag = CfExit;\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
@@ -2886,12 +3493,12 @@ UiDisplayMenu (
         // 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
+        // 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
+        //\r
+        if (!IsSelectable(NextMenuOption) && IsSelectable(MenuOption) &&\r
             (BottomRow - TopRow + 1 >= Difference + NextMenuOption->Skip + 1)) {\r
           NewPos = SavedListEntry;\r
         }\r
@@ -2904,6 +3511,8 @@ UiDisplayMenu (
       //\r
       AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
       AdjustDateAndTimePosition (TRUE, &NewPos);\r
+\r
+      UpdateHighlightMenuInfo(NewPos, TopOfScreen, SkipValue);\r
       break;\r
 \r
     case CfUiPageUp:\r
@@ -2930,11 +3539,11 @@ UiDisplayMenu (
       } else {\r
         Index     = (BottomRow + 1) - SkipValue - TopRow;\r
       }\r
-      \r
+\r
       TopOfScreen = FindTopOfScreenMenu(TopOfScreen, Index, &SkipValue);\r
       NewPos = TopOfScreen;\r
       MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow, FALSE);\r
-      \r
+\r
       UpdateStatusBar (INPUT_ERROR, FALSE);\r
 \r
       //\r
@@ -2943,6 +3552,8 @@ UiDisplayMenu (
       //\r
       AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
       AdjustDateAndTimePosition (TRUE, &NewPos);\r
+\r
+      UpdateHighlightMenuInfo(NewPos, TopOfScreen, SkipValue);\r
       break;\r
 \r
     case CfUiPageDown:\r
@@ -3004,6 +3615,8 @@ UiDisplayMenu (
       //\r
       AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
       AdjustDateAndTimePosition (TRUE, &NewPos);\r
+\r
+      UpdateHighlightMenuInfo(NewPos, TopOfScreen, SkipValue);\r
       break;\r
 \r
     case CfUiDown:\r
@@ -3049,7 +3662,7 @@ UiDisplayMenu (
         //\r
         // Scroll to the first page.\r
         //\r
-        if (TopOfScreen != gMenuOption.ForwardLink || SkipValue != 0) { \r
+        if (TopOfScreen != gMenuOption.ForwardLink || SkipValue != 0) {\r
           TopOfScreen = gMenuOption.ForwardLink;\r
           Repaint     = TRUE;\r
           MenuOption  = NULL;\r
@@ -3065,8 +3678,10 @@ UiDisplayMenu (
         //\r
         AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
         AdjustDateAndTimePosition (TRUE, &NewPos);\r
+\r
+        UpdateHighlightMenuInfo(NewPos, TopOfScreen, SkipValue);\r
         break;\r
-      }        \r
+      }\r
 \r
       //\r
       // Get next selected menu info.\r
@@ -3145,12 +3760,12 @@ UiDisplayMenu (
       // 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
+      // 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
+      //\r
+      if (!IsSelectable (NextMenuOption) && IsSelectable (MenuOption) &&\r
          (BottomRow - TopRow + 1 >= Difference + NextMenuOption->Skip + 1)) {\r
         NewPos = SavedListEntry;\r
       }\r
@@ -3162,6 +3777,8 @@ UiDisplayMenu (
       //\r
       AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
       AdjustDateAndTimePosition (TRUE, &NewPos);\r
+\r
+      UpdateHighlightMenuInfo(NewPos, TopOfScreen, SkipValue);\r
       break;\r
 \r
     case CfUiNoOperation:\r
@@ -3187,6 +3804,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
@@ -3197,14 +3842,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
@@ -3212,10 +3899,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
@@ -3228,33 +3911,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
@@ -3274,24 +4055,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
@@ -3301,7 +4095,7 @@ FormDisplay (
   }\r
 \r
   Status = UiDisplayMenu(FormData);\r
-  \r
+\r
   //\r
   // Backup last form info.\r
   //\r
@@ -3310,6 +4104,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
@@ -3317,7 +4116,7 @@ FormDisplay (
   Clear Screen to the initial state.\r
 **/\r
 VOID\r
-EFIAPI \r
+EFIAPI\r
 DriverClearDisplayPage (\r
   VOID\r
   )\r
@@ -3393,14 +4192,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
@@ -3411,11 +4221,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
@@ -3440,8 +4252,12 @@ UnloadDisplayEngine (
 \r
   FreeDisplayStrings ();\r
 \r
-  if (gHighligthMenuInfo.OpCode != NULL) {\r
-    FreePool (gHighligthMenuInfo.OpCode);\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