]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkUnixPkg/Dxe/PlatformBds/Generic/BootMaint/BootMaint.c
Unix version of EFI emulator
[mirror_edk2.git] / EdkUnixPkg / Dxe / PlatformBds / Generic / BootMaint / BootMaint.c
diff --git a/EdkUnixPkg/Dxe/PlatformBds/Generic/BootMaint/BootMaint.c b/EdkUnixPkg/Dxe/PlatformBds/Generic/BootMaint/BootMaint.c
new file mode 100644 (file)
index 0000000..7dfad51
--- /dev/null
@@ -0,0 +1,1316 @@
+/*++ \r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. 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
+\r
+Module Name:\r
+\r
+  BootMaint.c\r
+    \r
+Abstract:\r
+\r
+  Boot Maintainence Main File\r
+\r
+--*/\r
+\r
+#include "Generic/Bds.h"\r
+#include "BootMaint.h"\r
+#include "BdsStrDefs.h"\r
+#include "FormGuid.h"\r
+\r
+//\r
+// Form binary for Boot Maintenance\r
+//\r
+extern UINT8    BmBin[];\r
+extern UINT8    FEBin[];\r
+extern EFI_GUID gBdsStringPackGuid;\r
+extern BOOLEAN  gConnectAllHappened;\r
+\r
+EFI_GUID        EfiLegacyDevOrderGuid = EFI_LEGACY_DEV_ORDER_VARIABLE_GUID;\r
+\r
+VOID\r
+InitAllMenu (\r
+  IN  BMM_CALLBACK_DATA    *CallbackData\r
+  );\r
+\r
+VOID\r
+FreeAllMenu (\r
+  VOID\r
+  );\r
+\r
+EFI_STATUS\r
+CreateMenuStringToken (\r
+  IN BMM_CALLBACK_DATA                *CallbackData,\r
+  IN EFI_HII_HANDLE                   HiiHandle,\r
+  IN BM_MENU_OPTION                   *MenuOption\r
+  )\r
+/*++\r
+Routine Description:\r
+\r
+  Create string tokens for a menu from its help strings and display strings\r
+\r
+Arguments:\r
+\r
+  HiiHandle       - Hii Handle of the package to be updated.\r
+  \r
+  MenuOption      - The Menu whose string tokens need to be created\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS     - string tokens created successfully\r
+  \r
+  others          - contain some errors\r
+  \r
+--*/\r
+{\r
+  BM_MENU_ENTRY *NewMenuEntry;\r
+  UINTN         Index;\r
+\r
+  for (Index = 0; Index < MenuOption->MenuNumber; Index++) {\r
+    NewMenuEntry = BOpt_GetMenuEntry (MenuOption, Index);\r
+    CallbackData->Hii->NewString (\r
+                        CallbackData->Hii,\r
+                        NULL,\r
+                        HiiHandle,\r
+                        &NewMenuEntry->DisplayStringToken,\r
+                        NewMenuEntry->DisplayString\r
+                        );\r
+\r
+    if (NULL == NewMenuEntry->HelpString) {\r
+      NewMenuEntry->HelpStringToken = NewMenuEntry->DisplayStringToken;\r
+    } else {\r
+      CallbackData->Hii->NewString (\r
+                          CallbackData->Hii,\r
+                          NULL,\r
+                          HiiHandle,\r
+                          &NewMenuEntry->HelpStringToken,\r
+                          NewMenuEntry->HelpString\r
+                          );\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DriverCallback (\r
+  IN EFI_FORM_CALLBACK_PROTOCOL       *This,\r
+  IN UINT16                           KeyValue,\r
+  IN EFI_IFR_DATA_ARRAY               *Data,\r
+  OUT EFI_HII_CALLBACK_PACKET         **Packet\r
+  )\r
+/*++\r
+Routine Description:\r
+\r
+  Callback Function for boot maintenance utility user interface interaction.\r
+\r
+Arguments:\r
+\r
+  This            - File explorer callback protocol pointer.     \r
+  KeyValue        - Key value to identify the type of data to expect.\r
+  Data            - A pointer to the data being sent to the original exporting driver.\r
+  Packet          - A pointer to a packet of information which a driver passes back to the browser.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS     - Callback ended successfully.\r
+  Others          - Contain some errors.\r
+  \r
+--*/\r
+{\r
+  BMM_CALLBACK_DATA *Private;\r
+  BM_MENU_ENTRY     *NewMenuEntry;\r
+  BMM_FAKE_NV_DATA  *CurrentFakeNVMap;\r
+  EFI_STATUS        Status;\r
+  UINTN             OldValue;\r
+  UINTN             NewValue;\r
+  UINTN             Number;\r
+  UINTN             Pos;\r
+  UINTN             Bit;\r
+  UINT16            NewValuePos;\r
+  UINT16            Index2;\r
+  UINT16            Index;\r
+  UINT8             *OldLegacyDev;\r
+  UINT8             *NewLegacyDev;\r
+  UINT8             *Location;\r
+  UINT8             *DisMap;\r
+  FORM_ID           FormId;\r
+\r
+  OldValue                        = 0;\r
+  NewValue                        = 0;\r
+  Number                          = 0;\r
+  OldLegacyDev                    = NULL;\r
+  NewLegacyDev                    = NULL;\r
+  NewValuePos                     = 0;\r
+  DisMap                          = NULL;\r
+\r
+  Private                         = BMM_CALLBACK_DATA_FROM_THIS (This);\r
+  UpdateData->FormCallbackHandle  = (EFI_PHYSICAL_ADDRESS) (UINTN) Private->BmmCallbackHandle;\r
+  CurrentFakeNVMap                = (BMM_FAKE_NV_DATA *) Data->NvRamMap;\r
+  Private->BmmFakeNvData          = CurrentFakeNVMap;\r
+  Location                        = (UINT8 *) &UpdateData->Data;\r
+\r
+  UpdatePageId (Private, KeyValue);\r
+\r
+  //\r
+  // need to be subtituded.\r
+  //\r
+  // Update Select FD/HD/CD/NET/BEV Order Form\r
+  //\r
+  if (FORM_SET_FD_ORDER_ID == Private->BmmPreviousPageId ||\r
+      FORM_SET_HD_ORDER_ID == Private->BmmPreviousPageId ||\r
+      FORM_SET_CD_ORDER_ID == Private->BmmPreviousPageId ||\r
+      FORM_SET_NET_ORDER_ID == Private->BmmPreviousPageId ||\r
+      FORM_SET_BEV_ORDER_ID == Private->BmmPreviousPageId ||\r
+      ((FORM_BOOT_SETUP_ID == Private->BmmPreviousPageId) &&\r
+      (KeyValue >= LEGACY_FD_QUESTION_ID) &&\r
+       (KeyValue < (LEGACY_BEV_QUESTION_ID + 100)) )\r
+      ) {\r
+\r
+    DisMap  = Private->BmmOldFakeNVData.DisableMap;\r
+\r
+    FormId  = Private->BmmPreviousPageId;\r
+    if (FormId == FORM_BOOT_SETUP_ID) {\r
+      FormId = Private->BmmCurrentPageId;\r
+    }\r
+\r
+    switch (FormId) {\r
+    case FORM_SET_FD_ORDER_ID:\r
+      Number        = (UINT16) LegacyFDMenu.MenuNumber;\r
+      OldLegacyDev  = Private->BmmOldFakeNVData.LegacyFD;\r
+      NewLegacyDev  = CurrentFakeNVMap->LegacyFD;\r
+      break;\r
+\r
+    case FORM_SET_HD_ORDER_ID:\r
+      Number        = (UINT16) LegacyHDMenu.MenuNumber;\r
+      OldLegacyDev  = Private->BmmOldFakeNVData.LegacyHD;\r
+      NewLegacyDev  = CurrentFakeNVMap->LegacyHD;\r
+      break;\r
+\r
+    case FORM_SET_CD_ORDER_ID:\r
+      Number        = (UINT16) LegacyCDMenu.MenuNumber;\r
+      OldLegacyDev  = Private->BmmOldFakeNVData.LegacyCD;\r
+      NewLegacyDev  = CurrentFakeNVMap->LegacyCD;\r
+      break;\r
+\r
+    case FORM_SET_NET_ORDER_ID:\r
+      Number        = (UINT16) LegacyNETMenu.MenuNumber;\r
+      OldLegacyDev  = Private->BmmOldFakeNVData.LegacyNET;\r
+      NewLegacyDev  = CurrentFakeNVMap->LegacyNET;\r
+      break;\r
+\r
+    case FORM_SET_BEV_ORDER_ID:\r
+      Number        = (UINT16) LegacyBEVMenu.MenuNumber;\r
+      OldLegacyDev  = Private->BmmOldFakeNVData.LegacyBEV;\r
+      NewLegacyDev  = CurrentFakeNVMap->LegacyBEV;\r
+      break;\r
+\r
+    default:\r
+      break;\r
+    }\r
+    //\r
+    //  First, find the different position\r
+    //  if there is change, it should be only one\r
+    //\r
+    for (Index = 0; Index < Number; Index++) {\r
+      if (OldLegacyDev[Index] != NewLegacyDev[Index]) {\r
+        OldValue  = OldLegacyDev[Index];\r
+        NewValue  = NewLegacyDev[Index];\r
+        break;\r
+      }\r
+    }\r
+\r
+    if (Index != Number) {\r
+      //\r
+      // there is change, now process\r
+      //\r
+      if (0xFF == NewValue) {\r
+        //\r
+        // This item will be disable\r
+        // Just move the items behind this forward to overlap it\r
+        //\r
+        Pos = OldValue / 8;\r
+        Bit = 7 - (OldValue % 8);\r
+        DisMap[Pos] |= (UINT8) (1 << Bit);\r
+        for (Index2 = Index; Index2 < Number - 1; Index2++) {\r
+          NewLegacyDev[Index2] = NewLegacyDev[Index2 + 1];\r
+        }\r
+\r
+        NewLegacyDev[Index2] = 0xFF;\r
+      } else {\r
+        for (Index2 = 0; Index2 < Number; Index2++) {\r
+          if (Index2 == Index) {\r
+            continue;\r
+          }\r
+\r
+          if (OldLegacyDev[Index2] == NewValue) {\r
+            //\r
+            // If NewValue is in OldLegacyDev array\r
+            // remember its old position\r
+            //\r
+            NewValuePos = Index2;\r
+            break;\r
+          }\r
+        }\r
+\r
+        if (Index2 != Number) {\r
+          //\r
+          // We will change current item to an existing item\r
+          // (It's hard to describe here, please read code, it's like a cycle-moving)\r
+          //\r
+          for (Index2 = NewValuePos; Index2 != Index;) {\r
+            if (NewValuePos < Index) {\r
+              NewLegacyDev[Index2] = OldLegacyDev[Index2 + 1];\r
+              Index2++;\r
+            } else {\r
+              NewLegacyDev[Index2] = OldLegacyDev[Index2 - 1];\r
+              Index2--;\r
+            }\r
+          }\r
+        } else {\r
+          //\r
+          // If NewValue is not in OldlegacyDev array, we are changing to a disabled item\r
+          // so we should modify DisMap to reflect the change\r
+          //\r
+          Pos = NewValue / 8;\r
+          Bit = 7 - (NewValue % 8);\r
+          DisMap[Pos] &= ~ (UINT8) (1 << Bit);\r
+          if (0xFF != OldValue) {\r
+            //\r
+            // Because NewValue is a item that was disabled before\r
+            // so after changing the OldValue should be disabled\r
+            // actually we are doing a swap of enable-disable states of two items\r
+            //\r
+            Pos = OldValue / 8;\r
+            Bit = 7 - (OldValue % 8);\r
+            DisMap[Pos] |= (UINT8) (1 << Bit);\r
+          }\r
+        }\r
+      }\r
+      //\r
+      // To prevent DISABLE appears in the middle of the list\r
+      // we should perform a re-ordering\r
+      //\r
+      Index = 0;\r
+      while (Index < Number) {\r
+        if (0xFF != NewLegacyDev[Index]) {\r
+          Index++;\r
+          continue;\r
+        }\r
+\r
+        Index2 = Index;\r
+        Index2++;\r
+        while (Index2 < Number) {\r
+          if (0xFF != NewLegacyDev[Index2]) {\r
+            break;\r
+          }\r
+\r
+          Index2++;\r
+        }\r
+\r
+        if (Index2 < Number) {\r
+          NewLegacyDev[Index]   = NewLegacyDev[Index2];\r
+          NewLegacyDev[Index2]  = 0xFF;\r
+        }\r
+\r
+        Index++;\r
+      }\r
+\r
+      CopyMem (\r
+        OldLegacyDev,\r
+        NewLegacyDev,\r
+        Number\r
+        );\r
+    }\r
+  }\r
+\r
+  if (KeyValue < FILE_OPTION_OFFSET) {\r
+    if (KeyValue < NORMAL_GOTO_OFFSET) {\r
+      switch (KeyValue) {\r
+      case KEY_VALUE_BOOT_FROM_FILE:\r
+        Private->FeCurrentState = BOOT_FROM_FILE_STATE;\r
+\r
+        //\r
+        // Exit Bmm main formset to send File Explorer formset.\r
+        //\r
+        CreateCallbackPacket (Packet, EXIT_REQUIRED);\r
+\r
+        break;\r
+\r
+      case FORM_BOOT_ADD_ID:\r
+        Private->FeCurrentState = ADD_BOOT_OPTION_STATE;\r
+\r
+        //\r
+        // Exit Bmm main formset to send File Explorer formset.\r
+        //\r
+        CreateCallbackPacket (Packet, EXIT_REQUIRED);\r
+        break;\r
+\r
+      case FORM_DRV_ADD_FILE_ID:\r
+        Private->FeCurrentState = ADD_DRIVER_OPTION_STATE;\r
+\r
+        //\r
+        // Exit Bmm main formset to send File Explorer formset.\r
+        //\r
+        CreateCallbackPacket (Packet, EXIT_REQUIRED);\r
+\r
+        break;\r
+\r
+      case FORM_DRV_ADD_HANDLE_ID:\r
+        CleanUpPage (FORM_DRV_ADD_HANDLE_ID, Private);\r
+        UpdateDrvAddHandlePage (Private);\r
+        break;\r
+\r
+      case FORM_BOOT_DEL_ID:\r
+        CleanUpPage (FORM_BOOT_DEL_ID, Private);\r
+        UpdateBootDelPage (Private);\r
+        break;\r
+\r
+      case FORM_BOOT_CHG_ID:\r
+      case FORM_DRV_CHG_ID:\r
+        UpdatePageBody (KeyValue, Private);\r
+        break;\r
+\r
+      case FORM_DRV_DEL_ID:\r
+        CleanUpPage (FORM_DRV_DEL_ID, Private);\r
+        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_RESET:\r
+        gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);\r
+        return EFI_UNSUPPORTED;\r
+\r
+      case FORM_CON_IN_ID:\r
+      case FORM_CON_OUT_ID:\r
+      case FORM_CON_ERR_ID:\r
+        UpdatePageBody (KeyValue, Private);\r
+        break;\r
+\r
+      case FORM_CON_COM_ID:\r
+        CleanUpPage (FORM_CON_COM_ID, Private);\r
+        UpdateConCOMPage (Private);\r
+        break;\r
+\r
+      case FORM_SET_FD_ORDER_ID:\r
+      case FORM_SET_HD_ORDER_ID:\r
+      case FORM_SET_CD_ORDER_ID:\r
+      case FORM_SET_NET_ORDER_ID:\r
+      case FORM_SET_BEV_ORDER_ID:\r
+        CleanUpPage (KeyValue, Private);\r
+        UpdateSetLegacyDeviceOrderPage (KeyValue, Private);\r
+        break;\r
+\r
+      case KEY_VALUE_SAVE_AND_EXIT:\r
+      case KEY_VALUE_NO_SAVE_AND_EXIT:\r
+\r
+        if (KeyValue == KEY_VALUE_SAVE_AND_EXIT) {\r
+          Status = ApplyChangeHandler (Private, CurrentFakeNVMap, Private->BmmPreviousPageId);\r
+          if (EFI_ERROR (Status)) {\r
+            return Status;\r
+          }\r
+        } else if (KeyValue == KEY_VALUE_NO_SAVE_AND_EXIT) {\r
+          DiscardChangeHandler (Private, CurrentFakeNVMap);\r
+        }\r
+        //\r
+        // Tell browser not to ask for confirmation of changes,\r
+        // since we have already applied or discarded.\r
+        //\r
+        CreateCallbackPacket (Packet, NV_NOT_CHANGED);\r
+        break;\r
+\r
+      default:\r
+        break;\r
+      }\r
+    } else if ((KeyValue >= TERMINAL_OPTION_OFFSET) && (KeyValue < CONSOLE_OPTION_OFFSET)) {\r
+      Index2                    = (UINT16) (KeyValue - TERMINAL_OPTION_OFFSET);\r
+      Private->CurrentTerminal  = Index2;\r
+\r
+      CleanUpPage (FORM_CON_COM_SETUP_ID, Private);\r
+      UpdateTerminalPage (Private);\r
+\r
+    } else if (KeyValue >= HANDLE_OPTION_OFFSET) {\r
+      Index2                  = (UINT16) (KeyValue - HANDLE_OPTION_OFFSET);\r
+\r
+      NewMenuEntry            = BOpt_GetMenuEntry (&DriverMenu, Index2);\r
+      Private->HandleContext  = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+      CleanUpPage (FORM_DRV_ADD_HANDLE_DESC_ID, Private);\r
+\r
+      Private->MenuEntry                  = NewMenuEntry;\r
+      Private->LoadContext->FilePathList  = Private->HandleContext->DevicePath;\r
+\r
+      UpdateDriverAddHandleDescPage (Private);\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+ApplyChangeHandler (\r
+  IN  BMM_CALLBACK_DATA               *Private,\r
+  IN  BMM_FAKE_NV_DATA                *CurrentFakeNVMap,\r
+  IN  FORM_ID                         FormId\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Function handling request to apply changes for BMM pages.\r
+\r
+Arguments:\r
+\r
+  Private          - Pointer to callback data buffer.\r
+  CurrentFakeNVMap - Pointer to buffer holding data of various values used by BMM\r
+  FormId           - ID of the form which has sent the request to apply change.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS      - Change successfully applied.\r
+  Other            - Error occurs while trying to apply changes.\r
+\r
+--*/\r
+{\r
+  BM_CONSOLE_CONTEXT  *NewConsoleContext;\r
+  BM_TERMINAL_CONTEXT *NewTerminalContext;\r
+  BM_LOAD_CONTEXT     *NewLoadContext;\r
+  BM_MENU_ENTRY       *NewMenuEntry;\r
+  EFI_STATUS          Status;\r
+  UINT16              Index;\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  switch (FormId) {\r
+  case FORM_SET_FD_ORDER_ID:\r
+  case FORM_SET_HD_ORDER_ID:\r
+  case FORM_SET_CD_ORDER_ID:\r
+  case FORM_SET_NET_ORDER_ID:\r
+  case FORM_SET_BEV_ORDER_ID:\r
+    Var_UpdateBBSOption (Private);\r
+    break;\r
+\r
+  case FORM_BOOT_DEL_ID:\r
+    for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+      NewMenuEntry            = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
+      NewLoadContext          = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+      NewLoadContext->Deleted = CurrentFakeNVMap->BootOptionDel[Index];\r
+    }\r
+\r
+    Var_DelBootOption ();\r
+    break;\r
+\r
+  case FORM_DRV_DEL_ID:\r
+    for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {\r
+      NewMenuEntry            = BOpt_GetMenuEntry (&DriverOptionMenu, Index);\r
+      NewLoadContext          = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+      NewLoadContext->Deleted = CurrentFakeNVMap->DriverOptionDel[Index];\r
+    }\r
+\r
+    Var_DelDriverOption ();\r
+    break;\r
+\r
+  case FORM_BOOT_CHG_ID:\r
+    Status = Var_UpdateBootOrder (Private);\r
+    break;\r
+\r
+  case FORM_DRV_CHG_ID:\r
+    Status = Var_UpdateDriverOrder (Private);\r
+    break;\r
+\r
+  case FORM_TIME_OUT_ID:\r
+    Status = gRT->SetVariable (\r
+                    L"Timeout",\r
+                    &gEfiGlobalVariableGuid,\r
+                    VAR_FLAG,\r
+                    sizeof (UINT16),\r
+                    &(CurrentFakeNVMap->BootTimeOut)\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      goto Error;\r
+    }\r
+\r
+    Private->BmmOldFakeNVData.BootTimeOut = CurrentFakeNVMap->BootTimeOut;\r
+    break;\r
+\r
+  case FORM_BOOT_NEXT_ID:\r
+    Status = Var_UpdateBootNext (Private);\r
+    break;\r
+\r
+  case FORM_CON_COM_ID:\r
+    NewMenuEntry                      = BOpt_GetMenuEntry (&TerminalMenu, Private->CurrentTerminal);\r
+\r
+    NewTerminalContext                = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+    NewTerminalContext->BaudRateIndex = CurrentFakeNVMap->COMBaudRate;\r
+    NewTerminalContext->BaudRate      = BaudRateList[CurrentFakeNVMap->COMBaudRate].Value;\r
+    NewTerminalContext->DataBitsIndex = CurrentFakeNVMap->COMDataRate;\r
+    NewTerminalContext->DataBits      = (UINT8) DataBitsList[CurrentFakeNVMap->COMDataRate].Value;\r
+    NewTerminalContext->StopBitsIndex = CurrentFakeNVMap->COMStopBits;\r
+    NewTerminalContext->StopBits      = (UINT8) StopBitsList[CurrentFakeNVMap->COMStopBits].Value;\r
+    NewTerminalContext->ParityIndex   = CurrentFakeNVMap->COMParity;\r
+    NewTerminalContext->Parity        = (UINT8) ParityList[CurrentFakeNVMap->COMParity].Value;\r
+    NewTerminalContext->TerminalType  = CurrentFakeNVMap->COMTerminalType;\r
+\r
+    ChangeTerminalDevicePath (\r
+      NewTerminalContext->DevicePath,\r
+      FALSE\r
+      );\r
+\r
+    Var_UpdateConsoleInpOption ();\r
+    Var_UpdateConsoleOutOption ();\r
+    Var_UpdateErrorOutOption ();\r
+    break;\r
+\r
+  case FORM_CON_IN_ID:\r
+    for (Index = 0; Index < ConsoleInpMenu.MenuNumber; Index++) {\r
+      NewMenuEntry                = BOpt_GetMenuEntry (&ConsoleInpMenu, Index);\r
+      NewConsoleContext           = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+      NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index];\r
+    }\r
+\r
+    for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+      NewMenuEntry                = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
+      NewTerminalContext          = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+      NewTerminalContext->IsConIn = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleInpMenu.MenuNumber];\r
+    }\r
+\r
+    Var_UpdateConsoleInpOption ();\r
+    break;\r
+\r
+  case FORM_CON_OUT_ID:\r
+    for (Index = 0; Index < ConsoleOutMenu.MenuNumber; Index++) {\r
+      NewMenuEntry                = BOpt_GetMenuEntry (&ConsoleOutMenu, Index);\r
+      NewConsoleContext           = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+      NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index];\r
+    }\r
+\r
+    for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+      NewMenuEntry                  = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
+      NewTerminalContext            = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+      NewTerminalContext->IsConOut  = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleOutMenu.MenuNumber];\r
+    }\r
+\r
+    Var_UpdateConsoleOutOption ();\r
+    break;\r
+\r
+  case FORM_CON_ERR_ID:\r
+    for (Index = 0; Index < ConsoleErrMenu.MenuNumber; Index++) {\r
+      NewMenuEntry                = BOpt_GetMenuEntry (&ConsoleErrMenu, Index);\r
+      NewConsoleContext           = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+      NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index];\r
+    }\r
+\r
+    for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+      NewMenuEntry                  = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
+      NewTerminalContext            = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+      NewTerminalContext->IsStdErr  = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleErrMenu.MenuNumber];\r
+    }\r
+\r
+    Var_UpdateErrorOutOption ();\r
+    break;\r
+\r
+  case FORM_DRV_ADD_HANDLE_DESC_ID:\r
+    Status = Var_UpdateDriverOption (\r
+               Private,\r
+               Private->BmmHiiHandle,\r
+               CurrentFakeNVMap->DriverAddHandleDesc,\r
+               CurrentFakeNVMap->DriverAddHandleOptionalData,\r
+               CurrentFakeNVMap->DriverAddForceReconnect\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      goto Error;\r
+    }\r
+\r
+    BOpt_GetDriverOptions (Private);\r
+    CreateMenuStringToken (Private, Private->BmmHiiHandle, &DriverOptionMenu);\r
+    break;\r
+\r
+  default:\r
+    break;\r
+  }\r
+\r
+Error:\r
+  return Status;\r
+}\r
+\r
+VOID\r
+DiscardChangeHandler (\r
+  IN  BMM_CALLBACK_DATA               *Private,\r
+  IN  BMM_FAKE_NV_DATA                *CurrentFakeNVMap\r
+  )\r
+{\r
+  UINT16  Index;\r
+\r
+  switch (Private->BmmPreviousPageId) {\r
+  case FORM_BOOT_CHG_ID:\r
+  case FORM_DRV_CHG_ID:\r
+    CopyMem (CurrentFakeNVMap->OptionOrder, Private->BmmOldFakeNVData.OptionOrder, 100);\r
+    break;\r
+\r
+  case FORM_BOOT_DEL_ID:\r
+    for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+      CurrentFakeNVMap->BootOptionDel[Index] = 0x00;\r
+    }\r
+    break;\r
+\r
+  case FORM_DRV_DEL_ID:\r
+    for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {\r
+      CurrentFakeNVMap->DriverOptionDel[Index] = 0x00;\r
+    }\r
+    break;\r
+\r
+  case FORM_BOOT_NEXT_ID:\r
+    CurrentFakeNVMap->BootNext = Private->BmmOldFakeNVData.BootNext;\r
+    break;\r
+\r
+  case FORM_TIME_OUT_ID:\r
+    CurrentFakeNVMap->BootTimeOut = Private->BmmOldFakeNVData.BootTimeOut;\r
+    break;\r
+\r
+  case FORM_DRV_ADD_HANDLE_DESC_ID:\r
+  case FORM_DRV_ADD_FILE_ID:\r
+  case FORM_DRV_ADD_HANDLE_ID:\r
+    CurrentFakeNVMap->DriverAddHandleDesc[0]          = 0x0000;\r
+    CurrentFakeNVMap->DriverAddHandleOptionalData[0]  = 0x0000;\r
+    break;\r
+\r
+  default:\r
+    break;\r
+  }\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+NvWrite (\r
+  IN     EFI_FORM_CALLBACK_PROTOCOL              *This,\r
+  IN     CHAR16                                  *VariableName,\r
+  IN     EFI_GUID                                *VendorGuid,\r
+  OUT    UINT32                                  Attributes OPTIONAL,\r
+  IN OUT UINTN                                   DataSize,\r
+  OUT    VOID                                    *Buffer,\r
+  OUT    BOOLEAN                                 *ResetRequired\r
+  )\r
+{\r
+  //\r
+  // Do nothing here. Just to catch the F10, we use "Apply Changes" tag to save.\r
+  //\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+InitializeBM (\r
+  VOID\r
+  )\r
+/*++\r
+Routine Description:\r
+\r
+  Initialize the Boot Maintenance Utitliy\r
+\r
+Arguments:\r
+\r
+  ImageHandle     - caller provided handle\r
+  \r
+  SystemTable     - caller provided system tables\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS     - utility ended successfully\r
+  \r
+  others          - contain some errors\r
+  \r
+--*/\r
+{\r
+  EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;\r
+  EFI_HII_PACKAGES          *PackageList;\r
+  BMM_CALLBACK_DATA         *BmmCallbackInfo;\r
+  EFI_HII_PROTOCOL          *Hii;\r
+  EFI_HII_HANDLE            HiiHandle;\r
+  EFI_STATUS                Status;\r
+  EFI_HANDLE                Handle;\r
+  UINT8                     *Ptr;\r
+  UINT8                     *Location;\r
+\r
+  Status      = EFI_SUCCESS;\r
+  UpdateData  = NULL;\r
+  //\r
+  // Initialize EfiUtilityLib and EfiDriverLib\r
+  // Since many functions in UtilityLib must be used and\r
+  // SetupBrowser use DriverLib\r
+  //\r
+  //\r
+  // There should be only one EFI_HII_PROTOCOL Image\r
+  //\r
+  Status = EfiLibLocateProtocol (&gEfiHiiProtocolGuid, &Hii);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  //\r
+  // Create CallbackData structures for Driver Callback\r
+  //\r
+  BmmCallbackInfo = AllocateZeroPool (sizeof (BMM_CALLBACK_DATA));\r
+  if (!BmmCallbackInfo) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  //\r
+  // Create LoadOption in BmmCallbackInfo for Driver Callback\r
+  //\r
+  Ptr = AllocateZeroPool (sizeof (BM_LOAD_CONTEXT) + sizeof (BM_FILE_CONTEXT) + sizeof (BM_HANDLE_CONTEXT) + sizeof (BM_MENU_ENTRY));\r
+  if (!Ptr) {\r
+    SafeFreePool (BmmCallbackInfo);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  //\r
+  // Initialize Bmm callback data.\r
+  //\r
+  BmmCallbackInfo->LoadContext = (BM_LOAD_CONTEXT *) Ptr;\r
+  Ptr += sizeof (BM_LOAD_CONTEXT);\r
+\r
+  BmmCallbackInfo->FileContext = (BM_FILE_CONTEXT *) Ptr;\r
+  Ptr += sizeof (BM_FILE_CONTEXT);\r
+\r
+  BmmCallbackInfo->HandleContext = (BM_HANDLE_CONTEXT *) Ptr;\r
+  Ptr += sizeof (BM_HANDLE_CONTEXT);\r
+\r
+  BmmCallbackInfo->MenuEntry      = (BM_MENU_ENTRY *) Ptr;\r
+\r
+  BmmCallbackInfo->BmmFakeNvData  = &BmmCallbackInfo->BmmOldFakeNVData;\r
+\r
+  ZeroMem (BmmCallbackInfo->BmmFakeNvData, sizeof (BMM_FAKE_NV_DATA));\r
+\r
+  BmmCallbackInfo->Signature                  = BMM_CALLBACK_DATA_SIGNATURE;\r
+  BmmCallbackInfo->Hii                        = Hii;\r
+  BmmCallbackInfo->BmmDriverCallback.NvRead   = NULL;\r
+  BmmCallbackInfo->BmmDriverCallback.NvWrite  = NvWrite;\r
+  BmmCallbackInfo->BmmDriverCallback.Callback = DriverCallback;\r
+  BmmCallbackInfo->BmmPreviousPageId          = FORM_MAIN_ID;\r
+  BmmCallbackInfo->BmmCurrentPageId           = FORM_MAIN_ID;\r
+  BmmCallbackInfo->FeDriverCallback.NvRead    = NULL;\r
+  BmmCallbackInfo->FeDriverCallback.NvWrite   = NvWrite;\r
+  BmmCallbackInfo->FeDriverCallback.Callback  = FileExplorerCallback;\r
+  BmmCallbackInfo->FeCurrentState             = INACTIVE_STATE;\r
+  BmmCallbackInfo->FeDisplayContext           = UNKNOWN_CONTEXT;\r
+\r
+  //\r
+  // Install bmm callback protocol interface\r
+  //\r
+  Handle = NULL;\r
+  Status = gBS->InstallProtocolInterface (\r
+                  &Handle,\r
+                  &gEfiFormCallbackProtocolGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  &BmmCallbackInfo->BmmDriverCallback\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  BmmCallbackInfo->BmmCallbackHandle = Handle;\r
+\r
+  //\r
+  // Install file explorer callback protocol interface\r
+  //\r
+  Handle = NULL;\r
+  Status = gBS->InstallProtocolInterface (\r
+                  &Handle,\r
+                  &gEfiFormCallbackProtocolGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  &BmmCallbackInfo->FeDriverCallback\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  BmmCallbackInfo->FeCallbackHandle = Handle;\r
+\r
+  //\r
+  // Post our VFR to the HII database.\r
+  //\r
+  PackageList = PreparePackages (1, &gBdsStringPackGuid, BmBin);\r
+  Status      = Hii->NewPack (Hii, PackageList, &HiiHandle);\r
+  gBS->FreePool (PackageList);\r
+\r
+  BmmCallbackInfo->BmmHiiHandle = HiiHandle;\r
+\r
+  PackageList                   = PreparePackages (1, &gBdsStringPackGuid, FEBin);\r
+  Status                        = Hii->NewPack (Hii, PackageList, &HiiHandle);\r
+  gBS->FreePool (PackageList);\r
+\r
+  BmmCallbackInfo->FeHiiHandle = HiiHandle;\r
+\r
+  //\r
+  // Allocate space for creation of Buffer\r
+  //\r
+  UpdateData = AllocateZeroPool (UPDATE_DATA_SIZE);\r
+  if (!UpdateData) {\r
+    SafeFreePool (BmmCallbackInfo->LoadContext);\r
+    SafeFreePool (BmmCallbackInfo);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  //\r
+  // Initialize UpdateData structure\r
+  //\r
+  RefreshUpdateData (TRUE, (EFI_PHYSICAL_ADDRESS) (UINTN) BmmCallbackInfo->BmmCallbackHandle, FALSE, 0, 0);\r
+\r
+  Location = (UINT8 *) &UpdateData->Data;\r
+\r
+  InitializeStringDepository ();\r
+\r
+  InitAllMenu (BmmCallbackInfo);\r
+\r
+  CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleInpMenu);\r
+  CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleOutMenu);\r
+  CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleErrMenu);\r
+  CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &BootOptionMenu);\r
+  CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverOptionMenu);\r
+  CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &TerminalMenu);\r
+  CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverMenu);\r
+\r
+  UpdateBootDelPage (BmmCallbackInfo);\r
+  UpdateDrvDelPage (BmmCallbackInfo);\r
+\r
+  if (TerminalMenu.MenuNumber > 0) {\r
+    BmmCallbackInfo->CurrentTerminal = 0;\r
+    UpdateTerminalPage (BmmCallbackInfo);\r
+  }\r
+\r
+  Location  = (UINT8 *) &UpdateData->Data;\r
+  Status    = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, &LegacyBios);\r
+  if (!EFI_ERROR (Status)) {\r
+    //\r
+    // If LegacyBios Protocol is installed, add 3 tags about legacy boot option\r
+    // in BootOption form: legacy FD/HD/CD/NET/BEV\r
+    //\r
+    UpdateData->DataCount = 5;\r
+    CreateGotoOpCode (\r
+      FORM_SET_FD_ORDER_ID,\r
+      STRING_TOKEN (STR_FORM_SET_FD_ORDER_TITLE),\r
+      STRING_TOKEN (STR_FORM_SET_FD_ORDER_TITLE),\r
+      EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,\r
+      FORM_SET_FD_ORDER_ID,\r
+      Location\r
+      );\r
+\r
+    Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+\r
+    CreateGotoOpCode (\r
+      FORM_SET_HD_ORDER_ID,\r
+      STRING_TOKEN (STR_FORM_SET_HD_ORDER_TITLE),\r
+      STRING_TOKEN (STR_FORM_SET_HD_ORDER_TITLE),\r
+      EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,\r
+      FORM_SET_HD_ORDER_ID,\r
+      Location\r
+      );\r
+\r
+    Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+\r
+    CreateGotoOpCode (\r
+      FORM_SET_CD_ORDER_ID,\r
+      STRING_TOKEN (STR_FORM_SET_CD_ORDER_TITLE),\r
+      STRING_TOKEN (STR_FORM_SET_CD_ORDER_TITLE),\r
+      EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,\r
+      FORM_SET_CD_ORDER_ID,\r
+      Location\r
+      );\r
+\r
+    Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+\r
+    CreateGotoOpCode (\r
+      FORM_SET_NET_ORDER_ID,\r
+      STRING_TOKEN (STR_FORM_SET_NET_ORDER_TITLE),\r
+      STRING_TOKEN (STR_FORM_SET_NET_ORDER_TITLE),\r
+      EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,\r
+      FORM_SET_NET_ORDER_ID,\r
+      Location\r
+      );\r
+\r
+    Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+\r
+    CreateGotoOpCode (\r
+      FORM_SET_BEV_ORDER_ID,\r
+      STRING_TOKEN (STR_FORM_SET_BEV_ORDER_TITLE),\r
+      STRING_TOKEN (STR_FORM_SET_BEV_ORDER_TITLE),\r
+      EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,\r
+      FORM_SET_BEV_ORDER_ID,\r
+      Location\r
+      );\r
+\r
+    Hii->UpdateForm (\r
+          Hii,\r
+          BmmCallbackInfo->BmmHiiHandle,\r
+          (EFI_FORM_LABEL) FORM_BOOT_LEGACY_DEVICE_ID,\r
+          TRUE,\r
+          UpdateData\r
+          );\r
+  }\r
+  //\r
+  // Dispatch BMM main formset and File Explorer formset.\r
+  //\r
+  FormSetDispatcher (BmmCallbackInfo);\r
+\r
+  Hii->ResetStrings (Hii, HiiHandle);\r
+\r
+  CleanUpStringDepository ();\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  FreeAllMenu ();\r
+\r
+  SafeFreePool (BmmCallbackInfo->LoadContext);\r
+  BmmCallbackInfo->LoadContext = NULL;\r
+  SafeFreePool (BmmCallbackInfo);\r
+  BmmCallbackInfo = NULL;\r
+  SafeFreePool (UpdateData);\r
+  UpdateData = NULL;\r
+\r
+  return Status;\r
+}\r
+\r
+VOID\r
+InitAllMenu (\r
+  IN  BMM_CALLBACK_DATA    *CallbackData\r
+  )\r
+{\r
+  InitializeListHead (&BootOptionMenu.Head);\r
+  InitializeListHead (&DriverOptionMenu.Head);\r
+  BOpt_GetBootOptions (CallbackData);\r
+  BOpt_GetDriverOptions (CallbackData);\r
+  BOpt_GetLegacyOptions ();\r
+  InitializeListHead (&FsOptionMenu.Head);\r
+  BOpt_FindDrivers ();\r
+  InitializeListHead (&DirectoryMenu.Head);\r
+  InitializeListHead (&ConsoleInpMenu.Head);\r
+  InitializeListHead (&ConsoleOutMenu.Head);\r
+  InitializeListHead (&ConsoleErrMenu.Head);\r
+  InitializeListHead (&TerminalMenu.Head);\r
+  LocateSerialIo ();\r
+  GetAllConsoles ();\r
+}\r
+\r
+VOID\r
+FreeAllMenu (\r
+  VOID\r
+  )\r
+{\r
+  BOpt_FreeMenu (&DirectoryMenu);\r
+  BOpt_FreeMenu (&FsOptionMenu);\r
+  BOpt_FreeMenu (&BootOptionMenu);\r
+  BOpt_FreeMenu (&DriverOptionMenu);\r
+  BOpt_FreeMenu (&DriverMenu);\r
+  BOpt_FreeLegacyOptions ();\r
+  FreeAllConsoles ();\r
+}\r
+\r
+VOID\r
+InitializeStringDepository (\r
+  VOID\r
+  )\r
+/*++\r
+Routine Description:\r
+  Intialize all the string depositories.\r
+\r
+Arguments:\r
+  None.\r
+\r
+Returns:\r
+  None.  \r
+--*/\r
+{\r
+  STRING_DEPOSITORY *StringDepository;\r
+  StringDepository              = AllocateZeroPool (sizeof (STRING_DEPOSITORY) * STRING_DEPOSITORY_NUMBER);\r
+  FileOptionStrDepository       = StringDepository++;\r
+  ConsoleOptionStrDepository    = StringDepository++;\r
+  BootOptionStrDepository       = StringDepository++;\r
+  BootOptionHelpStrDepository   = StringDepository++;\r
+  DriverOptionStrDepository     = StringDepository++;\r
+  DriverOptionHelpStrDepository = StringDepository++;\r
+  TerminalStrDepository         = StringDepository;\r
+}\r
+\r
+STRING_REF\r
+GetStringTokenFromDepository (\r
+  IN   BMM_CALLBACK_DATA     *CallbackData,\r
+  IN   STRING_DEPOSITORY     *StringDepository\r
+  )\r
+/*++\r
+Routine Description:\r
+  Fetch a usable string node from the string depository and return the string token.\r
+\r
+Arguments:\r
+  StringDepository       - Pointer of the string depository.\r
+\r
+Returns:\r
+  STRING_REF             - String token.\r
+--*/\r
+{\r
+  STRING_LIST_NODE  *CurrentListNode;\r
+  STRING_LIST_NODE  *NextListNode;\r
+\r
+  CurrentListNode = StringDepository->CurrentNode;\r
+\r
+  if ((NULL != CurrentListNode) && (NULL != CurrentListNode->Next)) {\r
+    //\r
+    // Fetch one reclaimed node from the list.\r
+    //\r
+    NextListNode = StringDepository->CurrentNode->Next;\r
+  } else {\r
+    //\r
+    // If there is no usable node in the list, update the list.\r
+    //\r
+    NextListNode = AllocateZeroPool (sizeof (STRING_LIST_NODE));\r
+\r
+    CallbackData->Hii->NewString (\r
+                        CallbackData->Hii,\r
+                        NULL,\r
+                        CallbackData->BmmHiiHandle,\r
+                        &(NextListNode->StringToken),\r
+                        L" "\r
+                        );\r
+\r
+    ASSERT (NextListNode->StringToken != 0);\r
+\r
+    StringDepository->TotalNodeNumber++;\r
+\r
+    if (NULL == CurrentListNode) {\r
+      StringDepository->ListHead = NextListNode;\r
+    } else {\r
+      CurrentListNode->Next = NextListNode;\r
+    }\r
+  }\r
+\r
+  StringDepository->CurrentNode = NextListNode;\r
+\r
+  return StringDepository->CurrentNode->StringToken;\r
+}\r
+\r
+VOID\r
+ReclaimStringDepository (\r
+  VOID\r
+  )\r
+/*++\r
+Routine Description:\r
+  Reclaim string depositories by moving the current node pointer to list head..\r
+\r
+Arguments:\r
+  None.\r
+\r
+Returns:\r
+  None.\r
+--*/\r
+{\r
+  UINTN             DepositoryIndex;\r
+  STRING_DEPOSITORY *StringDepository;\r
+\r
+  StringDepository = FileOptionStrDepository;\r
+  for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) {\r
+    StringDepository->CurrentNode = StringDepository->ListHead;\r
+    StringDepository++;\r
+  }\r
+}\r
+\r
+VOID\r
+CleanUpStringDepository (\r
+  VOID\r
+  )\r
+/*++\r
+Routine Description:\r
+  Release resource for all the string depositories.\r
+\r
+Arguments:\r
+  None.\r
+\r
+Returns:\r
+  None.\r
+--*/\r
+{\r
+  UINTN             NodeIndex;\r
+  UINTN             DepositoryIndex;\r
+  STRING_LIST_NODE  *CurrentListNode;\r
+  STRING_LIST_NODE  *NextListNode;\r
+  STRING_DEPOSITORY *StringDepository;\r
+\r
+  //\r
+  // Release string list nodes.\r
+  //\r
+  StringDepository = FileOptionStrDepository;\r
+  for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) {\r
+    CurrentListNode = StringDepository->ListHead;\r
+    for (NodeIndex = 0; NodeIndex < StringDepository->TotalNodeNumber; NodeIndex++) {\r
+      NextListNode = CurrentListNode->Next;\r
+      SafeFreePool (CurrentListNode);\r
+      CurrentListNode = NextListNode;\r
+    }\r
+\r
+    StringDepository++;\r
+  }\r
+  //\r
+  // Release string depository.\r
+  //\r
+  SafeFreePool (FileOptionStrDepository);\r
+}\r
+\r
+EFI_STATUS\r
+BdsStartBootMaint (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Start boot maintenance manager\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  LIST_ENTRY  BdsBootOptionList;\r
+\r
+  InitializeListHead (&BdsBootOptionList);\r
+\r
+  //\r
+  // Connect all prior to entering the platform setup menu.\r
+  //\r
+  if (!gConnectAllHappened) {\r
+    BdsLibConnectAllDriversToAllControllers ();\r
+    gConnectAllHappened = TRUE;\r
+  }\r
+  //\r
+  // Have chance to enumerate boot device\r
+  //\r
+  BdsLibEnumerateAllBootOption (&BdsBootOptionList);\r
+\r
+  //\r
+  // Init the BMM\r
+  //\r
+  Status = InitializeBM ();\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+FormSetDispatcher (\r
+  IN  BMM_CALLBACK_DATA    *CallbackData\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Dispatch BMM formset and FileExplorer formset.\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+  EFI_FORM_BROWSER_PROTOCOL *FormConfig;\r
+  UINT8                     *Location;\r
+  EFI_STATUS                Status;\r
+  UINTN                     Index;\r
+  BM_MENU_ENTRY             *NewMenuEntry;\r
+  BM_FILE_CONTEXT           *NewFileContext;\r
+  BOOLEAN                       BootMaintMenuResetRequired;\r
+\r
+  Location        = NULL;\r
+  Index           = 0;\r
+  NewMenuEntry    = NULL;\r
+  NewFileContext  = NULL;\r
+\r
+  //\r
+  // There should only be one Form Configuration protocol\r
+  //\r
+  Status = EfiLibLocateProtocol (&gEfiFormBrowserProtocolGuid, &FormConfig);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  while (1) {\r
+    UpdatePageId (CallbackData, FORM_MAIN_ID);\r
+\r
+    BootMaintMenuResetRequired = FALSE;\r
+    Status = FormConfig->SendForm (\r
+                          FormConfig,\r
+                          TRUE,\r
+                          &(CallbackData->BmmHiiHandle),\r
+                          1,\r
+                          NULL,\r
+                          NULL,\r
+                          (UINT8 *) CallbackData->BmmFakeNvData,\r
+                          NULL,\r
+                          &BootMaintMenuResetRequired\r
+                          );\r
+\r
+    if (BootMaintMenuResetRequired) {\r
+      EnableResetRequired ();\r
+    }\r
+\r
+    ReclaimStringDepository ();\r
+\r
+    //\r
+    // When this Formset returns, check if we are going to explore files.\r
+    //\r
+    if (INACTIVE_STATE != CallbackData->FeCurrentState) {\r
+      UpdateFileExplorer (CallbackData, 0);\r
+\r
+      BootMaintMenuResetRequired = FALSE;\r
+      Status = FormConfig->SendForm (\r
+                            FormConfig,\r
+                            TRUE,\r
+                            &(CallbackData->FeHiiHandle),\r
+                            1,\r
+                            NULL,\r
+                            NULL,\r
+                            NULL,\r
+                            NULL,\r
+                            &BootMaintMenuResetRequired\r
+                            );\r
+\r
+      if (BootMaintMenuResetRequired) {\r
+        EnableResetRequired ();\r
+      }\r
+\r
+      CallbackData->FeCurrentState    = INACTIVE_STATE;\r
+      CallbackData->FeDisplayContext  = UNKNOWN_CONTEXT;\r
+      ReclaimStringDepository ();\r
+    } else {\r
+      break;\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+VOID\r
+CreateCallbackPacket (\r
+  OUT EFI_HII_CALLBACK_PACKET         **Packet,\r
+  IN  UINT16                          Flags\r
+  )\r
+{\r
+  *Packet = (EFI_HII_CALLBACK_PACKET *) AllocateZeroPool (sizeof (EFI_HII_CALLBACK_PACKET) + 2);\r
+  ASSERT (*Packet != NULL);\r
+\r
+  (*Packet)->DataArray.EntryCount   = 1;\r
+  (*Packet)->DataArray.NvRamMap     = NULL;\r
+  ((EFI_IFR_DATA_ENTRY *) (&((*Packet)->DataArray) + 1))->Flags  = Flags;\r
+}\r