--- /dev/null
+/*++ \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 "Bds.h"\r
+#include "BootMaint.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, (VOID**)&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, (VOID**) &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, (VOID**) &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