]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenance.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Library / BootMaintenanceManagerUiLib / BootMaintenance.c
index 745f9715540cd176e041f2b76669c25d86c13ef6..2167d3a5e8344b2d4f7bfada946c2523af143d2e 100644 (file)
@@ -1,14 +1,8 @@
 /** @file\r
 The functions for Boot Maintainence Main menu.\r
 \r
-Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution.  The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -30,6 +24,8 @@ UINT32    mBmmSetupTextModeRow            = 0;
 UINT32    mBmmSetupHorizontalResolution   = 0;\r
 UINT32    mBmmSetupVerticalResolution     = 0;\r
 \r
+BOOLEAN   mBmmModeInitialized             = FALSE;\r
+\r
 EFI_DEVICE_PATH_PROTOCOL  EndDevicePath[] = {\r
   {\r
     END_DEVICE_PATH_TYPE,\r
@@ -59,7 +55,7 @@ HII_VENDOR_DEVICE_PATH  mBmmHiiVendorDevicePath = {
   {\r
     END_DEVICE_PATH_TYPE,\r
     END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
-    { \r
+    {\r
       (UINT8) (END_DEVICE_PATH_LENGTH),\r
       (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)\r
     }\r
@@ -82,6 +78,7 @@ BMM_CALLBACK_DATA  gBootMaintenancePrivate = {
 \r
 BMM_CALLBACK_DATA *mBmmCallbackInfo = &gBootMaintenancePrivate;\r
 BOOLEAN  mAllMenuInit               = FALSE;\r
+BOOLEAN  mFirstEnterBMMForm         = FALSE;\r
 \r
 /**\r
   Init all memu.\r
@@ -103,19 +100,28 @@ FreeAllMenu (
   VOID\r
   );\r
 \r
+/**\r
+\r
+  Update the menus in the BMM page.\r
+\r
+**/\r
+VOID\r
+CustomizeMenus (\r
+  VOID\r
+  );\r
+\r
 /**\r
   This function will change video resolution and text mode\r
-  according to defined setup mode or defined boot mode  \r
+  according to defined setup mode or defined boot mode\r
 \r
-  @param  IsSetupMode   Indicate mode is changed to setup mode or boot mode. \r
+  @param  IsSetupMode   Indicate mode is changed to setup mode or boot mode.\r
 \r
   @retval  EFI_SUCCESS  Mode is changed successfully.\r
   @retval  Others       Mode failed to be changed.\r
 \r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
-BmmBdsSetConsoleMode (\r
+BmmSetConsoleMode (\r
   BOOLEAN  IsSetupMode\r
   )\r
 {\r
@@ -135,13 +141,13 @@ BmmBdsSetConsoleMode (
   EFI_STATUS                            Status;\r
   UINTN                                 Index;\r
   UINTN                                 CurrentColumn;\r
-  UINTN                                 CurrentRow;  \r
+  UINTN                                 CurrentRow;\r
 \r
   MaxGopMode  = 0;\r
   MaxTextMode = 0;\r
 \r
   //\r
-  // Get current video resolution and text mode \r
+  // Get current video resolution and text mode\r
   //\r
   Status = gBS->HandleProtocol (\r
                   gST->ConsoleOutHandle,\r
@@ -159,7 +165,7 @@ BmmBdsSetConsoleMode (
                   );\r
   if (EFI_ERROR (Status)) {\r
     SimpleTextOut = NULL;\r
-  }  \r
+  }\r
 \r
   if ((GraphicsOutput == NULL) || (SimpleTextOut == NULL)) {\r
     return EFI_UNSUPPORTED;\r
@@ -167,7 +173,7 @@ BmmBdsSetConsoleMode (
 \r
   if (IsSetupMode) {\r
     //\r
-    // The requried resolution and text mode is setup mode.\r
+    // The required resolution and text mode is setup mode.\r
     //\r
     NewHorizontalResolution = mBmmSetupHorizontalResolution;\r
     NewVerticalResolution   = mBmmSetupVerticalResolution;\r
@@ -180,12 +186,12 @@ BmmBdsSetConsoleMode (
     NewHorizontalResolution = mBmmBootHorizontalResolution;\r
     NewVerticalResolution   = mBmmBootVerticalResolution;\r
     NewColumns              = mBmmBootTextModeColumn;\r
-    NewRows                 = mBmmBootTextModeRow;   \r
+    NewRows                 = mBmmBootTextModeRow;\r
   }\r
 \r
   if (GraphicsOutput != NULL) {\r
     MaxGopMode  = GraphicsOutput->Mode->MaxMode;\r
-  } \r
+  }\r
 \r
   if (SimpleTextOut != NULL) {\r
     MaxTextMode = SimpleTextOut->Mode->MaxMode;\r
@@ -223,7 +229,7 @@ BmmBdsSetConsoleMode (
             return EFI_SUCCESS;\r
           } else {\r
             //\r
-            // If current text mode is different from requried text mode.  Set new video mode\r
+            // If current text mode is different from required text mode.  Set new video mode\r
             //\r
             for (Index = 0; Index < MaxTextMode; Index++) {\r
               Status = SimpleTextOut->QueryMode (SimpleTextOut, Index, &CurrentColumn, &CurrentRow);\r
@@ -248,7 +254,7 @@ BmmBdsSetConsoleMode (
             }\r
             if (Index == MaxTextMode) {\r
               //\r
-              // If requried text mode is not supported, return error.\r
+              // If required text mode is not supported, return error.\r
               //\r
               FreePool (Info);\r
               return EFI_UNSUPPORTED;\r
@@ -378,6 +384,7 @@ ExtractFileNameFromDevicePath (
   String = UiDevicePathToStr(DevicePath);\r
   MatchString = String;\r
   LastMatch   = String;\r
+  FileName    = NULL;\r
 \r
   while(MatchString != NULL){\r
     LastMatch   = MatchString + 1;\r
@@ -386,7 +393,9 @@ ExtractFileNameFromDevicePath (
 \r
   Length = StrLen(LastMatch);\r
   FileName = AllocateCopyPool ((Length + 1) * sizeof(CHAR16), LastMatch);\r
-  *(FileName + Length) = 0;\r
+  if (FileName != NULL) {\r
+    *(FileName + Length) = 0;\r
+  }\r
 \r
   FreePool(String);\r
 \r
@@ -428,6 +437,194 @@ BmmExtractDevicePathFromHiiHandle (
 \r
 }\r
 \r
+/**\r
+  Converts the unicode character of the string from uppercase to lowercase.\r
+  This is a internal function.\r
+\r
+  @param ConfigString  String to be converted\r
+\r
+**/\r
+VOID\r
+HiiToLower (\r
+  IN EFI_STRING  ConfigString\r
+  )\r
+{\r
+  EFI_STRING  String;\r
+  BOOLEAN     Lower;\r
+\r
+  ASSERT (ConfigString != NULL);\r
+\r
+  //\r
+  // Convert all hex digits in range [A-F] in the configuration header to [a-f]\r
+  //\r
+  for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {\r
+    if (*String == L'=') {\r
+      Lower = TRUE;\r
+    } else if (*String == L'&') {\r
+      Lower = FALSE;\r
+    } else if (Lower && *String >= L'A' && *String <= L'F') {\r
+      *String = (CHAR16) (*String - L'A' + L'a');\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  Update the progress string through the offset value.\r
+\r
+  @param Offset           The offset value\r
+  @param Configuration    Point to the configuration string.\r
+\r
+**/\r
+EFI_STRING\r
+UpdateProgress(\r
+  IN  UINTN       Offset,\r
+  IN  EFI_STRING  Configuration\r
+)\r
+{\r
+  UINTN       Length;\r
+  EFI_STRING  StringPtr;\r
+  EFI_STRING  ReturnString;\r
+\r
+  StringPtr    = NULL;\r
+  ReturnString = NULL;\r
+\r
+  //\r
+  // &OFFSET=XXXX followed by a Null-terminator.\r
+  // Length = StrLen (L"&OFFSET=") + 4 + 1\r
+  //\r
+  Length    = StrLen (L"&OFFSET=") + 4 + 1;\r
+\r
+  StringPtr = AllocateZeroPool (Length * sizeof (CHAR16));\r
+\r
+  if (StringPtr == NULL) {\r
+    return  NULL;\r
+  }\r
+\r
+  UnicodeSPrint (\r
+    StringPtr,\r
+    (8 + 4 + 1) * sizeof (CHAR16),\r
+    L"&OFFSET=%04x",\r
+    Offset\r
+    );\r
+\r
+  ReturnString = StrStr (Configuration, StringPtr);\r
+\r
+  if (ReturnString == NULL) {\r
+    //\r
+    // If doesn't find the string in Configuration, convert the string to lower case then search again.\r
+    //\r
+    HiiToLower (StringPtr);\r
+    ReturnString = StrStr (Configuration, StringPtr);\r
+  }\r
+\r
+  FreePool (StringPtr);\r
+\r
+  return ReturnString;\r
+}\r
+\r
+/**\r
+  Update the terminal content in TerminalMenu.\r
+\r
+  @param BmmData           The BMM fake NV data.\r
+\r
+**/\r
+VOID\r
+UpdateTerminalContent (\r
+  IN BMM_FAKE_NV_DATA       *BmmData\r
+  )\r
+{\r
+  UINT16                          Index;\r
+  BM_TERMINAL_CONTEXT             *NewTerminalContext;\r
+  BM_MENU_ENTRY                   *NewMenuEntry;\r
+\r
+  for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+    NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
+    ASSERT (NewMenuEntry != NULL);\r
+    NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+    NewTerminalContext->BaudRateIndex = BmmData->COMBaudRate[Index];\r
+    ASSERT (BmmData->COMBaudRate[Index] < (ARRAY_SIZE (BaudRateList)));\r
+    NewTerminalContext->BaudRate      = BaudRateList[BmmData->COMBaudRate[Index]].Value;\r
+    NewTerminalContext->DataBitsIndex = BmmData->COMDataRate[Index];\r
+    ASSERT (BmmData->COMDataRate[Index] < (ARRAY_SIZE (DataBitsList)));\r
+    NewTerminalContext->DataBits      = (UINT8) DataBitsList[BmmData->COMDataRate[Index]].Value;\r
+    NewTerminalContext->StopBitsIndex = BmmData->COMStopBits[Index];\r
+    ASSERT (BmmData->COMStopBits[Index] < (ARRAY_SIZE (StopBitsList)));\r
+    NewTerminalContext->StopBits      = (UINT8) StopBitsList[BmmData->COMStopBits[Index]].Value;\r
+    NewTerminalContext->ParityIndex   = BmmData->COMParity[Index];\r
+    ASSERT (BmmData->COMParity[Index] < (ARRAY_SIZE (ParityList)));\r
+    NewTerminalContext->Parity        = (UINT8) ParityList[BmmData->COMParity[Index]].Value;\r
+    NewTerminalContext->TerminalType  = BmmData->COMTerminalType[Index];\r
+    NewTerminalContext->FlowControl   = BmmData->COMFlowControl[Index];\r
+    ChangeTerminalDevicePath (\r
+      NewTerminalContext->DevicePath,\r
+      FALSE\r
+      );\r
+  }\r
+}\r
+\r
+/**\r
+  Update the console content in ConsoleMenu.\r
+\r
+  @param ConsoleName       The name for the console device type.\r
+  @param BmmData           The BMM fake NV data.\r
+\r
+**/\r
+VOID\r
+UpdateConsoleContent(\r
+  IN CHAR16                 *ConsoleName,\r
+  IN BMM_FAKE_NV_DATA       *BmmData\r
+  )\r
+{\r
+  UINT16                          Index;\r
+  BM_CONSOLE_CONTEXT              *NewConsoleContext;\r
+  BM_TERMINAL_CONTEXT             *NewTerminalContext;\r
+  BM_MENU_ENTRY                   *NewMenuEntry;\r
+\r
+  if (StrCmp (ConsoleName, L"ConIn") == 0) {\r
+    for (Index = 0; Index < ConsoleInpMenu.MenuNumber; Index++){\r
+      NewMenuEntry                = BOpt_GetMenuEntry(&ConsoleInpMenu, Index);\r
+      NewConsoleContext           = (BM_CONSOLE_CONTEXT *)NewMenuEntry->VariableContext;\r
+      ASSERT (Index < MAX_MENU_NUMBER);\r
+      NewConsoleContext->IsActive = BmmData->ConsoleInCheck[Index];\r
+    }\r
+    for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+      NewMenuEntry                = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
+      NewTerminalContext          = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+      ASSERT (Index + ConsoleInpMenu.MenuNumber < MAX_MENU_NUMBER);\r
+      NewTerminalContext->IsConIn = BmmData->ConsoleInCheck[Index + ConsoleInpMenu.MenuNumber];\r
+    }\r
+  }\r
+\r
+  if (StrCmp (ConsoleName, L"ConOut") == 0) {\r
+    for (Index = 0; Index < ConsoleOutMenu.MenuNumber; Index++){\r
+      NewMenuEntry                = BOpt_GetMenuEntry(&ConsoleOutMenu, Index);\r
+      NewConsoleContext           = (BM_CONSOLE_CONTEXT *)NewMenuEntry->VariableContext;\r
+      ASSERT (Index < MAX_MENU_NUMBER);\r
+      NewConsoleContext->IsActive = BmmData->ConsoleOutCheck[Index];\r
+    }\r
+    for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+      NewMenuEntry                = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
+      NewTerminalContext          = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+      ASSERT (Index + ConsoleOutMenu.MenuNumber < MAX_MENU_NUMBER);\r
+      NewTerminalContext->IsConOut = BmmData->ConsoleOutCheck[Index + ConsoleOutMenu.MenuNumber];\r
+    }\r
+  }\r
+  if (StrCmp (ConsoleName, L"ErrOut") == 0) {\r
+    for (Index = 0; Index < ConsoleErrMenu.MenuNumber; Index++){\r
+      NewMenuEntry                = BOpt_GetMenuEntry(&ConsoleErrMenu, Index);\r
+      NewConsoleContext           = (BM_CONSOLE_CONTEXT *)NewMenuEntry->VariableContext;\r
+      ASSERT (Index < MAX_MENU_NUMBER);\r
+      NewConsoleContext->IsActive = BmmData->ConsoleErrCheck[Index];\r
+    }\r
+    for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+      NewMenuEntry                = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
+      NewTerminalContext          = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+      ASSERT (Index + ConsoleErrMenu.MenuNumber < MAX_MENU_NUMBER);\r
+      NewTerminalContext->IsStdErr = BmmData->ConsoleErrCheck[Index + ConsoleErrMenu.MenuNumber];\r
+    }\r
+  }\r
+}\r
+\r
 /**\r
   This function allows a caller to extract the current configuration for one\r
   or more named elements from the target driver.\r
@@ -540,7 +737,7 @@ BootMaintExtractConfig (
 \r
   @param[in]  This                Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
   @param[in]  Configuration       A null-terminated Unicode string in\r
-                                  <ConfigString> format.   \r
+                                  <ConfigString> format.\r
   @param[out] Progress            A pointer to a string filled in with the\r
                                   offset of the most recent '&' before the\r
                                   first failing name / value pair (or the\r
@@ -550,7 +747,7 @@ BootMaintExtractConfig (
                                   successful.\r
 \r
   @retval EFI_SUCCESS             The results have been distributed or are\r
-                                  awaiting distribution.  \r
+                                  awaiting distribution.\r
   @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the\r
                                   parts of the results that must be\r
                                   stored awaiting possible future\r
@@ -574,13 +771,12 @@ BootMaintRouteConfig (
   EFI_HII_CONFIG_ROUTING_PROTOCOL *ConfigRouting;\r
   BMM_FAKE_NV_DATA                *NewBmmData;\r
   BMM_FAKE_NV_DATA                *OldBmmData;\r
-  BM_CONSOLE_CONTEXT              *NewConsoleContext;\r
-  BM_TERMINAL_CONTEXT             *NewTerminalContext;\r
   BM_MENU_ENTRY                   *NewMenuEntry;\r
   BM_LOAD_CONTEXT                 *NewLoadContext;\r
   UINT16                          Index;\r
   BOOLEAN                         TerminalAttChange;\r
-  BMM_CALLBACK_DATA               *Private; \r
+  BMM_CALLBACK_DATA               *Private;\r
+  UINTN                           Offset;\r
 \r
   if (Progress == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -600,21 +796,22 @@ BootMaintRouteConfig (
   }\r
 \r
   Status = gBS->LocateProtocol (\r
-                  &gEfiHiiConfigRoutingProtocolGuid, \r
-                  NULL, \r
+                  &gEfiHiiConfigRoutingProtocolGuid,\r
+                  NULL,\r
                   (VOID **)&ConfigRouting\r
                   );\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
 \r
-  Private = BMM_CALLBACK_DATA_FROM_THIS (This);  \r
+  Private = BMM_CALLBACK_DATA_FROM_THIS (This);\r
   //\r
   // Get Buffer Storage data from EFI variable\r
   //\r
   BufferSize = sizeof (BMM_FAKE_NV_DATA);\r
   OldBmmData = &Private->BmmOldFakeNVData;\r
   NewBmmData = &Private->BmmFakeNvData;\r
+  Offset     = 0;\r
   //\r
   // Convert <ConfigResp> to buffer data by helper function ConfigToBlock()\r
   //\r
@@ -625,25 +822,29 @@ BootMaintRouteConfig (
                             &BufferSize,\r
                             Progress\r
                             );\r
-  ASSERT_EFI_ERROR (Status);    \r
+  ASSERT_EFI_ERROR (Status);\r
   //\r
-  // Compare new and old BMM configuration data and only do action for modified item to \r
+  // Compare new and old BMM configuration data and only do action for modified item to\r
   // avoid setting unnecessary non-volatile variable\r
   //\r
 \r
   //\r
   // Check data which located in BMM main page and save the settings if need\r
-  //         \r
+  //\r
   if (CompareMem (&NewBmmData->BootNext, &OldBmmData->BootNext, sizeof (NewBmmData->BootNext)) != 0) {\r
     Status = Var_UpdateBootNext (Private);\r
+    if (EFI_ERROR (Status)) {\r
+      Offset = OFFSET_OF (BMM_FAKE_NV_DATA, BootNext);\r
+      goto Exit;\r
+    }\r
   }\r
 \r
   //\r
   // Check data which located in Boot Options Menu and save the settings if need\r
-  //      \r
-  if (CompareMem (NewBmmData->BootOptionDel, OldBmmData->BootOptionDel, sizeof (NewBmmData->BootOptionDel)) != 0) {  \r
-    for (Index = 0; \r
-         ((Index < BootOptionMenu.MenuNumber) && (Index < (sizeof (NewBmmData->BootOptionDel) / sizeof (NewBmmData->BootOptionDel[0])))); \r
+  //\r
+  if (CompareMem (NewBmmData->BootOptionDel, OldBmmData->BootOptionDel, sizeof (NewBmmData->BootOptionDel)) != 0) {\r
+    for (Index = 0;\r
+         ((Index < BootOptionMenu.MenuNumber) && (Index < (sizeof (NewBmmData->BootOptionDel) / sizeof (NewBmmData->BootOptionDel[0]))));\r
          Index ++) {\r
       NewMenuEntry            = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
       NewLoadContext          = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
@@ -652,11 +853,19 @@ BootMaintRouteConfig (
       NewBmmData->BootOptionDelMark[Index] = FALSE;\r
     }\r
 \r
-    Var_DelBootOption ();\r
+    Status = Var_DelBootOption ();\r
+    if (EFI_ERROR (Status)) {\r
+      Offset = OFFSET_OF (BMM_FAKE_NV_DATA, BootOptionDel);\r
+      goto Exit;\r
+    }\r
   }\r
 \r
   if (CompareMem (NewBmmData->BootOptionOrder, OldBmmData->BootOptionOrder, sizeof (NewBmmData->BootOptionOrder)) != 0) {\r
     Status = Var_UpdateBootOrder (Private);\r
+    if (EFI_ERROR (Status)) {\r
+      Offset = OFFSET_OF (BMM_FAKE_NV_DATA, BootOptionOrder);\r
+      goto Exit;\r
+    }\r
   }\r
 \r
   if (CompareMem (&NewBmmData->BootTimeOut, &OldBmmData->BootTimeOut, sizeof (NewBmmData->BootTimeOut)) != 0){\r
@@ -668,25 +877,18 @@ BootMaintRouteConfig (
                     &(NewBmmData->BootTimeOut)\r
                     );\r
     if (EFI_ERROR (Status)) {\r
-      //\r
-      // If set variable fail, and don't have the appropriate error status for RouteConfig fuction to return,\r
-      // just return the EFI_NOT_FOUND.\r
-      //\r
-      if (Status == EFI_OUT_OF_RESOURCES) {\r
-        return Status;\r
-      } else {\r
-        return EFI_NOT_FOUND;\r
-      }\r
+      Offset = OFFSET_OF (BMM_FAKE_NV_DATA, BootTimeOut);\r
+      goto Exit;\r
     }\r
     Private->BmmOldFakeNVData.BootTimeOut = NewBmmData->BootTimeOut;\r
   }\r
 \r
   //\r
   // Check data which located in Driver Options Menu and save the settings if need\r
-  //              \r
-  if (CompareMem (NewBmmData->DriverOptionDel, OldBmmData->DriverOptionDel, sizeof (NewBmmData->DriverOptionDel)) != 0) {       \r
-    for (Index = 0; \r
-         ((Index < DriverOptionMenu.MenuNumber) && (Index < (sizeof (NewBmmData->DriverOptionDel) / sizeof (NewBmmData->DriverOptionDel[0])))); \r
+  //\r
+  if (CompareMem (NewBmmData->DriverOptionDel, OldBmmData->DriverOptionDel, sizeof (NewBmmData->DriverOptionDel)) != 0) {\r
+    for (Index = 0;\r
+         ((Index < DriverOptionMenu.MenuNumber) && (Index < (sizeof (NewBmmData->DriverOptionDel) / sizeof (NewBmmData->DriverOptionDel[0]))));\r
          Index++) {\r
       NewMenuEntry            = BOpt_GetMenuEntry (&DriverOptionMenu, Index);\r
       NewLoadContext          = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
@@ -694,15 +896,27 @@ BootMaintRouteConfig (
       NewBmmData->DriverOptionDel[Index] = FALSE;\r
       NewBmmData->DriverOptionDelMark[Index] = FALSE;\r
     }\r
-    Var_DelDriverOption ();  \r
+    Status = Var_DelDriverOption ();\r
+    if (EFI_ERROR (Status)) {\r
+      Offset = OFFSET_OF (BMM_FAKE_NV_DATA, DriverOptionDel);\r
+      goto Exit;\r
+    }\r
   }\r
 \r
-  if (CompareMem (NewBmmData->DriverOptionOrder, OldBmmData->DriverOptionOrder, sizeof (NewBmmData->DriverOptionOrder)) != 0) {  \r
+  if (CompareMem (NewBmmData->DriverOptionOrder, OldBmmData->DriverOptionOrder, sizeof (NewBmmData->DriverOptionOrder)) != 0) {\r
     Status = Var_UpdateDriverOrder (Private);\r
+    if (EFI_ERROR (Status)) {\r
+      Offset = OFFSET_OF (BMM_FAKE_NV_DATA, DriverOptionOrder);\r
+      goto Exit;\r
+    }\r
   }\r
 \r
   if (CompareMem (&NewBmmData->ConsoleOutMode, &OldBmmData->ConsoleOutMode, sizeof (NewBmmData->ConsoleOutMode)) != 0){\r
-    Var_UpdateConMode(Private);\r
+    Status = Var_UpdateConMode(Private);\r
+    if (EFI_ERROR (Status)) {\r
+      Offset = OFFSET_OF (BMM_FAKE_NV_DATA, ConsoleOutMode);\r
+      goto Exit;\r
+    }\r
   }\r
 \r
   TerminalAttChange = FALSE;\r
@@ -720,83 +934,60 @@ BootMaintRouteConfig (
       continue;\r
     }\r
 \r
-    NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
-    ASSERT (NewMenuEntry != NULL);\r
-    NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
-    NewTerminalContext->BaudRateIndex = NewBmmData->COMBaudRate[Index];\r
-    ASSERT (NewBmmData->COMBaudRate[Index] < (sizeof (BaudRateList) / sizeof (BaudRateList[0])));\r
-    NewTerminalContext->BaudRate      = BaudRateList[NewBmmData->COMBaudRate[Index]].Value;\r
-    NewTerminalContext->DataBitsIndex = NewBmmData->COMDataRate[Index];\r
-    ASSERT (NewBmmData->COMDataRate[Index] < (sizeof (DataBitsList) / sizeof (DataBitsList[0])));\r
-    NewTerminalContext->DataBits      = (UINT8) DataBitsList[NewBmmData->COMDataRate[Index]].Value;\r
-    NewTerminalContext->StopBitsIndex = NewBmmData->COMStopBits[Index];\r
-    ASSERT (NewBmmData->COMStopBits[Index] < (sizeof (StopBitsList) / sizeof (StopBitsList[0])));\r
-    NewTerminalContext->StopBits      = (UINT8) StopBitsList[NewBmmData->COMStopBits[Index]].Value;\r
-    NewTerminalContext->ParityIndex   = NewBmmData->COMParity[Index];\r
-    ASSERT (NewBmmData->COMParity[Index] < (sizeof (ParityList) / sizeof (ParityList[0])));\r
-    NewTerminalContext->Parity        = (UINT8) ParityList[NewBmmData->COMParity[Index]].Value;\r
-    NewTerminalContext->TerminalType  = NewBmmData->COMTerminalType[Index];\r
-    NewTerminalContext->FlowControl   = NewBmmData->COMFlowControl[Index];\r
-    ChangeTerminalDevicePath (\r
-      NewTerminalContext->DevicePath,\r
-      FALSE\r
-      );\r
     TerminalAttChange = TRUE;\r
   }\r
   if (TerminalAttChange) {\r
-    Var_UpdateConsoleInpOption ();\r
-    Var_UpdateConsoleOutOption ();\r
-    Var_UpdateErrorOutOption ();\r
+    if (CompareMem (&NewBmmData->COMBaudRate[Index], &OldBmmData->COMBaudRate[Index], sizeof (NewBmmData->COMBaudRate[Index])) != 0) {\r
+      Offset = OFFSET_OF (BMM_FAKE_NV_DATA, COMBaudRate);\r
+    } else if (CompareMem (&NewBmmData->COMDataRate[Index], &OldBmmData->COMDataRate[Index], sizeof (NewBmmData->COMDataRate[Index])) != 0) {\r
+      Offset = OFFSET_OF (BMM_FAKE_NV_DATA, COMDataRate);\r
+    } else if (CompareMem (&NewBmmData->COMStopBits[Index], &OldBmmData->COMStopBits[Index], sizeof (NewBmmData->COMStopBits[Index])) != 0) {\r
+      Offset = OFFSET_OF (BMM_FAKE_NV_DATA, COMStopBits);\r
+    } else if (CompareMem (&NewBmmData->COMParity[Index], &OldBmmData->COMParity[Index], sizeof (NewBmmData->COMParity[Index])) != 0) {\r
+      Offset = OFFSET_OF (BMM_FAKE_NV_DATA, COMParity);\r
+    } else if (CompareMem (&NewBmmData->COMTerminalType[Index], &OldBmmData->COMTerminalType[Index], sizeof (NewBmmData->COMTerminalType[Index])) != 0) {\r
+      Offset = OFFSET_OF (BMM_FAKE_NV_DATA, COMTerminalType);\r
+    } else if (CompareMem (&NewBmmData->COMFlowControl[Index], &OldBmmData->COMFlowControl[Index], sizeof (NewBmmData->COMFlowControl[Index])) != 0) {\r
+      Offset = OFFSET_OF (BMM_FAKE_NV_DATA, COMFlowControl);\r
+    }\r
+    Status = Var_UpdateConsoleInpOption ();\r
+    if (EFI_ERROR (Status)) {\r
+      goto Exit;\r
+    }\r
+    Status = Var_UpdateConsoleOutOption ();\r
+    if (EFI_ERROR (Status)) {\r
+      goto Exit;\r
+    }\r
+    Status = Var_UpdateErrorOutOption ();\r
+    if (EFI_ERROR (Status)) {\r
+      goto Exit;\r
+    }\r
   }\r
   //\r
   // Check data which located in Console Options Menu and save the settings if need\r
   //\r
   if (CompareMem (NewBmmData->ConsoleInCheck, OldBmmData->ConsoleInCheck, sizeof (NewBmmData->ConsoleInCheck)) != 0){\r
-    for (Index = 0; Index < ConsoleInpMenu.MenuNumber; Index++){\r
-      NewMenuEntry                = BOpt_GetMenuEntry(&ConsoleInpMenu, Index);\r
-      NewConsoleContext           = (BM_CONSOLE_CONTEXT *)NewMenuEntry->VariableContext;\r
-      ASSERT (Index < MAX_MENU_NUMBER);\r
-      NewConsoleContext->IsActive = NewBmmData->ConsoleInCheck[Index];\r
-    }\r
-    for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
-      NewMenuEntry                = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
-      NewTerminalContext          = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
-      ASSERT (Index + ConsoleInpMenu.MenuNumber < MAX_MENU_NUMBER);\r
-      NewTerminalContext->IsConIn = NewBmmData->ConsoleInCheck[Index + ConsoleInpMenu.MenuNumber];\r
+    Status = Var_UpdateConsoleInpOption();\r
+    if (EFI_ERROR (Status)) {\r
+      Offset = OFFSET_OF (BMM_FAKE_NV_DATA, ConsoleInCheck);\r
+      goto Exit;\r
     }\r
-    Var_UpdateConsoleInpOption();\r
   }\r
 \r
   if (CompareMem (NewBmmData->ConsoleOutCheck, OldBmmData->ConsoleOutCheck, sizeof (NewBmmData->ConsoleOutCheck)) != 0){\r
-    for (Index = 0; Index < ConsoleOutMenu.MenuNumber; Index++){\r
-      NewMenuEntry                = BOpt_GetMenuEntry(&ConsoleOutMenu, Index);\r
-      NewConsoleContext           = (BM_CONSOLE_CONTEXT *)NewMenuEntry->VariableContext;\r
-      ASSERT (Index < MAX_MENU_NUMBER);\r
-      NewConsoleContext->IsActive = NewBmmData->ConsoleOutCheck[Index];\r
-    }\r
-    for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
-      NewMenuEntry                = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
-      NewTerminalContext          = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
-      ASSERT (Index + ConsoleOutMenu.MenuNumber < MAX_MENU_NUMBER);\r
-      NewTerminalContext->IsConOut = NewBmmData->ConsoleOutCheck[Index + ConsoleOutMenu.MenuNumber];\r
+    Status = Var_UpdateConsoleOutOption();\r
+    if (EFI_ERROR (Status)) {\r
+      Offset = OFFSET_OF (BMM_FAKE_NV_DATA, ConsoleOutCheck);\r
+      goto Exit;\r
     }\r
-    Var_UpdateConsoleOutOption();\r
   }\r
 \r
   if (CompareMem (NewBmmData->ConsoleErrCheck, OldBmmData->ConsoleErrCheck, sizeof (NewBmmData->ConsoleErrCheck)) != 0){\r
-    for (Index = 0; Index < ConsoleErrMenu.MenuNumber; Index++){\r
-      NewMenuEntry                = BOpt_GetMenuEntry(&ConsoleErrMenu, Index);\r
-      NewConsoleContext           = (BM_CONSOLE_CONTEXT *)NewMenuEntry->VariableContext;\r
-      ASSERT (Index < MAX_MENU_NUMBER);\r
-      NewConsoleContext->IsActive = NewBmmData->ConsoleErrCheck[Index];\r
-    }\r
-    for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
-      NewMenuEntry                = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
-      NewTerminalContext          = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
-      ASSERT (Index + ConsoleErrMenu.MenuNumber < MAX_MENU_NUMBER);\r
-      NewTerminalContext->IsStdErr = NewBmmData->ConsoleErrCheck[Index + ConsoleErrMenu.MenuNumber];\r
+    Status = Var_UpdateErrorOutOption();\r
+    if (EFI_ERROR (Status)) {\r
+      Offset = OFFSET_OF (BMM_FAKE_NV_DATA, ConsoleErrCheck);\r
+      goto Exit;\r
     }\r
-    Var_UpdateErrorOutOption();\r
   }\r
 \r
   if (CompareMem (NewBmmData->BootDescriptionData, OldBmmData->BootDescriptionData, sizeof (NewBmmData->BootDescriptionData)) != 0 ||\r
@@ -804,7 +995,12 @@ BootMaintRouteConfig (
     Status = Var_UpdateBootOption (Private);\r
     NewBmmData->BootOptionChanged = FALSE;\r
     if (EFI_ERROR (Status)) {\r
-      return Status;\r
+      if (CompareMem (NewBmmData->BootDescriptionData, OldBmmData->BootDescriptionData, sizeof (NewBmmData->BootDescriptionData)) != 0) {\r
+        Offset = OFFSET_OF (BMM_FAKE_NV_DATA, BootDescriptionData);\r
+      } else {\r
+        Offset = OFFSET_OF (BMM_FAKE_NV_DATA, BootOptionalData);\r
+      }\r
+      goto Exit;\r
     }\r
     BOpt_GetBootOptions (Private);\r
   }\r
@@ -821,7 +1017,12 @@ BootMaintRouteConfig (
     NewBmmData->DriverOptionChanged = FALSE;\r
     NewBmmData->ForceReconnect      = TRUE;\r
     if (EFI_ERROR (Status)) {\r
-      return Status;\r
+      if (CompareMem (NewBmmData->DriverDescriptionData, OldBmmData->DriverDescriptionData, sizeof (NewBmmData->DriverDescriptionData)) != 0) {\r
+        Offset = OFFSET_OF (BMM_FAKE_NV_DATA, DriverDescriptionData);\r
+      } else {\r
+        Offset = OFFSET_OF (BMM_FAKE_NV_DATA, DriverOptionalData);\r
+      }\r
+      goto Exit;\r
     }\r
 \r
     BOpt_GetDriverOptions (Private);\r
@@ -833,6 +1034,17 @@ BootMaintRouteConfig (
   CopyMem (OldBmmData, NewBmmData, sizeof (BMM_FAKE_NV_DATA));\r
 \r
   return EFI_SUCCESS;\r
+\r
+Exit:\r
+  //\r
+  // Fail to save the data, update the progress string.\r
+  //\r
+  *Progress = UpdateProgress (Offset, Configuration);\r
+  if (Status == EFI_OUT_OF_RESOURCES) {\r
+    return Status;\r
+  } else {\r
+    return EFI_NOT_FOUND;\r
+  }\r
 }\r
 \r
 /**\r
@@ -867,47 +1079,63 @@ BootMaintCallback (
   BMM_CALLBACK_DATA *Private;\r
   BM_MENU_ENTRY     *NewMenuEntry;\r
   BMM_FAKE_NV_DATA  *CurrentFakeNVMap;\r
-  UINTN             OldValue;\r
-  UINTN             NewValue;\r
-  UINTN             Number;\r
+  BMM_FAKE_NV_DATA  *OldFakeNVMap;\r
   UINTN             Index;\r
   EFI_DEVICE_PATH_PROTOCOL * File;\r
 \r
-  if (Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_CHANGED) {\r
+  if (Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_CHANGED && Action != EFI_BROWSER_ACTION_FORM_OPEN) {\r
     //\r
-    // Do nothing for other UEFI Action. Only do call back when data is changed.\r
+    // Do nothing for other UEFI Action. Only do call back when data is changed or the form is open.\r
     //\r
     return EFI_UNSUPPORTED;\r
   }\r
-  OldValue       = 0;\r
-  NewValue       = 0;\r
-  Number         = 0;\r
 \r
   Private        = BMM_CALLBACK_DATA_FROM_THIS (This);\r
+\r
+  if (Action == EFI_BROWSER_ACTION_FORM_OPEN) {\r
+    if (QuestionId == KEY_VALUE_TRIGGER_FORM_OPEN_ACTION) {\r
+      if (!mFirstEnterBMMForm) {\r
+        //\r
+        // BMMUiLib depends on LegacyUi library to show legacy menus.\r
+        // If we want to show Legacy menus correctly in BMM page,\r
+        // we must do it after the LegacyUi library has already been initialized.\r
+        // Opening the BMM form is the appropriate time that the LegacyUi library has already been initialized.\r
+        // So we do the tasks which are related to legacy menus here.\r
+        // 1. Update the menus (including legacy munu) show in BootMiantenanceManager page.\r
+        // 2. Re-scan the BootOption menus (including the legacy boot option).\r
+        //\r
+        CustomizeMenus ();\r
+        EfiBootManagerRefreshAllBootOption ();\r
+        BOpt_GetBootOptions (Private);\r
+        mFirstEnterBMMForm = TRUE;\r
+      }\r
+    }\r
+  }\r
   //\r
-  // Retrive uncommitted data from Form Browser\r
+  // Retrieve uncommitted data from Form Browser\r
   //\r
   CurrentFakeNVMap = &Private->BmmFakeNvData;\r
+  OldFakeNVMap     = &Private->BmmOldFakeNVData;\r
   HiiGetBrowserData (&mBootMaintGuid, mBootMaintStorageName, sizeof (BMM_FAKE_NV_DATA), (UINT8 *) CurrentFakeNVMap);\r
 \r
   if (Action == EFI_BROWSER_ACTION_CHANGING) {\r
     if (Value == NULL) {\r
       return EFI_INVALID_PARAMETER;\r
     }\r
-    \r
+\r
     UpdatePageId (Private, QuestionId);\r
 \r
     if (QuestionId < FILE_OPTION_OFFSET) {\r
       if (QuestionId < CONFIG_OPTION_OFFSET) {\r
         switch (QuestionId) {\r
         case FORM_BOOT_ADD_ID:\r
-          // Leave BMM and enter FileExplorer. \r
-          ChooseFile( NULL, L".efi", (CHOOSE_HANDLER) CreateBootOptionFromFile, &File);\r
+          // Leave BMM and enter FileExplorer.\r
+          ChooseFile (NULL, L".efi", CreateBootOptionFromFile, &File);\r
           break;\r
 \r
         case FORM_DRV_ADD_FILE_ID:\r
           // Leave BMM and enter FileExplorer.\r
-          ChooseFile( NULL, L".efi", (CHOOSE_HANDLER) CreateDriverOptionFromFile, &File);\r
+          ChooseFile (NULL, L".efi", CreateDriverOptionFromFile, &File);\r
           break;\r
 \r
         case FORM_DRV_ADD_HANDLE_ID:\r
@@ -930,16 +1158,6 @@ BootMaintCallback (
           UpdateDrvDelPage (Private);\r
           break;\r
 \r
-        case FORM_BOOT_NEXT_ID:\r
-          CleanUpPage (FORM_BOOT_NEXT_ID, Private);\r
-          UpdateBootNextPage (Private);\r
-          break;\r
-\r
-        case FORM_TIME_OUT_ID:\r
-          CleanUpPage (FORM_TIME_OUT_ID, Private);\r
-          UpdateTimeOutPage (Private);\r
-          break;\r
-\r
         case FORM_CON_IN_ID:\r
         case FORM_CON_OUT_ID:\r
         case FORM_CON_ERR_ID:\r
@@ -983,25 +1201,29 @@ BootMaintCallback (
     }\r
     if (QuestionId == KEY_VALUE_BOOT_FROM_FILE){\r
       // Leave BMM and enter FileExplorer.\r
-      ChooseFile( NULL, L".efi", (CHOOSE_HANDLER) BootFromFile, &File);\r
+      ChooseFile (NULL, L".efi", BootFromFile, &File);\r
     }\r
   } else if (Action == EFI_BROWSER_ACTION_CHANGED) {\r
     if ((Value == NULL) || (ActionRequest == NULL)) {\r
       return EFI_INVALID_PARAMETER;\r
     }\r
-   \r
+\r
     if (QuestionId == KEY_VALUE_SAVE_AND_EXIT_BOOT) {\r
+      CleanUselessBeforeSubmit (Private);\r
       CurrentFakeNVMap->BootOptionChanged = FALSE;\r
       *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;\r
     } else if (QuestionId == KEY_VALUE_SAVE_AND_EXIT_DRIVER) {\r
+      CleanUselessBeforeSubmit (Private);\r
       CurrentFakeNVMap->DriverOptionChanged = FALSE;\r
       *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;\r
     } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER) {\r
       //\r
       // Discard changes and exit formset\r
       //\r
-      CurrentFakeNVMap->DriverOptionalData[0]     = 0x0000;\r
-      CurrentFakeNVMap->DriverDescriptionData[0]  = 0x0000;\r
+      ZeroMem (CurrentFakeNVMap->DriverOptionalData, sizeof (CurrentFakeNVMap->DriverOptionalData));\r
+      ZeroMem (CurrentFakeNVMap->BootDescriptionData, sizeof (CurrentFakeNVMap->BootDescriptionData));\r
+      ZeroMem (OldFakeNVMap->DriverOptionalData, sizeof (OldFakeNVMap->DriverOptionalData));\r
+      ZeroMem (OldFakeNVMap->DriverDescriptionData, sizeof (OldFakeNVMap->DriverDescriptionData));\r
       CurrentFakeNVMap->DriverOptionChanged = FALSE;\r
       CurrentFakeNVMap->ForceReconnect      = TRUE;\r
       *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;\r
@@ -1009,15 +1231,17 @@ BootMaintCallback (
       //\r
       // Discard changes and exit formset\r
       //\r
-      CurrentFakeNVMap->BootOptionalData[0]     = 0x0000;\r
-      CurrentFakeNVMap->BootDescriptionData[0]  = 0x0000;\r
+      ZeroMem (CurrentFakeNVMap->BootOptionalData, sizeof (CurrentFakeNVMap->BootOptionalData));\r
+      ZeroMem (CurrentFakeNVMap->BootDescriptionData, sizeof (CurrentFakeNVMap->BootDescriptionData));\r
+      ZeroMem (OldFakeNVMap->BootOptionalData, sizeof (OldFakeNVMap->BootOptionalData));\r
+      ZeroMem (OldFakeNVMap->BootDescriptionData, sizeof (OldFakeNVMap->BootDescriptionData));\r
       CurrentFakeNVMap->BootOptionChanged = FALSE;\r
       *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;\r
     } else if (QuestionId == KEY_VALUE_BOOT_DESCRIPTION || QuestionId == KEY_VALUE_BOOT_OPTION) {\r
       CurrentFakeNVMap->BootOptionChanged = TRUE;\r
     } else if (QuestionId == KEY_VALUE_DRIVER_DESCRIPTION || QuestionId == KEY_VALUE_DRIVER_OPTION) {\r
       CurrentFakeNVMap->DriverOptionChanged = TRUE;\r
-    } \r
+    }\r
 \r
     if ((QuestionId >= BOOT_OPTION_DEL_QUESTION_ID) && (QuestionId < BOOT_OPTION_DEL_QUESTION_ID + MAX_MENU_NUMBER)) {\r
       if (Value->b){\r
@@ -1042,6 +1266,7 @@ BootMaintCallback (
       case KEY_VALUE_SAVE_AND_EXIT:\r
       case KEY_VALUE_NO_SAVE_AND_EXIT:\r
         if (QuestionId == KEY_VALUE_SAVE_AND_EXIT) {\r
+          CleanUselessBeforeSubmit (Private);\r
           *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;\r
         } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT) {\r
           DiscardChangeHandler (Private, CurrentFakeNVMap);\r
@@ -1058,6 +1283,22 @@ BootMaintCallback (
         break;\r
       }\r
     }\r
+    //\r
+    // Update the content in Terminal menu and Console menu here.\r
+    //\r
+    if (QuestionId == COM_BAUD_RATE_QUESTION_ID + Private->CurrentTerminal || QuestionId == COM_DATA_RATE_QUESTION_ID + Private->CurrentTerminal ||\r
+      QuestionId == COM_PARITY_QUESTION_ID + Private->CurrentTerminal || QuestionId == COM_STOP_BITS_QUESTION_ID + Private->CurrentTerminal ||\r
+      QuestionId == COM_TERMINAL_QUESTION_ID + Private->CurrentTerminal || QuestionId == COM_FLOWCONTROL_QUESTION_ID + Private->CurrentTerminal\r
+    ) {\r
+      UpdateTerminalContent(CurrentFakeNVMap);\r
+    }\r
+    if ((QuestionId >= CON_IN_DEVICE_QUESTION_ID) && (QuestionId < CON_IN_DEVICE_QUESTION_ID + MAX_MENU_NUMBER)) {\r
+      UpdateConsoleContent (L"ConIn",CurrentFakeNVMap);\r
+    } else if ((QuestionId >= CON_OUT_DEVICE_QUESTION_ID) && (QuestionId < CON_OUT_DEVICE_QUESTION_ID + MAX_MENU_NUMBER)) {\r
+      UpdateConsoleContent (L"ConOut", CurrentFakeNVMap);\r
+    } else if ((QuestionId >= CON_ERR_DEVICE_QUESTION_ID) && (QuestionId < CON_ERR_DEVICE_QUESTION_ID + MAX_MENU_NUMBER)) {\r
+      UpdateConsoleContent (L"ErrOut", CurrentFakeNVMap);\r
+    }\r
   }\r
 \r
   //\r
@@ -1128,42 +1369,50 @@ DiscardChangeHandler (
 }\r
 \r
 /**\r
-  Create dynamic code for BMM.\r
+  This function is to clean some useless data before submit changes.\r
 \r
-  @param  BmmCallbackInfo        The BMM context data.\r
+  @param Private            The BMM context data.\r
 \r
 **/\r
 VOID\r
-InitializeDrivers(\r
-  IN BMM_CALLBACK_DATA        *BmmCallbackInfo\r
+CleanUselessBeforeSubmit (\r
+  IN  BMM_CALLBACK_DATA               *Private\r
+  )\r
+{\r
+  UINT16  Index;\r
+  if (Private->BmmPreviousPageId != FORM_BOOT_DEL_ID) {\r
+    for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+      if (Private->BmmFakeNvData.BootOptionDel[Index] && !Private->BmmFakeNvData.BootOptionDelMark[Index]) {\r
+        Private->BmmFakeNvData.BootOptionDel[Index] = FALSE;\r
+        Private->BmmOldFakeNVData.BootOptionDel[Index] = FALSE;\r
+      }\r
+    }\r
+  }\r
+  if (Private->BmmPreviousPageId != FORM_DRV_DEL_ID) {\r
+    for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {\r
+      if (Private->BmmFakeNvData.DriverOptionDel[Index] && !Private->BmmFakeNvData.DriverOptionDelMark[Index]) {\r
+        Private->BmmFakeNvData.DriverOptionDel[Index] = FALSE;\r
+        Private->BmmOldFakeNVData.DriverOptionDel[Index] = FALSE;\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+\r
+  Update the menus in the BMM page.\r
+\r
+**/\r
+VOID\r
+CustomizeMenus (\r
+  VOID\r
   )\r
 {\r
-  EFI_HII_HANDLE              HiiHandle;\r
   VOID                        *StartOpCodeHandle;\r
   VOID                        *EndOpCodeHandle;\r
-  EFI_IFR_GUID_LABEL          *StartLabel;\r
-  EFI_IFR_GUID_LABEL          *EndLabel;\r
-  UINTN                       Index;    \r
-  EFI_STRING                  String;\r
-  EFI_STRING_ID               Token;\r
-  EFI_STRING_ID               TokenHelp;  \r
-  EFI_HII_HANDLE              *HiiHandles;\r
-  EFI_GUID                    FormSetGuid;\r
-  CHAR16                      *DevicePathStr;\r
-  EFI_STRING_ID               DevicePathId;\r
-  EFI_IFR_FORM_SET            *Buffer;      \r
-  UINTN                       BufferSize;   \r
-  UINT8                       ClassGuidNum; \r
-  EFI_GUID                    *ClassGuid;   \r
-  UINTN                       TempSize;\r
-  UINT8                       *Ptr;\r
-  EFI_STATUS                  Status;\r
-\r
-  TempSize =0;\r
-  BufferSize = 0;\r
-  Buffer = NULL;\r
-\r
-  HiiHandle = BmmCallbackInfo->BmmHiiHandle;\r
+  EFI_IFR_GUID_LABEL          *StartGuidLabel;\r
+  EFI_IFR_GUID_LABEL          *EndGuidLabel;\r
+\r
   //\r
   // Allocate space for creation of UpdateData Buffer\r
   //\r
@@ -1172,104 +1421,29 @@ InitializeDrivers(
 \r
   EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
   ASSERT (EndOpCodeHandle != NULL);\r
-\r
   //\r
   // Create Hii Extend Label OpCode as the start opcode\r
   //\r
-  StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
-  StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
-  StartLabel->Number       = LABEL_BMM_PLATFORM_INFORMATION;\r
-\r
+  StartGuidLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
+  StartGuidLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
+  StartGuidLabel->Number       = LABEL_FORM_MAIN_START;\r
   //\r
   // Create Hii Extend Label OpCode as the end opcode\r
   //\r
-  EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
-  EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
-  EndLabel->Number       = LABEL_END;\r
+  EndGuidLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
+  EndGuidLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
+  EndGuidLabel->Number       = LABEL_FORM_MAIN_END;\r
 \r
   //\r
-  // Get all the Hii handles\r
-  //\r
-  HiiHandles = HiiGetHiiHandles (NULL);\r
-  ASSERT (HiiHandles != NULL);\r
-\r
+  //Updata Front Page form\r
   //\r
-  // Search for formset of each class type\r
-  //\r
-  for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
-    Status = HiiGetFormSetFromHiiHandle(HiiHandles[Index], &Buffer,&BufferSize);\r
-    if (EFI_ERROR (Status)) {\r
-      continue;\r
-    }\r
-\r
-    Ptr = (UINT8 *)Buffer;\r
-    while(TempSize < BufferSize)  {\r
-      TempSize += ((EFI_IFR_OP_HEADER *) Ptr)->Length;\r
-\r
-      if (((EFI_IFR_OP_HEADER *) Ptr)->Length <= OFFSET_OF (EFI_IFR_FORM_SET, Flags)){\r
-        Ptr += ((EFI_IFR_OP_HEADER *) Ptr)->Length;\r
-        continue;\r
-      }\r
-\r
-      //\r
-      // Find FormSet OpCode\r
-      //\r
-      ClassGuidNum = (UINT8) (((EFI_IFR_FORM_SET *)Ptr)->Flags & 0x3);\r
-      ClassGuid = (EFI_GUID *) (VOID *)(Ptr + sizeof (EFI_IFR_FORM_SET));\r
-      while (ClassGuidNum-- > 0) {\r
-        if (CompareGuid (&gEfiIfrBootMaintenanceGuid, ClassGuid) == 0){\r
-          ClassGuid ++;\r
-          continue;\r
-        }\r
-\r
-        String = HiiGetString (HiiHandles[Index], ((EFI_IFR_FORM_SET *)Ptr)->FormSetTitle, NULL);\r
-        if (String == NULL) {\r
-          String = HiiGetString (HiiHandle, STRING_TOKEN (STR_MISSING_STRING), NULL);\r
-          ASSERT (String != NULL);\r
-        }\r
-        Token = HiiSetString (HiiHandle, 0, String, NULL);\r
-        FreePool (String);\r
-\r
-        String = HiiGetString (HiiHandles[Index], ((EFI_IFR_FORM_SET *)Ptr)->Help, NULL);\r
-        if (String == NULL) {\r
-          String = HiiGetString (HiiHandle, STRING_TOKEN (STR_MISSING_STRING), NULL);\r
-          ASSERT (String != NULL);\r
-        }\r
-        TokenHelp = HiiSetString (HiiHandle, 0, String, NULL);\r
-        FreePool (String);\r
-\r
-        FormSetGuid = ((EFI_IFR_FORM_SET *)Ptr)->Guid;\r
-\r
-        DevicePathStr = BmmExtractDevicePathFromHiiHandle(HiiHandles[Index]);\r
-        DevicePathId  = 0;\r
-        if (DevicePathStr != NULL){\r
-          DevicePathId = HiiSetString (HiiHandle, 0, DevicePathStr, NULL);\r
-          FreePool (DevicePathStr);\r
-        }\r
-         HiiCreateGotoExOpCode (\r
-           StartOpCodeHandle,\r
-           0,\r
-           Token,\r
-           TokenHelp,\r
-           0,\r
-           (EFI_QUESTION_ID) (Index + FRONT_PAGE_KEY_OFFSET),\r
-           0,\r
-           &FormSetGuid,\r
-           DevicePathId\r
-         );\r
-        break;\r
-      }\r
-      Ptr += ((EFI_IFR_OP_HEADER *) Ptr)->Length;\r
-    }\r
+  UiCustomizeBMMPage (\r
+    mBmmCallbackInfo->BmmHiiHandle,\r
+    StartOpCodeHandle\r
+    );\r
 \r
-    FreePool(Buffer);\r
-    Buffer = NULL;\r
-    TempSize = 0;\r
-    BufferSize = 0;\r
-  } \r
-  \r
   HiiUpdateForm (\r
-    HiiHandle,\r
+    mBmmCallbackInfo->BmmHiiHandle,\r
     &mBootMaintGuid,\r
     FORM_MAIN_ID,\r
     StartOpCodeHandle,\r
@@ -1277,8 +1451,7 @@ InitializeDrivers(
     );\r
 \r
   HiiFreeOpCodeHandle (StartOpCodeHandle);\r
-  HiiFreeOpCodeHandle (EndOpCodeHandle);  \r
-  FreePool (HiiHandles);\r
+  HiiFreeOpCodeHandle (EndOpCodeHandle);\r
 }\r
 \r
 /**\r
@@ -1299,8 +1472,6 @@ InitializeBmmConfig (
 \r
   ASSERT (CallbackData != NULL);\r
 \r
-  InitializeDrivers (CallbackData);\r
-\r
   //\r
   // Initialize data which located in BMM main page\r
   //\r
@@ -1388,6 +1559,77 @@ FreeAllMenu (
   mAllMenuInit = FALSE;\r
 }\r
 \r
+/**\r
+  Initial the boot mode related parameters.\r
+\r
+**/\r
+VOID\r
+BmmInitialBootModeInfo (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                         Status;\r
+  EFI_GRAPHICS_OUTPUT_PROTOCOL       *GraphicsOutput;\r
+  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL    *SimpleTextOut;\r
+  UINTN                              BootTextColumn;\r
+  UINTN                              BootTextRow;\r
+\r
+  if (mBmmModeInitialized) {\r
+    return;\r
+  }\r
+\r
+  //\r
+  // After the console is ready, get current video resolution\r
+  // and text mode before launching setup at first time.\r
+  //\r
+  Status = gBS->HandleProtocol (\r
+                  gST->ConsoleOutHandle,\r
+                  &gEfiGraphicsOutputProtocolGuid,\r
+                  (VOID**)&GraphicsOutput\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    GraphicsOutput = NULL;\r
+  }\r
+\r
+  Status = gBS->HandleProtocol (\r
+                  gST->ConsoleOutHandle,\r
+                  &gEfiSimpleTextOutProtocolGuid,\r
+                  (VOID**)&SimpleTextOut\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    SimpleTextOut = NULL;\r
+  }\r
+\r
+  if (GraphicsOutput != NULL) {\r
+    //\r
+    // Get current video resolution and text mode.\r
+    //\r
+    mBmmBootHorizontalResolution = GraphicsOutput->Mode->Info->HorizontalResolution;\r
+    mBmmBootVerticalResolution   = GraphicsOutput->Mode->Info->VerticalResolution;\r
+  }\r
+\r
+  if (SimpleTextOut != NULL) {\r
+    Status = SimpleTextOut->QueryMode (\r
+                              SimpleTextOut,\r
+                              SimpleTextOut->Mode->Mode,\r
+                              &BootTextColumn,\r
+                              &BootTextRow\r
+                              );\r
+    mBmmBootTextModeColumn = (UINT32)BootTextColumn;\r
+    mBmmBootTextModeRow    = (UINT32)BootTextRow;\r
+  }\r
+\r
+  //\r
+  // Get user defined text mode for setup.\r
+  //\r
+  mBmmSetupHorizontalResolution = PcdGet32 (PcdSetupVideoHorizontalResolution);\r
+  mBmmSetupVerticalResolution   = PcdGet32 (PcdSetupVideoVerticalResolution);\r
+  mBmmSetupTextModeColumn       = PcdGet32 (PcdSetupConOutColumn);\r
+  mBmmSetupTextModeRow          = PcdGet32 (PcdSetupConOutRow);\r
+\r
+  mBmmModeInitialized           = TRUE;\r
+}\r
+\r
 /**\r
 \r
   Install Boot Maintenance Manager Menu driver.\r
@@ -1443,8 +1685,6 @@ BootMaintenanceManagerUiLibConstructor (
   Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &mBmmCallbackInfo->FormBrowser2);\r
   ASSERT_EFI_ERROR (Status);\r
 \r
-  EfiBootManagerRefreshAllBootOption ();\r
-\r
   //\r
   // Create LoadOption in BmmCallbackInfo for Driver Callback\r
   //\r
@@ -1472,10 +1712,12 @@ BootMaintenanceManagerUiLibConstructor (
 \r
   CreateUpdateData();\r
   //\r
-  // Update boot maintenance manager page \r
+  // Update boot maintenance manager page\r
   //\r
   InitializeBmmConfig(mBmmCallbackInfo);\r
 \r
+  BmmInitialBootModeInfo();\r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r