]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c
MdeModulePkg:Fix the potential memory leak issue in Display Engine
[mirror_edk2.git] / MdeModulePkg / Universal / DisplayEngineDxe / FormDisplay.c
index 0db450e078d1f7a750730bcd4969c59a87715691..37cfcc591f9a17883cd50f90e1f2345859c2ea0e 100644 (file)
@@ -1,7 +1,7 @@
 /** @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 - 2016, 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
@@ -98,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
@@ -114,9 +113,13 @@ 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
@@ -136,7 +139,20 @@ 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            *gConfirmMsgConnect;\r
+CHAR16            *gConfirmMsgEnd;\r
 CHAR16            gModalSkipColumn;\r
 CHAR16            gPromptBlockWidth;\r
 CHAR16            gOptionBlockWidth;\r
@@ -191,9 +207,13 @@ 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
@@ -213,7 +233,21 @@ 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
+  gConfirmMsgConnect    = GetToken (STRING_TOKEN (CONFIRM_OPTION_CONNECT), gHiiHandle);\r
+  gConfirmMsgEnd        = GetToken (STRING_TOKEN (CONFIRM_OPTION_END), gHiiHandle);\r
 }\r
 \r
 /**\r
@@ -230,6 +264,10 @@ FreeDisplayStrings (
   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
@@ -246,9 +284,23 @@ 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 (gConfirmMsgConnect);\r
+  FreePool (gConfirmMsgEnd);\r
 }\r
 \r
 /**\r
@@ -552,7 +604,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
@@ -569,9 +620,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
@@ -581,7 +629,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
@@ -645,11 +693,11 @@ UiAddMenuOption (
       (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
@@ -1474,6 +1522,238 @@ 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
+  Find the Top of screen 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
+FindTopOfScreenMenuOption (\r
+ VOID\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
+  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
+    NewPos = NULL;\r
+  }\r
+\r
+  return NewPos;\r
+}\r
+\r
 /**\r
   Find the first menu which will be show at the top.\r
 \r
@@ -1491,160 +1771,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
-  //\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
-\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
+  // 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
-  NewPos = gMenuOption.ForwardLink;\r
-  SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);\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
-  while ((SavedMenuOption->ThisTag != FormData->HighLightedStatement) ||\r
-         (SavedMenuOption->Sequence != gSequence)) {\r
-    NewPos     = NewPos->ForwardLink;\r
-    if (NewPos == &gMenuOption) {\r
+    *HighlightMenu = FindHighLightMenuOption(NULL);\r
+    if (*HighlightMenu != NULL) {\r
       //\r
-      // Not Found it, break\r
+      // Update skip info for this highlight menu.\r
       //\r
-      break;\r
-    }\r
-    SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
-  }\r
-  ASSERT (SavedMenuOption->ThisTag == FormData->HighLightedStatement);\r
-\r
-  *HighlightMenu = NewPos;\r
+      MenuOption = MENU_OPTION_FROM_LINK (*HighlightMenu);\r
+      UpdateOptionSkipLines (MenuOption);\r
 \r
-  AdjustDateAndTimePosition(FALSE, &NewPos);\r
-  SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
-  UpdateOptionSkipLines (SavedMenuOption);\r
+      //\r
+      // Found the last time highlight menu.\r
+      //\r
+      *TopOfScreen = FindTopOfScreenMenuOption();\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
-  //\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
+        *SkipValue = gHighligthMenuInfo.SkipValue;\r
+      } else {\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
       }\r
-    } else if (gHighligthMenuInfo.OpCode != NULL){\r
-      if (!CompareMem (gHighligthMenuInfo.OpCode, SavedMenuOption->ThisTag->OpCode, gHighligthMenuInfo.OpCode->Length)) {\r
-        BottomRow = gHighligthMenuInfo.DisplayRow + SavedMenuOption->Skip;\r
+    } else {\r
+      //\r
+      // Last time highlight menu has disappear, find the first highlightable menu as the defalut 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();\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
-    }\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
-  if (SavedMenuOption->Skip >= BottomRow - TopRow) {\r
-    *TopOfScreen = NewPos;\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
-    *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
-  //\r
-  // Get the highlight statement.\r
-  //\r
-  gUserInput->SelectedStatement = Statement;\r
-  gSequence = (UINT16) MenuOption->Sequence;\r
+  if (!IsListEmpty (&gMenuOption)) {\r
+    MenuOption = MENU_OPTION_FROM_LINK (Highlight);\r
+    Statement  = MenuOption->ThisTag;\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
+    gUserInput->SelectedStatement = Statement;\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.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.OpCode = AllocateCopyPool (Statement->OpCode->Length, Statement->OpCode);\r
-      ASSERT (gHighligthMenuInfo.OpCode != NULL);\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
-    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
@@ -1777,6 +2127,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
@@ -1816,6 +2309,7 @@ DisplayOneMenu (
   UINTN                           Temp3;\r
   EFI_STATUS                      Status;\r
   UINTN                           Row;\r
+  BOOLEAN                         IsProcessingFirstRow;\r
   UINTN                           Col;\r
   UINTN                           PromptLineNum;\r
   UINTN                           OptionLineNum;\r
@@ -1830,6 +2324,7 @@ DisplayOneMenu (
   PromptLineNum = 0;\r
   OptionLineNum = 0;\r
   MaxRow        = 0;\r
+  IsProcessingFirstRow = TRUE;\r
 \r
   //\r
   // Set default color.\r
@@ -1933,7 +2428,7 @@ DisplayOneMenu (
         //\r
         PrintStringAtWithWidth (BeginCol, Row, L"", SkipWidth);\r
         \r
-        if (Statement->OpCode->OpCode == EFI_IFR_REF_OP && MenuOption->Col >= 2) {\r
+        if (Statement->OpCode->OpCode == EFI_IFR_REF_OP && MenuOption->Col >= 2 && IsProcessingFirstRow) {\r
           //\r
           // Print Arrow for Goto button.\r
           //\r
@@ -1942,6 +2437,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
@@ -2049,10 +2545,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
@@ -2069,10 +2565,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
@@ -2087,8 +2581,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
@@ -2098,7 +2592,6 @@ UiDisplayMenu (
   OptionString        = NULL;\r
   ScreenOperation     = UiNoOperation;\r
   NewLine             = TRUE;\r
-  DefaultId           = 0;\r
   HelpPageCount       = 0;\r
   HelpLine            = 0;\r
   RowCount            = 0;\r
@@ -2109,24 +2602,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
-  Width     = (UINT16)gOptionBlockWidth - 1;\r
   TopRow    = gStatementDimensions.TopRow    + SCROLL_ARROW_HEIGHT;\r
   BottomRow = gStatementDimensions.BottomRow - SCROLL_ARROW_HEIGHT - 1;\r
 \r
@@ -2138,6 +2627,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
@@ -2243,7 +2736,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
@@ -2306,10 +2803,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
@@ -2351,9 +2850,7 @@ 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
@@ -2392,10 +2889,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
@@ -2432,7 +2945,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
@@ -2588,6 +3101,7 @@ UiDisplayMenu (
       }\r
 \r
       if (EventType == UIEventDriver) {\r
+        gMisMatch = TRUE;\r
         gUserInput->Action = BROWSER_ACTION_NONE;\r
         ControlFlag = CfExit;\r
         break;\r
@@ -2795,13 +3309,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
@@ -2810,8 +3317,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
@@ -2914,6 +3432,8 @@ UiDisplayMenu (
       //\r
       AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
       AdjustDateAndTimePosition (TRUE, &NewPos);\r
+\r
+      UpdateHighlightMenuInfo(NewPos, TopOfScreen, SkipValue);\r
       break;\r
 \r
     case CfUiPageUp:\r
@@ -2953,6 +3473,8 @@ UiDisplayMenu (
       //\r
       AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
       AdjustDateAndTimePosition (TRUE, &NewPos);\r
+\r
+      UpdateHighlightMenuInfo(NewPos, TopOfScreen, SkipValue);\r
       break;\r
 \r
     case CfUiPageDown:\r
@@ -3014,6 +3536,8 @@ UiDisplayMenu (
       //\r
       AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
       AdjustDateAndTimePosition (TRUE, &NewPos);\r
+\r
+      UpdateHighlightMenuInfo(NewPos, TopOfScreen, SkipValue);\r
       break;\r
 \r
     case CfUiDown:\r
@@ -3075,6 +3599,8 @@ UiDisplayMenu (
         //\r
         AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
         AdjustDateAndTimePosition (TRUE, &NewPos);\r
+\r
+        UpdateHighlightMenuInfo(NewPos, TopOfScreen, SkipValue);\r
         break;\r
       }        \r
 \r
@@ -3172,6 +3698,8 @@ UiDisplayMenu (
       //\r
       AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
       AdjustDateAndTimePosition (TRUE, &NewPos);\r
+\r
+      UpdateHighlightMenuInfo(NewPos, TopOfScreen, SkipValue);\r
       break;\r
 \r
     case CfUiNoOperation:\r
@@ -3197,6 +3725,35 @@ 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
+\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
@@ -3280,8 +3837,20 @@ BrowserStatusProcess (
       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
@@ -3289,15 +3858,21 @@ BrowserStatusProcess (
   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
-    DiscardChange = gDiscardChange[0];\r
 \r
     do {\r
       CreateDialog (&Key, gEmptyString, ErrorInfo, PrintString, gEmptyString, NULL);\r
@@ -3451,6 +4026,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
@@ -3581,8 +4161,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