/** @file The functions for Boot Maintainence Main menu. Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "BootMaint.h" #include "FormGuid.h" #include "Bds.h" #include "FrontPage.h" EFI_DEVICE_PATH_PROTOCOL EndDevicePath[] = { { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { END_DEVICE_PATH_LENGTH, 0 } } }; HII_VENDOR_DEVICE_PATH mBmmHiiVendorDevicePath = { { { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, { (UINT8) (sizeof (VENDOR_DEVICE_PATH)), (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) } }, BOOT_MAINT_FORMSET_GUID }, { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { (UINT8) (END_DEVICE_PATH_LENGTH), (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) } } }; HII_VENDOR_DEVICE_PATH mFeHiiVendorDevicePath = { { { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, { (UINT8) (sizeof (VENDOR_DEVICE_PATH)), (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) } }, FILE_EXPLORE_FORMSET_GUID }, { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { (UINT8) (END_DEVICE_PATH_LENGTH), (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) } } }; CHAR16 mBootMaintStorageName[] = L"BmmData"; CHAR16 mFileExplorerStorageName[] = L"FeData"; BMM_CALLBACK_DATA *mBmmCallbackInfo = NULL; /** Init all memu. @param CallbackData The BMM context data. **/ VOID InitAllMenu ( IN BMM_CALLBACK_DATA *CallbackData ); /** Free up all Menu Option list. **/ VOID FreeAllMenu ( VOID ); /** Initialize all of BMM configuration data in BmmFakeNvData and BmmOldFakeNVData member in BMM context data and create all of dynamic OP code for BMM. @param CallbackData The BMM context data. **/ VOID InitializeBmmConfig ( IN BMM_CALLBACK_DATA *CallbackData ) { BM_MENU_ENTRY *NewMenuEntry; BM_LOAD_CONTEXT *NewLoadContext; UINT16 Index; ASSERT (CallbackData != NULL); // // Initialize data which located in BMM main page // CallbackData->BmmFakeNvData.BootNext = (UINT16) (BootOptionMenu.MenuNumber); for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) { NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; if (NewLoadContext->IsBootNext) { CallbackData->BmmFakeNvData.BootNext = Index; break; } } CallbackData->BmmFakeNvData.BootTimeOut = PcdGet16 (PcdPlatformBootTimeOut); // // Initialize data which located in Boot Options Menu // GetBootOrder (CallbackData); GetLegacyDeviceOrder (CallbackData); // // Initialize data which located in Driver Options Menu // GetDriverOrder (CallbackData); // // Initialize data which located in Console Options Menu // GetConsoleOutMode (CallbackData); GetConsoleInCheck (CallbackData); GetConsoleOutCheck (CallbackData); GetConsoleErrCheck (CallbackData); GetTerminalAttribute (CallbackData); // // Backup Initialize BMM configuartion data to BmmOldFakeNVData // CopyMem (&CallbackData->BmmOldFakeNVData, &CallbackData->BmmFakeNvData, sizeof (BMM_FAKE_NV_DATA)); } /** Create string tokens for a menu from its help strings and display strings @param CallbackData The BMM context data. @param HiiHandle Hii Handle of the package to be updated. @param MenuOption The Menu whose string tokens need to be created @retval EFI_SUCCESS String tokens created successfully @retval others contain some errors **/ EFI_STATUS CreateMenuStringToken ( IN BMM_CALLBACK_DATA *CallbackData, IN EFI_HII_HANDLE HiiHandle, IN BM_MENU_OPTION *MenuOption ) { BM_MENU_ENTRY *NewMenuEntry; UINTN Index; for (Index = 0; Index < MenuOption->MenuNumber; Index++) { NewMenuEntry = BOpt_GetMenuEntry (MenuOption, Index); NewMenuEntry->DisplayStringToken = HiiSetString ( HiiHandle, 0, NewMenuEntry->DisplayString, NULL ); if (NULL == NewMenuEntry->HelpString) { NewMenuEntry->HelpStringToken = NewMenuEntry->DisplayStringToken; } else { NewMenuEntry->HelpStringToken = HiiSetString ( HiiHandle, 0, NewMenuEntry->HelpString, NULL ); } } return EFI_SUCCESS; } /** This function allows a caller to extract the current configuration for one or more named elements from the target driver. @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. @param Request A null-terminated Unicode string in format. @param Progress On return, points to a character in the Request string. Points to the string's null terminator if request was successful. Points to the most recent '&' before the first failing name/value pair (or the beginning of the string if the failure is in the first name/value pair) if the request was not successful. @param Results A null-terminated Unicode string in format which has all values filled in for the names in the Request string. String to be allocated by the called function. @retval EFI_SUCCESS The Results is filled with the requested values. @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results. @retval EFI_INVALID_PARAMETER Request is NULL, illegal syntax, or unknown name. @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. **/ EFI_STATUS EFIAPI BootMaintExtractConfig ( IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, IN CONST EFI_STRING Request, OUT EFI_STRING *Progress, OUT EFI_STRING *Results ) { EFI_STATUS Status; UINTN BufferSize; BMM_CALLBACK_DATA *Private; EFI_STRING ConfigRequestHdr; EFI_STRING ConfigRequest; BOOLEAN AllocatedRequest; UINTN Size; if (Progress == NULL || Results == NULL) { return EFI_INVALID_PARAMETER; } *Progress = Request; if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gBootMaintFormSetGuid, mBootMaintStorageName)) { return EFI_NOT_FOUND; } ConfigRequestHdr = NULL; ConfigRequest = NULL; AllocatedRequest = FALSE; Size = 0; Private = BMM_CALLBACK_DATA_FROM_THIS (This); // // Convert buffer data to by helper function BlockToConfig() // BufferSize = sizeof (BMM_FAKE_NV_DATA); ConfigRequest = Request; if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) { // // Request has no request element, construct full request string. // Allocate and fill a buffer large enough to hold the template // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator // ConfigRequestHdr = HiiConstructConfigHdr (&gBootMaintFormSetGuid, mBootMaintStorageName, Private->BmmDriverHandle); Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16); ConfigRequest = AllocateZeroPool (Size); ASSERT (ConfigRequest != NULL); AllocatedRequest = TRUE; UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize); FreePool (ConfigRequestHdr); } Status = gHiiConfigRouting->BlockToConfig ( gHiiConfigRouting, ConfigRequest, (UINT8 *) &Private->BmmFakeNvData, BufferSize, Results, Progress ); // // Free the allocated config request string. // if (AllocatedRequest) { FreePool (ConfigRequest); ConfigRequest = NULL; } // // Set Progress string to the original request string. // if (Request == NULL) { *Progress = NULL; } else if (StrStr (Request, L"OFFSET") == NULL) { *Progress = Request + StrLen (Request); } return Status; } /** This function applies changes in a driver's configuration. Input is a Configuration, which has the routing data for this driver followed by name / value configuration pairs. The driver must apply those pairs to its configurable storage. If the driver's configuration is stored in a linear block of data and the driver's name / value pairs are in format, it may use the ConfigToBlock helper function (above) to simplify the job. Currently not implemented. @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. @param[in] Configuration A null-terminated Unicode string in format. @param[out] Progress A pointer to a string filled in with the offset of the most recent '&' before the first failing name / value pair (or the beginn ing of the string if the failure is in the first name / value pair) or the terminating NULL if all was successful. @retval EFI_SUCCESS The results have been distributed or are awaiting distribution. @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the results that must be stored awaiting possible future protocols. @retval EFI_INVALID_PARAMETERS Passing in a NULL for the Results parameter would result in this type of error. @retval EFI_NOT_FOUND Target for the specified routing data was not found. **/ EFI_STATUS EFIAPI BootMaintRouteConfig ( IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, IN CONST EFI_STRING Configuration, OUT EFI_STRING *Progress ) { EFI_STATUS Status; UINTN BufferSize; EFI_HII_CONFIG_ROUTING_PROTOCOL *ConfigRouting; BMM_FAKE_NV_DATA *NewBmmData; BMM_FAKE_NV_DATA *OldBmmData; BM_CONSOLE_CONTEXT *NewConsoleContext; BM_TERMINAL_CONTEXT *NewTerminalContext; BM_MENU_ENTRY *NewMenuEntry; BM_LOAD_CONTEXT *NewLoadContext; UINT16 Index; BOOLEAN TerminalAttChange; BMM_CALLBACK_DATA *Private; if (Progress == NULL) { return EFI_INVALID_PARAMETER; } *Progress = Configuration; if (Configuration == NULL) { return EFI_INVALID_PARAMETER; } // // Check routing data in . // Note: there is no name for Name/Value storage, only GUID will be checked // if (!HiiIsConfigHdrMatch (Configuration, &gBootMaintFormSetGuid, mBootMaintStorageName)) { return EFI_NOT_FOUND; } Status = gBS->LocateProtocol ( &gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID**) &ConfigRouting ); if (EFI_ERROR (Status)) { return Status; } Private = BMM_CALLBACK_DATA_FROM_THIS (This); // // Get Buffer Storage data from EFI variable // BufferSize = sizeof (BMM_FAKE_NV_DATA); OldBmmData = &Private->BmmOldFakeNVData; NewBmmData = &Private->BmmFakeNvData; // // Convert to buffer data by helper function ConfigToBlock() // Status = ConfigRouting->ConfigToBlock ( ConfigRouting, Configuration, (UINT8 *) NewBmmData, &BufferSize, Progress ); ASSERT_EFI_ERROR (Status); // // Compare new and old BMM configuration data and only do action for modified item to // avoid setting unnecessary non-volatile variable // // // Check data which located in BMM main page and save the settings if need // if (CompareMem (NewBmmData->LegacyFD, OldBmmData->LegacyFD, sizeof (NewBmmData->LegacyFD)) != 0) { Var_UpdateBBSOption (Private, FORM_SET_FD_ORDER_ID); } if (CompareMem (NewBmmData->LegacyHD, OldBmmData->LegacyHD, sizeof (NewBmmData->LegacyHD)) != 0) { Var_UpdateBBSOption (Private, FORM_SET_HD_ORDER_ID); } if (CompareMem (NewBmmData->LegacyCD, OldBmmData->LegacyCD, sizeof (NewBmmData->LegacyCD)) != 0) { Var_UpdateBBSOption (Private, FORM_SET_CD_ORDER_ID); } if (CompareMem (NewBmmData->LegacyNET, OldBmmData->LegacyNET, sizeof (NewBmmData->LegacyNET)) != 0) { Var_UpdateBBSOption (Private, FORM_SET_NET_ORDER_ID); } if (CompareMem (NewBmmData->LegacyBEV, OldBmmData->LegacyBEV, sizeof (NewBmmData->LegacyBEV)) != 0) { Var_UpdateBBSOption (Private, FORM_SET_BEV_ORDER_ID); } // // Change for "delete boot option" page need update NewBmmData->BootOptionOrder, so process // NewBmmData->BootOptionOrder before NewBmmData->BootOptionDel // if (CompareMem (NewBmmData->BootOptionOrder, OldBmmData->BootOptionOrder, sizeof (NewBmmData->BootOptionOrder)) != 0) { Status = Var_UpdateBootOrder (Private); } // // Change for "delete driver option" page need update NewBmmData->DriverOptionOrder, so process // NewBmmData->DriverOptionOrder before NewBmmData->DriverOptionDel // if (CompareMem (NewBmmData->DriverOptionOrder, OldBmmData->DriverOptionOrder, sizeof (NewBmmData->DriverOptionOrder)) != 0) { Status = Var_UpdateDriverOrder (Private); } // // Check data which located in Boot Options Menu and save the settings if need // if (CompareMem (NewBmmData->BootOptionDel, OldBmmData->BootOptionDel, sizeof (NewBmmData->BootOptionDel)) != 0) { for (Index = 0; ((Index < BootOptionMenu.MenuNumber) && (Index < (sizeof (NewBmmData->BootOptionDel) / sizeof (NewBmmData->BootOptionDel[0])))); Index ++) { NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; NewLoadContext->Deleted = NewBmmData->BootOptionDel[Index]; NewBmmData->BootOptionDel[Index] = FALSE; NewBmmData->BootOptionDelMark[Index] = FALSE; } Var_DelBootOption (); } // // Check data which located in Driver Options Menu and save the settings if need // if (CompareMem (NewBmmData->DriverOptionDel, OldBmmData->DriverOptionDel, sizeof (NewBmmData->DriverOptionDel)) != 0) { for (Index = 0; ((Index < DriverOptionMenu.MenuNumber) && (Index < (sizeof (NewBmmData->DriverOptionDel) / sizeof (NewBmmData->DriverOptionDel[0])))); Index++) { NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index); NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; NewLoadContext->Deleted = NewBmmData->DriverOptionDel[Index]; NewBmmData->DriverOptionDel[Index] = FALSE; NewBmmData->DriverOptionDelMark[Index] = FALSE; } Var_DelDriverOption (); } if (CompareMem (&NewBmmData->BootTimeOut, &OldBmmData->BootTimeOut, sizeof (NewBmmData->BootTimeOut)) != 0) { Status = gRT->SetVariable ( L"Timeout", &gEfiGlobalVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, sizeof (UINT16), &(NewBmmData->BootTimeOut) ); ASSERT_EFI_ERROR(Status); // // Bugbug: code not exit in UiApp but in IntelFrameworkModulePkg, need do more check. // Private->BmmOldFakeNVData.BootTimeOut = NewBmmData->BootTimeOut; } if (CompareMem (&NewBmmData->BootNext, &OldBmmData->BootNext, sizeof (NewBmmData->BootNext)) != 0) { Status = Var_UpdateBootNext (Private); } if (CompareMem (&NewBmmData->ConsoleOutMode, &OldBmmData->ConsoleOutMode, sizeof (NewBmmData->ConsoleOutMode)) != 0) { Var_UpdateConMode (Private); } TerminalAttChange = FALSE; for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { // // only need update modified items // if (CompareMem (&NewBmmData->COMBaudRate[Index], &OldBmmData->COMBaudRate[Index], sizeof (NewBmmData->COMBaudRate[Index])) == 0 && CompareMem (&NewBmmData->COMDataRate[Index], &OldBmmData->COMDataRate[Index], sizeof (NewBmmData->COMDataRate[Index])) == 0 && CompareMem (&NewBmmData->COMStopBits[Index], &OldBmmData->COMStopBits[Index], sizeof (NewBmmData->COMStopBits[Index])) == 0 && CompareMem (&NewBmmData->COMParity[Index], &OldBmmData->COMParity[Index], sizeof (NewBmmData->COMParity[Index])) == 0 && CompareMem (&NewBmmData->COMTerminalType[Index], &OldBmmData->COMTerminalType[Index], sizeof (NewBmmData->COMTerminalType[Index])) == 0 && CompareMem (&NewBmmData->COMFlowControl[Index], &OldBmmData->COMFlowControl[Index], sizeof (NewBmmData->COMFlowControl[Index])) == 0) { continue; } NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); ASSERT (NewMenuEntry != NULL); NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; NewTerminalContext->BaudRateIndex = NewBmmData->COMBaudRate[Index]; ASSERT (NewBmmData->COMBaudRate[Index] < (ARRAY_SIZE (BaudRateList))); NewTerminalContext->BaudRate = BaudRateList[NewBmmData->COMBaudRate[Index]].Value; NewTerminalContext->DataBitsIndex = NewBmmData->COMDataRate[Index]; ASSERT (NewBmmData->COMDataRate[Index] < (ARRAY_SIZE (DataBitsList))); NewTerminalContext->DataBits = (UINT8) DataBitsList[NewBmmData->COMDataRate[Index]].Value; NewTerminalContext->StopBitsIndex = NewBmmData->COMStopBits[Index]; ASSERT (NewBmmData->COMStopBits[Index] < (ARRAY_SIZE (StopBitsList))); NewTerminalContext->StopBits = (UINT8) StopBitsList[NewBmmData->COMStopBits[Index]].Value; NewTerminalContext->ParityIndex = NewBmmData->COMParity[Index]; ASSERT (NewBmmData->COMParity[Index] < (ARRAY_SIZE (ParityList))); NewTerminalContext->Parity = (UINT8) ParityList[NewBmmData->COMParity[Index]].Value; NewTerminalContext->TerminalType = NewBmmData->COMTerminalType[Index]; NewTerminalContext->FlowControl = NewBmmData->COMFlowControl[Index]; ChangeTerminalDevicePath ( &(NewTerminalContext->DevicePath), FALSE ); TerminalAttChange = TRUE; } if (TerminalAttChange) { Var_UpdateConsoleInpOption (); Var_UpdateConsoleOutOption (); Var_UpdateErrorOutOption (); } // // Check data which located in Console Options Menu and save the settings if need // if (CompareMem (NewBmmData->ConsoleInCheck, OldBmmData->ConsoleInCheck, sizeof (NewBmmData->ConsoleInCheck)) != 0) { for (Index = 0; Index < ConsoleInpMenu.MenuNumber; Index++) { NewMenuEntry = BOpt_GetMenuEntry (&ConsoleInpMenu, Index); NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; ASSERT (Index < MAX_MENU_NUMBER); NewConsoleContext->IsActive = NewBmmData->ConsoleInCheck[Index]; } Var_UpdateConsoleInpOption (); } if (CompareMem (NewBmmData->ConsoleOutCheck, OldBmmData->ConsoleOutCheck, sizeof (NewBmmData->ConsoleOutCheck)) != 0) { for (Index = 0; Index < ConsoleOutMenu.MenuNumber; Index++) { NewMenuEntry = BOpt_GetMenuEntry (&ConsoleOutMenu, Index); NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; ASSERT (Index < MAX_MENU_NUMBER); NewConsoleContext->IsActive = NewBmmData->ConsoleOutCheck[Index]; } Var_UpdateConsoleOutOption (); } if (CompareMem (NewBmmData->ConsoleErrCheck, OldBmmData->ConsoleErrCheck, sizeof (NewBmmData->ConsoleErrCheck)) != 0) { for (Index = 0; Index < ConsoleErrMenu.MenuNumber; Index++) { NewMenuEntry = BOpt_GetMenuEntry (&ConsoleErrMenu, Index); NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; ASSERT (Index < MAX_MENU_NUMBER); NewConsoleContext->IsActive = NewBmmData->ConsoleErrCheck[Index]; } Var_UpdateErrorOutOption (); } // // After user do the save action, need to update OldBmmData. // CopyMem (OldBmmData, NewBmmData, sizeof (BMM_FAKE_NV_DATA)); return EFI_SUCCESS; } /** Create GoTo OP code into FORM_BOOT_LEGACY_DEVICE label for legacy boot option. **/ EFI_STATUS InitializeLegacyBootOption ( VOID ) { RefreshUpdateData (); mStartLabel->Number = FORM_BOOT_LEGACY_DEVICE_ID; // // If LegacyBios Protocol is installed, add 3 tags about legacy boot option // in BootOption form: legacy FD/HD/CD/NET/BEV // HiiCreateGotoOpCode ( mStartOpCodeHandle, FORM_SET_FD_ORDER_ID, STRING_TOKEN (STR_FORM_SET_FD_ORDER_TITLE), STRING_TOKEN (STR_FORM_SET_FD_ORDER_TITLE), EFI_IFR_FLAG_CALLBACK, FORM_SET_FD_ORDER_ID ); HiiCreateGotoOpCode ( mStartOpCodeHandle, FORM_SET_HD_ORDER_ID, STRING_TOKEN (STR_FORM_SET_HD_ORDER_TITLE), STRING_TOKEN (STR_FORM_SET_HD_ORDER_TITLE), EFI_IFR_FLAG_CALLBACK, FORM_SET_HD_ORDER_ID ); HiiCreateGotoOpCode ( mStartOpCodeHandle, FORM_SET_CD_ORDER_ID, STRING_TOKEN (STR_FORM_SET_CD_ORDER_TITLE), STRING_TOKEN (STR_FORM_SET_CD_ORDER_TITLE), EFI_IFR_FLAG_CALLBACK, FORM_SET_CD_ORDER_ID ); HiiCreateGotoOpCode ( mStartOpCodeHandle, FORM_SET_NET_ORDER_ID, STRING_TOKEN (STR_FORM_SET_NET_ORDER_TITLE), STRING_TOKEN (STR_FORM_SET_NET_ORDER_TITLE), EFI_IFR_FLAG_CALLBACK, FORM_SET_NET_ORDER_ID ); HiiCreateGotoOpCode ( mStartOpCodeHandle, FORM_SET_BEV_ORDER_ID, STRING_TOKEN (STR_FORM_SET_BEV_ORDER_TITLE), STRING_TOKEN (STR_FORM_SET_BEV_ORDER_TITLE), EFI_IFR_FLAG_CALLBACK, FORM_SET_BEV_ORDER_ID ); HiiUpdateForm ( mBmmCallbackInfo->BmmHiiHandle, &gBootMaintFormSetGuid, FORM_BOOT_SETUP_ID, mStartOpCodeHandle, // Label FORM_BOOT_LEGACY_DEVICE_ID mEndOpCodeHandle // LABEL_END ); return EFI_SUCCESS; } /** This function processes the results of changes in configuration. @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. @param Action Specifies the type of action taken by the browser. @param QuestionId A unique value which is sent to the original exporting driver so that it can identify the type of data to expect. @param Type The type of value for the question. @param Value A pointer to the data being sent to the original exporting driver. @param ActionRequest On return, points to the action requested by the callback function. @retval EFI_SUCCESS The callback successfully handled the action. @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. @retval EFI_DEVICE_ERROR The variable could not be saved. @retval EFI_UNSUPPORTED The specified Action is not supported by the callback. @retval EFI_INVALID_PARAMETER The parameter of Value or ActionRequest is invalid. **/ EFI_STATUS EFIAPI BootMaintCallback ( IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, IN EFI_BROWSER_ACTION Action, IN EFI_QUESTION_ID QuestionId, IN UINT8 Type, IN EFI_IFR_TYPE_VALUE *Value, OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest ) { BMM_CALLBACK_DATA *Private; BM_MENU_ENTRY *NewMenuEntry; BMM_FAKE_NV_DATA *CurrentFakeNVMap; EFI_STATUS Status; UINTN OldValue; UINTN NewValue; UINTN Number; UINTN Pos; UINTN Bit; UINT16 NewValuePos; UINT16 Index3; UINT16 Index2; UINT16 Index; UINT8 *OldLegacyDev; UINT8 *NewLegacyDev; UINT8 *DisMap; EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; Private = BMM_CALLBACK_DATA_FROM_THIS (This); if (Action == EFI_BROWSER_ACTION_FORM_OPEN && QuestionId == FORM_BOOT_SETUP_ID) { // // Initilize Form for legacy boot option. // Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios); if (!EFI_ERROR (Status)) { InitializeLegacyBootOption (); } return EFI_SUCCESS; } if (Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_CHANGED) { // // All other action return unsupported. // return EFI_UNSUPPORTED; } Status = EFI_SUCCESS; OldValue = 0; NewValue = 0; Number = 0; OldLegacyDev = NULL; NewLegacyDev = NULL; NewValuePos = 0; DisMap = NULL; Private = BMM_CALLBACK_DATA_FROM_THIS (This); // // Retrieve uncommitted data from Form Browser // CurrentFakeNVMap = &Private->BmmFakeNvData; HiiGetBrowserData (&gBootMaintFormSetGuid, mBootMaintStorageName, sizeof (BMM_FAKE_NV_DATA), (UINT8 *) CurrentFakeNVMap); if (Action == EFI_BROWSER_ACTION_CHANGING) { if (Value == NULL) { return EFI_INVALID_PARAMETER; } UpdatePageId (Private, QuestionId); if (QuestionId < FILE_OPTION_OFFSET) { if (QuestionId < CONFIG_OPTION_OFFSET) { switch (QuestionId) { case KEY_VALUE_BOOT_FROM_FILE: Private->FeCurrentState = FileExplorerStateBootFromFile; break; case FORM_BOOT_ADD_ID: Private->FeCurrentState = FileExplorerStateAddBootOption; break; case FORM_DRV_ADD_FILE_ID: Private->FeCurrentState = FileExplorerStateAddDriverOptionState; break; case FORM_DRV_ADD_HANDLE_ID: CleanUpPage (FORM_DRV_ADD_HANDLE_ID, Private); UpdateDrvAddHandlePage (Private); break; case FORM_BOOT_DEL_ID: CleanUpPage (FORM_BOOT_DEL_ID, Private); UpdateBootDelPage (Private); break; case FORM_BOOT_CHG_ID: case FORM_DRV_CHG_ID: UpdatePageBody (QuestionId, Private); break; case FORM_DRV_DEL_ID: CleanUpPage (FORM_DRV_DEL_ID, Private); UpdateDrvDelPage (Private); break; case FORM_BOOT_NEXT_ID: CleanUpPage (FORM_BOOT_NEXT_ID, Private); UpdateBootNextPage (Private); break; case FORM_TIME_OUT_ID: CleanUpPage (FORM_TIME_OUT_ID, Private); UpdateTimeOutPage (Private); break; case FORM_CON_IN_ID: case FORM_CON_OUT_ID: case FORM_CON_ERR_ID: UpdatePageBody (QuestionId, Private); break; case FORM_CON_MODE_ID: CleanUpPage (FORM_CON_MODE_ID, Private); UpdateConModePage (Private); break; case FORM_CON_COM_ID: CleanUpPage (FORM_CON_COM_ID, Private); UpdateConCOMPage (Private); break; case FORM_SET_FD_ORDER_ID: case FORM_SET_HD_ORDER_ID: case FORM_SET_CD_ORDER_ID: case FORM_SET_NET_ORDER_ID: case FORM_SET_BEV_ORDER_ID: CleanUpPage (QuestionId, Private); UpdateSetLegacyDeviceOrderPage (QuestionId, Private); break; default: break; } } else if ((QuestionId >= TERMINAL_OPTION_OFFSET) && (QuestionId < CONSOLE_OPTION_OFFSET)) { Index2 = (UINT16) (QuestionId - TERMINAL_OPTION_OFFSET); Private->CurrentTerminal = Index2; CleanUpPage (FORM_CON_COM_SETUP_ID, Private); UpdateTerminalPage (Private); } else if (QuestionId >= HANDLE_OPTION_OFFSET) { Index2 = (UINT16) (QuestionId - HANDLE_OPTION_OFFSET); NewMenuEntry = BOpt_GetMenuEntry (&DriverMenu, Index2); ASSERT (NewMenuEntry != NULL); Private->HandleContext = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext; CleanUpPage (FORM_DRV_ADD_HANDLE_DESC_ID, Private); Private->MenuEntry = NewMenuEntry; Private->LoadContext->FilePathList = Private->HandleContext->DevicePath; UpdateDriverAddHandleDescPage (Private); } } } else if (Action == EFI_BROWSER_ACTION_CHANGED) { if ((Value == NULL) || (ActionRequest == NULL)) { return EFI_INVALID_PARAMETER; } if ((QuestionId >= BOOT_OPTION_DEL_QUESTION_ID) && (QuestionId < BOOT_OPTION_DEL_QUESTION_ID + MAX_MENU_NUMBER)) { if (Value->b){ // // Means user try to delete this boot option but not press F10 or "Commit Changes and Exit" menu. // CurrentFakeNVMap->BootOptionDelMark[QuestionId - BOOT_OPTION_DEL_QUESTION_ID] = TRUE; } else { // // Means user remove the old check status. // CurrentFakeNVMap->BootOptionDelMark[QuestionId - BOOT_OPTION_DEL_QUESTION_ID] = FALSE; } } else if ((QuestionId >= DRIVER_OPTION_DEL_QUESTION_ID) && (QuestionId < DRIVER_OPTION_DEL_QUESTION_ID + MAX_MENU_NUMBER)) { if (Value->b){ CurrentFakeNVMap->DriverOptionDelMark[QuestionId - DRIVER_OPTION_DEL_QUESTION_ID] = TRUE; } else { CurrentFakeNVMap->DriverOptionDelMark[QuestionId - DRIVER_OPTION_DEL_QUESTION_ID] = FALSE; } } else if ((QuestionId >= LEGACY_FD_QUESTION_ID) && (QuestionId < LEGACY_BEV_QUESTION_ID + MAX_MENU_NUMBER)) { // // Update Select FD/HD/CD/NET/BEV Order Form // DisMap = Private->BmmOldFakeNVData.DisableMap; if (QuestionId >= LEGACY_FD_QUESTION_ID && QuestionId < LEGACY_FD_QUESTION_ID + MAX_MENU_NUMBER) { Number = (UINT16) LegacyFDMenu.MenuNumber; OldLegacyDev = Private->BmmOldFakeNVData.LegacyFD; NewLegacyDev = CurrentFakeNVMap->LegacyFD; } else if (QuestionId >= LEGACY_HD_QUESTION_ID && QuestionId < LEGACY_HD_QUESTION_ID + MAX_MENU_NUMBER) { Number = (UINT16) LegacyHDMenu.MenuNumber; OldLegacyDev = Private->BmmOldFakeNVData.LegacyHD; NewLegacyDev = CurrentFakeNVMap->LegacyHD; } else if (QuestionId >= LEGACY_CD_QUESTION_ID && QuestionId < LEGACY_CD_QUESTION_ID + MAX_MENU_NUMBER) { Number = (UINT16) LegacyCDMenu.MenuNumber; OldLegacyDev = Private->BmmOldFakeNVData.LegacyCD; NewLegacyDev = CurrentFakeNVMap->LegacyCD; } else if (QuestionId >= LEGACY_NET_QUESTION_ID && QuestionId < LEGACY_NET_QUESTION_ID + MAX_MENU_NUMBER) { Number = (UINT16) LegacyNETMenu.MenuNumber; OldLegacyDev = Private->BmmOldFakeNVData.LegacyNET; NewLegacyDev = CurrentFakeNVMap->LegacyNET; } else if (QuestionId >= LEGACY_BEV_QUESTION_ID && QuestionId < LEGACY_BEV_QUESTION_ID + MAX_MENU_NUMBER) { Number = (UINT16) LegacyBEVMenu.MenuNumber; OldLegacyDev = Private->BmmOldFakeNVData.LegacyBEV; NewLegacyDev = CurrentFakeNVMap->LegacyBEV; } // // First, find the different position // if there is change, it should be only one // for (Index = 0; Index < Number; Index++) { if (OldLegacyDev[Index] != NewLegacyDev[Index]) { OldValue = OldLegacyDev[Index]; NewValue = NewLegacyDev[Index]; break; } } if (Index != Number) { // // there is change, now process // if (0xFF == NewValue) { // // This item will be disable // Just move the items behind this forward to overlap it // Pos = OldValue / 8; Bit = 7 - (OldValue % 8); DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit)); for (Index2 = Index; Index2 < Number - 1; Index2++) { NewLegacyDev[Index2] = NewLegacyDev[Index2 + 1]; } NewLegacyDev[Index2] = 0xFF; } else { for (Index2 = 0; Index2 < Number; Index2++) { if (Index2 == Index) { continue; } if (OldLegacyDev[Index2] == NewValue) { // // If NewValue is in OldLegacyDev array // remember its old position // NewValuePos = Index2; break; } } if (Index2 != Number) { // // We will change current item to an existing item // (It's hard to describe here, please read code, it's like a cycle-moving) // for (Index2 = NewValuePos; Index2 != Index;) { if (NewValuePos < Index) { NewLegacyDev[Index2] = OldLegacyDev[Index2 + 1]; Index2++; } else { NewLegacyDev[Index2] = OldLegacyDev[Index2 - 1]; Index2--; } } } else { // // If NewValue is not in OldlegacyDev array, we are changing to a disabled item // so we should modify DisMap to reflect the change // Pos = NewValue / 8; Bit = 7 - (NewValue % 8); DisMap[Pos] = (UINT8) (DisMap[Pos] & (~ (UINT8) (1 << Bit))); if (0xFF != OldValue) { // // Because NewValue is a item that was disabled before // so after changing the OldValue should be disabled // actually we are doing a swap of enable-disable states of two items // Pos = OldValue / 8; Bit = 7 - (OldValue % 8); DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit)); } } } // // To prevent DISABLE appears in the middle of the list // we should perform a re-ordering // Index3 = Index; Index = 0; while (Index < Number) { if (0xFF != NewLegacyDev[Index]) { Index++; continue; } Index2 = Index; Index2++; while (Index2 < Number) { if (0xFF != NewLegacyDev[Index2]) { break; } Index2++; } if (Index2 < Number) { NewLegacyDev[Index] = NewLegacyDev[Index2]; NewLegacyDev[Index2] = 0xFF; } Index++; } // // Return correct question value. // Value->u8 = NewLegacyDev[Index3]; } } else { switch (QuestionId) { case KEY_VALUE_SAVE_AND_EXIT: *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT; break; case KEY_VALUE_NO_SAVE_AND_EXIT: // // Restore local maintain data. // DiscardChangeHandler (Private, CurrentFakeNVMap); *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT; break; case FORM_RESET: gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); return EFI_UNSUPPORTED; default: break; } } } // // Pass changed uncommitted data back to Form Browser // HiiSetBrowserData (&gBootMaintFormSetGuid, mBootMaintStorageName, sizeof (BMM_FAKE_NV_DATA), (UINT8 *) CurrentFakeNVMap, NULL); return EFI_SUCCESS; } /** Discard all changes done to the BMM pages such as Boot Order change, Driver order change. @param Private The BMM context data. @param CurrentFakeNVMap The current Fack NV Map. **/ VOID DiscardChangeHandler ( IN BMM_CALLBACK_DATA *Private, IN BMM_FAKE_NV_DATA *CurrentFakeNVMap ) { UINT16 Index; switch (Private->BmmPreviousPageId) { case FORM_BOOT_CHG_ID: CopyMem (CurrentFakeNVMap->BootOptionOrder, Private->BmmOldFakeNVData.BootOptionOrder, sizeof (CurrentFakeNVMap->BootOptionOrder)); break; case FORM_DRV_CHG_ID: CopyMem (CurrentFakeNVMap->DriverOptionOrder, Private->BmmOldFakeNVData.DriverOptionOrder, sizeof (CurrentFakeNVMap->DriverOptionOrder)); break; case FORM_BOOT_DEL_ID: ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CurrentFakeNVMap->BootOptionDel) / sizeof (CurrentFakeNVMap->BootOptionDel[0]))); for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) { CurrentFakeNVMap->BootOptionDel[Index] = FALSE; CurrentFakeNVMap->BootOptionDelMark[Index] = FALSE; } break; case FORM_DRV_DEL_ID: ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CurrentFakeNVMap->DriverOptionDel) / sizeof (CurrentFakeNVMap->DriverOptionDel[0]))); for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) { CurrentFakeNVMap->DriverOptionDel[Index] = FALSE; CurrentFakeNVMap->DriverOptionDelMark[Index] = FALSE; } break; case FORM_BOOT_NEXT_ID: CurrentFakeNVMap->BootNext = Private->BmmOldFakeNVData.BootNext; break; case FORM_TIME_OUT_ID: CurrentFakeNVMap->BootTimeOut = Private->BmmOldFakeNVData.BootTimeOut; break; case FORM_DRV_ADD_HANDLE_DESC_ID: case FORM_DRV_ADD_FILE_ID: case FORM_DRV_ADD_HANDLE_ID: CurrentFakeNVMap->DriverAddHandleDesc[0] = 0x0000; CurrentFakeNVMap->DriverAddHandleOptionalData[0] = 0x0000; break; default: break; } } /** Initialize the Boot Maintenance Utitliy. @retval EFI_SUCCESS utility ended successfully @retval others contain some errors **/ EFI_STATUS InitializeBM ( VOID ) { BMM_CALLBACK_DATA *BmmCallbackInfo; EFI_STATUS Status; EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader; UINT32 Length; UINT8 *Data; Status = EFI_SUCCESS; BmmCallbackInfo = mBmmCallbackInfo; BmmCallbackInfo->BmmPreviousPageId = FORM_MAIN_ID; BmmCallbackInfo->BmmCurrentPageId = FORM_MAIN_ID; BmmCallbackInfo->FeCurrentState = FileExplorerStateInActive; BmmCallbackInfo->FeDisplayContext = FileExplorerDisplayUnknown; // // Reinstall String packages to include more new strings. // // // String package size // Length = ReadUnaligned32 ((UINT32 *) BdsDxeStrings) - sizeof (UINT32); // // Add the length of the Package List Header and the terminating Package Header // Length += sizeof (EFI_HII_PACKAGE_LIST_HEADER) + sizeof (EFI_HII_PACKAGE_HEADER); // // Allocate the storage for the entire Package List // PackageListHeader = AllocateZeroPool (Length); // // If the Package List can not be allocated, then return a NULL HII Handle // if (PackageListHeader == NULL) { return EFI_OUT_OF_RESOURCES; } // // Fill in the GUID and Length of the Package List Header // PackageListHeader->PackageLength = Length; // // Copy String Data into Package list. // Data = (UINT8 *)(PackageListHeader + 1); Length = ReadUnaligned32 ((UINT32 *) BdsDxeStrings) - sizeof (UINT32); CopyMem (Data, (UINT8 *) BdsDxeStrings + sizeof (UINT32), Length); // // Add End type HII package. // Data += Length; ((EFI_HII_PACKAGE_HEADER *) Data)->Type = EFI_HII_PACKAGE_END; ((EFI_HII_PACKAGE_HEADER *) Data)->Length = sizeof (EFI_HII_PACKAGE_HEADER); // // Update String package for BM // CopyGuid (&PackageListHeader->PackageListGuid, &gBootMaintFormSetGuid); Status = gHiiDatabase->UpdatePackageList (gHiiDatabase, BmmCallbackInfo->BmmHiiHandle, PackageListHeader); // // Update String package for FE. // CopyGuid (&PackageListHeader->PackageListGuid, &gFileExploreFormSetGuid); Status = gHiiDatabase->UpdatePackageList (gHiiDatabase, BmmCallbackInfo->FeHiiHandle, PackageListHeader); FreePool (PackageListHeader); // // Init OpCode Handle and Allocate space for creation of Buffer // mStartOpCodeHandle = HiiAllocateOpCodeHandle (); if (mStartOpCodeHandle == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Exit; } mEndOpCodeHandle = HiiAllocateOpCodeHandle (); if (mEndOpCodeHandle == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Exit; } // // Create Hii Extend Label OpCode as the start opcode // mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (mStartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; // // Create Hii Extend Label OpCode as the end opcode // mEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (mEndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); mEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; mEndLabel->Number = LABEL_END; InitializeStringDepository (); InitAllMenu (BmmCallbackInfo); CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleInpMenu); CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleOutMenu); CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleErrMenu); CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &BootOptionMenu); CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverOptionMenu); CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &TerminalMenu); CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverMenu); InitializeBmmConfig (BmmCallbackInfo); // // Dispatch BMM main formset and File Explorer formset. // FormSetDispatcher (BmmCallbackInfo); // // Clean up. // CleanUpStringDepository (); FreeAllMenu (); Exit: if (mStartOpCodeHandle != NULL) { HiiFreeOpCodeHandle (mStartOpCodeHandle); } if (mEndOpCodeHandle != NULL) { HiiFreeOpCodeHandle (mEndOpCodeHandle); } return Status; } /** Initialized all Menu Option List. @param CallbackData The BMM context data. **/ VOID InitAllMenu ( IN BMM_CALLBACK_DATA *CallbackData ) { InitializeListHead (&BootOptionMenu.Head); InitializeListHead (&DriverOptionMenu.Head); BOpt_GetBootOptions (CallbackData); BOpt_GetDriverOptions (CallbackData); BOpt_GetLegacyOptions (); InitializeListHead (&FsOptionMenu.Head); BOpt_FindDrivers (); InitializeListHead (&DirectoryMenu.Head); InitializeListHead (&ConsoleInpMenu.Head); InitializeListHead (&ConsoleOutMenu.Head); InitializeListHead (&ConsoleErrMenu.Head); InitializeListHead (&TerminalMenu.Head); LocateSerialIo (); GetAllConsoles (); } /** Free up all Menu Option list. **/ VOID FreeAllMenu ( VOID ) { BOpt_FreeMenu (&DirectoryMenu); BOpt_FreeMenu (&FsOptionMenu); BOpt_FreeMenu (&BootOptionMenu); BOpt_FreeMenu (&DriverOptionMenu); BOpt_FreeMenu (&DriverMenu); BOpt_FreeLegacyOptions (); FreeAllConsoles (); } /** Initialize all the string depositories. **/ VOID InitializeStringDepository ( VOID ) { STRING_DEPOSITORY *StringDepository; StringDepository = AllocateZeroPool (sizeof (STRING_DEPOSITORY) * STRING_DEPOSITORY_NUMBER); FileOptionStrDepository = StringDepository++; ConsoleOptionStrDepository = StringDepository++; BootOptionStrDepository = StringDepository++; BootOptionHelpStrDepository = StringDepository++; DriverOptionStrDepository = StringDepository++; DriverOptionHelpStrDepository = StringDepository++; TerminalStrDepository = StringDepository; } /** Fetch a usable string node from the string depository and return the string token. @param CallbackData The BMM context data. @param StringDepository The string repository. @retval EFI_STRING_ID String token. **/ EFI_STRING_ID GetStringTokenFromDepository ( IN BMM_CALLBACK_DATA *CallbackData, IN STRING_DEPOSITORY *StringDepository ) { STRING_LIST_NODE *CurrentListNode; STRING_LIST_NODE *NextListNode; CurrentListNode = StringDepository->CurrentNode; if ((NULL != CurrentListNode) && (NULL != CurrentListNode->Next)) { // // Fetch one reclaimed node from the list. // NextListNode = StringDepository->CurrentNode->Next; } else { // // If there is no usable node in the list, update the list. // NextListNode = AllocateZeroPool (sizeof (STRING_LIST_NODE)); ASSERT (NextListNode != NULL); NextListNode->StringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, L" ", NULL); ASSERT (NextListNode->StringToken != 0); StringDepository->TotalNodeNumber++; if (NULL == CurrentListNode) { StringDepository->ListHead = NextListNode; } else { CurrentListNode->Next = NextListNode; } } StringDepository->CurrentNode = NextListNode; return StringDepository->CurrentNode->StringToken; } /** Reclaim string depositories by moving the current node pointer to list head.. **/ VOID ReclaimStringDepository ( VOID ) { UINTN DepositoryIndex; STRING_DEPOSITORY *StringDepository; StringDepository = FileOptionStrDepository; for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) { StringDepository->CurrentNode = StringDepository->ListHead; StringDepository++; } } /** Release resource for all the string depositories. **/ VOID CleanUpStringDepository ( VOID ) { UINTN NodeIndex; UINTN DepositoryIndex; STRING_LIST_NODE *CurrentListNode; STRING_LIST_NODE *NextListNode; STRING_DEPOSITORY *StringDepository; // // Release string list nodes. // StringDepository = FileOptionStrDepository; for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) { CurrentListNode = StringDepository->ListHead; for (NodeIndex = 0; NodeIndex < StringDepository->TotalNodeNumber; NodeIndex++) { NextListNode = CurrentListNode->Next; FreePool (CurrentListNode); CurrentListNode = NextListNode; } StringDepository++; } // // Release string depository. // FreePool (FileOptionStrDepository); } /** Start boot maintenance manager @retval EFI_SUCCESS If BMM is invoked successfully. @return Other value if BMM return unsuccessfully. **/ EFI_STATUS BdsStartBootMaint ( VOID ) { EFI_STATUS Status; LIST_ENTRY BdsBootOptionList; InitializeListHead (&BdsBootOptionList); // // Connect all prior to entering the platform setup menu. // if (!gConnectAllHappened) { BdsLibConnectAllDriversToAllControllers (); gConnectAllHappened = TRUE; } // // Have chance to enumerate boot device // BdsLibEnumerateAllBootOption (&BdsBootOptionList); // // Group the legacy boot options for the same device type // GroupMultipleLegacyBootOption4SameType (); // // Init the BMM // Status = InitializeBM (); return Status; } /** Dispatch BMM formset and FileExplorer formset. @param CallbackData The BMM context data. @retval EFI_SUCCESS If function complete successfully. @return Other value if the Setup Browser process BMM's pages and return unsuccessfully. **/ EFI_STATUS FormSetDispatcher ( IN BMM_CALLBACK_DATA *CallbackData ) { EFI_STATUS Status; EFI_BROWSER_ACTION_REQUEST ActionRequest; while (TRUE) { UpdatePageId (CallbackData, FORM_MAIN_ID); ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; Status = gFormBrowser2->SendForm ( gFormBrowser2, &CallbackData->BmmHiiHandle, 1, &gBootMaintFormSetGuid, 0, NULL, &ActionRequest ); if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) { EnableResetRequired (); } ReclaimStringDepository (); // // When this Formset returns, check if we are going to explore files. // if (FileExplorerStateInActive != CallbackData->FeCurrentState) { UpdateFileExplorer (CallbackData, 0); ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; Status = gFormBrowser2->SendForm ( gFormBrowser2, &CallbackData->FeHiiHandle, 1, &gFileExploreFormSetGuid, 0, NULL, &ActionRequest ); if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) { EnableResetRequired (); } CallbackData->FeCurrentState = FileExplorerStateInActive; CallbackData->FeDisplayContext = FileExplorerDisplayUnknown; ReclaimStringDepository (); } else { break; } } return Status; } /** Intall BootMaint and FileExplorer HiiPackages. **/ EFI_STATUS InitBMPackage ( VOID ) { BMM_CALLBACK_DATA *BmmCallbackInfo; EFI_STATUS Status; UINT8 *Ptr; // // Create CallbackData structures for Driver Callback // BmmCallbackInfo = AllocateZeroPool (sizeof (BMM_CALLBACK_DATA)); if (BmmCallbackInfo == NULL) { return EFI_OUT_OF_RESOURCES; } // // Create LoadOption in BmmCallbackInfo for Driver Callback // Ptr = AllocateZeroPool (sizeof (BM_LOAD_CONTEXT) + sizeof (BM_FILE_CONTEXT) + sizeof (BM_HANDLE_CONTEXT) + sizeof (BM_MENU_ENTRY)); if (Ptr == NULL) { FreePool (BmmCallbackInfo); BmmCallbackInfo = NULL; return EFI_OUT_OF_RESOURCES; } // // Initialize Bmm callback data. // BmmCallbackInfo->LoadContext = (BM_LOAD_CONTEXT *) Ptr; Ptr += sizeof (BM_LOAD_CONTEXT); BmmCallbackInfo->FileContext = (BM_FILE_CONTEXT *) Ptr; Ptr += sizeof (BM_FILE_CONTEXT); BmmCallbackInfo->HandleContext = (BM_HANDLE_CONTEXT *) Ptr; Ptr += sizeof (BM_HANDLE_CONTEXT); BmmCallbackInfo->MenuEntry = (BM_MENU_ENTRY *) Ptr; BmmCallbackInfo->Signature = BMM_CALLBACK_DATA_SIGNATURE; BmmCallbackInfo->BmmConfigAccess.ExtractConfig = BootMaintExtractConfig; BmmCallbackInfo->BmmConfigAccess.RouteConfig = BootMaintRouteConfig; BmmCallbackInfo->BmmConfigAccess.Callback = BootMaintCallback; BmmCallbackInfo->FeConfigAccess.ExtractConfig = FakeExtractConfig; BmmCallbackInfo->FeConfigAccess.RouteConfig = FileExplorerRouteConfig; BmmCallbackInfo->FeConfigAccess.Callback = FileExplorerCallback; // // Install Device Path Protocol and Config Access protocol to driver handle // Status = gBS->InstallMultipleProtocolInterfaces ( &BmmCallbackInfo->BmmDriverHandle, &gEfiDevicePathProtocolGuid, &mBmmHiiVendorDevicePath, &gEfiHiiConfigAccessProtocolGuid, &BmmCallbackInfo->BmmConfigAccess, NULL ); ASSERT_EFI_ERROR (Status); // // Install Device Path Protocol and Config Access protocol to driver handle // Status = gBS->InstallMultipleProtocolInterfaces ( &BmmCallbackInfo->FeDriverHandle, &gEfiDevicePathProtocolGuid, &mFeHiiVendorDevicePath, &gEfiHiiConfigAccessProtocolGuid, &BmmCallbackInfo->FeConfigAccess, NULL ); ASSERT_EFI_ERROR (Status); // // Post our Boot Maint VFR binary to the HII database. // BmmCallbackInfo->BmmHiiHandle = HiiAddPackages ( &gBootMaintFormSetGuid, BmmCallbackInfo->BmmDriverHandle, BmBin, BdsDxeStrings, NULL ); ASSERT (BmmCallbackInfo->BmmHiiHandle != NULL); // // Post our File Explorer VFR binary to the HII database. // BmmCallbackInfo->FeHiiHandle = HiiAddPackages ( &gFileExploreFormSetGuid, BmmCallbackInfo->FeDriverHandle, FEBin, BdsDxeStrings, NULL ); ASSERT (BmmCallbackInfo->FeHiiHandle != NULL); mBmmCallbackInfo = BmmCallbackInfo; return EFI_SUCCESS; } /** Remvoe the intalled BootMaint and FileExplorer HiiPackages. **/ VOID FreeBMPackage ( VOID ) { BMM_CALLBACK_DATA *BmmCallbackInfo; BmmCallbackInfo = mBmmCallbackInfo; // // Remove our IFR data from HII database // HiiRemovePackages (BmmCallbackInfo->BmmHiiHandle); HiiRemovePackages (BmmCallbackInfo->FeHiiHandle); if (BmmCallbackInfo->FeDriverHandle != NULL) { gBS->UninstallMultipleProtocolInterfaces ( BmmCallbackInfo->FeDriverHandle, &gEfiDevicePathProtocolGuid, &mFeHiiVendorDevicePath, &gEfiHiiConfigAccessProtocolGuid, &BmmCallbackInfo->FeConfigAccess, NULL ); } if (BmmCallbackInfo->BmmDriverHandle != NULL) { gBS->UninstallMultipleProtocolInterfaces ( BmmCallbackInfo->BmmDriverHandle, &gEfiDevicePathProtocolGuid, &mBmmHiiVendorDevicePath, &gEfiHiiConfigAccessProtocolGuid, &BmmCallbackInfo->BmmConfigAccess, NULL ); } FreePool (BmmCallbackInfo->LoadContext); FreePool (BmmCallbackInfo); mBmmCallbackInfo = NULL; return; }