| /** @file | |
| File explorer related functions. | |
| Copyright (c) 2004 - 2009, Intel Corporation. <BR> | |
| All rights reserved. This program and the accompanying materials | |
| are licensed and made available under the terms and conditions of the BSD License | |
| which accompanies this distribution. The full text of the license may be found at | |
| http://opensource.org/licenses/bsd-license.php | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
| **/ | |
| #include "BootMaint.h" | |
| /** | |
| Update the File Explore page. | |
| @param CallbackData The BMM context data. | |
| @param MenuOption Pointer to menu options to display. | |
| **/ | |
| VOID | |
| UpdateFileExplorePage ( | |
| IN BMM_CALLBACK_DATA *CallbackData, | |
| BM_MENU_OPTION *MenuOption | |
| ) | |
| { | |
| UINTN Index; | |
| BM_MENU_ENTRY *NewMenuEntry; | |
| BM_FILE_CONTEXT *NewFileContext; | |
| EFI_FORM_ID FormId; | |
| NewMenuEntry = NULL; | |
| NewFileContext = NULL; | |
| FormId = 0; | |
| RefreshUpdateData (); | |
| mStartLabel->Number = FORM_FILE_EXPLORER_ID; | |
| for (Index = 0; Index < MenuOption->MenuNumber; Index++) { | |
| NewMenuEntry = BOpt_GetMenuEntry (MenuOption, Index); | |
| NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext; | |
| if (NewFileContext->IsBootLegacy) { | |
| continue; | |
| } | |
| if ((NewFileContext->IsDir) || (FileExplorerStateBootFromFile == CallbackData->FeCurrentState)) { | |
| // | |
| // Create Text opcode for directory, also create Text opcode for file in FileExplorerStateBootFromFile. | |
| // | |
| HiiCreateActionOpCode ( | |
| mStartOpCodeHandle, | |
| (UINT16) (FILE_OPTION_OFFSET + Index), | |
| NewMenuEntry->DisplayStringToken, | |
| STRING_TOKEN (STR_NULL_STRING), | |
| EFI_IFR_FLAG_CALLBACK, | |
| 0 | |
| ); | |
| } else { | |
| // | |
| // Create Goto opcode for file in FileExplorerStateAddBootOption or FileExplorerStateAddDriverOptionState. | |
| // | |
| if (FileExplorerStateAddBootOption == CallbackData->FeCurrentState) { | |
| FormId = FORM_BOOT_ADD_DESCRIPTION_ID; | |
| } else if (FileExplorerStateAddDriverOptionState == CallbackData->FeCurrentState) { | |
| FormId = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID; | |
| } | |
| HiiCreateGotoOpCode ( | |
| mStartOpCodeHandle, | |
| FormId, | |
| NewMenuEntry->DisplayStringToken, | |
| STRING_TOKEN (STR_NULL_STRING), | |
| EFI_IFR_FLAG_CALLBACK, | |
| (UINT16) (FILE_OPTION_OFFSET + Index) | |
| ); | |
| } | |
| } | |
| HiiUpdateForm ( | |
| CallbackData->FeHiiHandle, | |
| &mFileExplorerGuid, | |
| FORM_FILE_EXPLORER_ID, | |
| mStartOpCodeHandle, // Label FORM_FILE_EXPLORER_ID | |
| mEndOpCodeHandle // LABEL_END | |
| ); | |
| } | |
| /** | |
| Update the file explower page with the refershed file system. | |
| @param CallbackData BMM context data | |
| @param KeyValue Key value to identify the type of data to expect. | |
| @retval TRUE Inform the caller to create a callback packet to exit file explorer. | |
| @retval FALSE Indicate that there is no need to exit file explorer. | |
| **/ | |
| BOOLEAN | |
| UpdateFileExplorer ( | |
| IN BMM_CALLBACK_DATA *CallbackData, | |
| IN UINT16 KeyValue | |
| ) | |
| { | |
| UINT16 FileOptionMask; | |
| BM_MENU_ENTRY *NewMenuEntry; | |
| BM_FILE_CONTEXT *NewFileContext; | |
| EFI_FORM_ID FormId; | |
| BOOLEAN ExitFileExplorer; | |
| EFI_STATUS Status; | |
| NewMenuEntry = NULL; | |
| NewFileContext = NULL; | |
| ExitFileExplorer = FALSE; | |
| FileOptionMask = (UINT16) (FILE_OPTION_MASK & KeyValue); | |
| if (FileExplorerDisplayUnknown == CallbackData->FeDisplayContext) { | |
| // | |
| // First in, display file system. | |
| // | |
| BOpt_FreeMenu (&FsOptionMenu); | |
| BOpt_FindFileSystem (CallbackData); | |
| CreateMenuStringToken (CallbackData, CallbackData->FeHiiHandle, &FsOptionMenu); | |
| UpdateFileExplorePage (CallbackData, &FsOptionMenu); | |
| CallbackData->FeDisplayContext = FileExplorerDisplayFileSystem; | |
| } else { | |
| if (FileExplorerDisplayFileSystem == CallbackData->FeDisplayContext) { | |
| NewMenuEntry = BOpt_GetMenuEntry (&FsOptionMenu, FileOptionMask); | |
| } else if (FileExplorerDisplayDirectory == CallbackData->FeDisplayContext) { | |
| NewMenuEntry = BOpt_GetMenuEntry (&DirectoryMenu, FileOptionMask); | |
| } | |
| NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext; | |
| if (NewFileContext->IsDir ) { | |
| CallbackData->FeDisplayContext = FileExplorerDisplayDirectory; | |
| RemoveEntryList (&NewMenuEntry->Link); | |
| BOpt_FreeMenu (&DirectoryMenu); | |
| Status = BOpt_FindFiles (CallbackData, NewMenuEntry); | |
| if (EFI_ERROR (Status)) { | |
| ExitFileExplorer = TRUE; | |
| goto exit; | |
| } | |
| CreateMenuStringToken (CallbackData, CallbackData->FeHiiHandle, &DirectoryMenu); | |
| BOpt_DestroyMenuEntry (NewMenuEntry); | |
| UpdateFileExplorePage (CallbackData, &DirectoryMenu); | |
| } else { | |
| switch (CallbackData->FeCurrentState) { | |
| case FileExplorerStateBootFromFile: | |
| // | |
| // Here boot from file | |
| // | |
| BootThisFile (NewFileContext); | |
| ExitFileExplorer = TRUE; | |
| break; | |
| case FileExplorerStateAddBootOption: | |
| case FileExplorerStateAddDriverOptionState: | |
| if (FileExplorerStateAddBootOption == CallbackData->FeCurrentState) { | |
| FormId = FORM_BOOT_ADD_DESCRIPTION_ID; | |
| } else { | |
| FormId = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID; | |
| } | |
| CallbackData->MenuEntry = NewMenuEntry; | |
| CallbackData->LoadContext->FilePathList = ((BM_FILE_CONTEXT *) (CallbackData->MenuEntry->VariableContext))->DevicePath; | |
| // | |
| // Create Subtitle op-code for the display string of the option. | |
| // | |
| RefreshUpdateData (); | |
| mStartLabel->Number = FormId; | |
| HiiCreateSubTitleOpCode ( | |
| mStartOpCodeHandle, | |
| NewMenuEntry->DisplayStringToken, | |
| 0, | |
| 0, | |
| 0 | |
| ); | |
| HiiUpdateForm ( | |
| CallbackData->FeHiiHandle, | |
| &mFileExplorerGuid, | |
| FormId, | |
| mStartOpCodeHandle, // Label FormId | |
| mEndOpCodeHandle // LABEL_END | |
| ); | |
| break; | |
| default: | |
| break; | |
| } | |
| } | |
| } | |
| exit: | |
| return ExitFileExplorer; | |
| } | |
| /** | |
| This function processes the results of changes in configuration. | |
| When user select a interactive opcode, this callback will be triggered. | |
| Based on the Question(QuestionId) that triggers the callback, the corresponding | |
| actions is performed. It handles: | |
| 1) the addition of boot option. | |
| 2) the addition of driver option. | |
| 3) exit from file browser | |
| 4) update of file content if a dir is selected. | |
| 5) boot the file if a file is selected in "boot from file" | |
| @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 If paramter Value or ActionRequest is NULL. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| FileExplorerCallback ( | |
| 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; | |
| FILE_EXPLORER_NV_DATA *NvRamMap; | |
| EFI_STATUS Status; | |
| if ((Value == NULL) || (ActionRequest == NULL)) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| Status = EFI_SUCCESS; | |
| Private = FE_CALLBACK_DATA_FROM_THIS (This); | |
| *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; | |
| // | |
| // Retrieve uncommitted data from Form Browser | |
| // | |
| NvRamMap = &Private->FeFakeNvData; | |
| HiiGetBrowserData (&mFileExplorerGuid, mFileExplorerStorageName, sizeof (FILE_EXPLORER_NV_DATA), (UINT8 *) NvRamMap); | |
| if (QuestionId == KEY_VALUE_SAVE_AND_EXIT_BOOT || QuestionId == KEY_VALUE_SAVE_AND_EXIT_DRIVER) { | |
| // | |
| // Apply changes and exit formset | |
| // | |
| if (FileExplorerStateAddBootOption == Private->FeCurrentState) { | |
| Status = Var_UpdateBootOption (Private, NvRamMap); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| BOpt_GetBootOptions (Private); | |
| CreateMenuStringToken (Private, Private->FeHiiHandle, &BootOptionMenu); | |
| } else if (FileExplorerStateAddDriverOptionState == Private->FeCurrentState) { | |
| Status = Var_UpdateDriverOption ( | |
| Private, | |
| Private->FeHiiHandle, | |
| NvRamMap->DescriptionData, | |
| NvRamMap->OptionalData, | |
| NvRamMap->ForceReconnect | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| BOpt_GetDriverOptions (Private); | |
| CreateMenuStringToken (Private, Private->FeHiiHandle, &DriverOptionMenu); | |
| } | |
| *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; | |
| } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_BOOT || QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER) { | |
| // | |
| // Discard changes and exit formset | |
| // | |
| NvRamMap->OptionalData[0] = 0x0000; | |
| NvRamMap->DescriptionData[0] = 0x0000; | |
| *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; | |
| } else if (QuestionId < FILE_OPTION_OFFSET) { | |
| // | |
| // Exit File Explorer formset | |
| // | |
| *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; | |
| } else { | |
| if (UpdateFileExplorer (Private, QuestionId)) { | |
| *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; | |
| } | |
| } | |
| return Status; | |
| } |