audk/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/FileExplorer.c

340 lines
10 KiB
C

/*++
Copyright (c) 2006, Intel Corporation
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.
Module Name:
FileExplorer.c
AgBStract:
File explorer related functions.
--*/
#include "Bds.h"
#include "BootMaint.h"
VOID
UpdateFileExplorePage (
IN BMM_CALLBACK_DATA *CallbackData,
BM_MENU_OPTION *MenuOption
)
/*++
Routine Description:
Update the File Explore page.
Arguments:
MenuOption - Pointer to menu options to display.
Returns:
None.
--*/
{
UINT8 *Location;
UINTN Index;
BM_MENU_ENTRY *NewMenuEntry;
BM_FILE_CONTEXT *NewFileContext;
FORM_ID FormId;
NewMenuEntry = NULL;
NewFileContext = NULL;
FormId = 0;
//
// Clean up file explore page.
//
RefreshUpdateData (FALSE, 0, FALSE, 0, 0xff);
//
// Remove all op-codes from dynamic page
//
CallbackData->Hii->UpdateForm (
CallbackData->Hii,
CallbackData->FeHiiHandle,
FORM_FILE_EXPLORER_ID,
FALSE,
UpdateData
);
RefreshUpdateData (TRUE, (EFI_PHYSICAL_ADDRESS) (UINTN) CallbackData->FeCallbackHandle, FALSE, 0, 0);
Location = (UINT8 *) &UpdateData->Data;
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) || (BOOT_FROM_FILE_STATE == CallbackData->FeCurrentState)) {
//
// Create Text opcode for directory, also create Text opcode for file in BOOT_FROM_FILE_STATE.
//
CreateTextOpCode (
NewMenuEntry->DisplayStringToken,
STR_NULL_STRING,
STR_NULL_STRING,
EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,
(UINT16) (FILE_OPTION_OFFSET + Index),
Location
);
} else {
//
// Create Goto opcode for file in ADD_BOOT_OPTION_STATE or ADD_DRIVER_OPTION_STATE.
//
if (ADD_BOOT_OPTION_STATE == CallbackData->FeCurrentState) {
FormId = FORM_BOOT_ADD_DESCRIPTION_ID;
} else if (ADD_DRIVER_OPTION_STATE == CallbackData->FeCurrentState) {
FormId = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID;
}
CreateGotoOpCode (
FormId,
NewMenuEntry->DisplayStringToken,
STRING_TOKEN (STR_NULL_STRING),
EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,
(UINT16) (FILE_OPTION_OFFSET + Index),
Location
);
}
UpdateData->DataCount++;
Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;
}
CallbackData->Hii->UpdateForm (
CallbackData->Hii,
CallbackData->FeHiiHandle,
FORM_FILE_EXPLORER_ID,
TRUE,
UpdateData
);
}
BOOLEAN
UpdateFileExplorer (
IN BMM_CALLBACK_DATA *CallbackData,
IN UINT16 KeyValue
)
/*++
Routine Description:
Update the file explower page with the refershed file system.
Arguments:
CallbackData - BMM context data
KeyValue - Key value to identify the type of data to expect.
Returns:
TRUE - Inform the caller to create a callback packet to exit file explorer.
FALSE - Indicate that there is no need to exit file explorer.
--*/
{
UINT16 FileOptionMask;
BM_MENU_ENTRY *NewMenuEntry;
BM_FILE_CONTEXT *NewFileContext;
FORM_ID FormId;
BOOLEAN ExitFileExplorer;
EFI_STATUS Status;
NewMenuEntry = NULL;
NewFileContext = NULL;
ExitFileExplorer = FALSE;
FileOptionMask = (UINT16) (FILE_OPTION_MASK & KeyValue);
if (UNKNOWN_CONTEXT == CallbackData->FeDisplayContext) {
//
// First in, display file system.
//
BOpt_FreeMenu (&FsOptionMenu);
BOpt_FindFileSystem (CallbackData);
CreateMenuStringToken (CallbackData, CallbackData->FeHiiHandle, &FsOptionMenu);
UpdateFileExplorePage (CallbackData, &FsOptionMenu);
CallbackData->FeDisplayContext = FILE_SYSTEM;
} else {
if (FILE_SYSTEM == CallbackData->FeDisplayContext) {
NewMenuEntry = BOpt_GetMenuEntry (&FsOptionMenu, FileOptionMask);
} else if (DIRECTORY == CallbackData->FeDisplayContext) {
NewMenuEntry = BOpt_GetMenuEntry (&DirectoryMenu, FileOptionMask);
}
CallbackData->FeDisplayContext = DIRECTORY;
NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext;
if (NewFileContext->IsDir ) {
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 BOOT_FROM_FILE_STATE:
//
// Here boot from file
//
BootThisFile (NewFileContext);
ExitFileExplorer = TRUE;
break;
case ADD_BOOT_OPTION_STATE:
case ADD_DRIVER_OPTION_STATE:
if (ADD_BOOT_OPTION_STATE == 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;
//
// Clean up file explore page.
//
RefreshUpdateData (FALSE, 0, FALSE, 0, 1);
//
// Remove the Subtitle op-code.
//
CallbackData->Hii->UpdateForm (
CallbackData->Hii,
CallbackData->FeHiiHandle,
FormId,
FALSE,
UpdateData
);
//
// Create Subtitle op-code for the display string of the option.
//
RefreshUpdateData (TRUE, (EFI_PHYSICAL_ADDRESS) (UINTN) CallbackData->FeCallbackHandle, FALSE, 0, 1);
CreateSubTitleOpCode (
NewMenuEntry->DisplayStringToken,
&UpdateData->Data
);
CallbackData->Hii->UpdateForm (
CallbackData->Hii,
CallbackData->FeHiiHandle,
FormId,
TRUE,
UpdateData
);
break;
default:
break;
}
}
}
exit:
return ExitFileExplorer;
}
EFI_STATUS
EFIAPI
FileExplorerCallback (
IN EFI_FORM_CALLBACK_PROTOCOL *This,
IN UINT16 KeyValue,
IN EFI_IFR_DATA_ARRAY *Data,
OUT EFI_HII_CALLBACK_PACKET **Packet
)
/*++
Routine Description:
Callback Function for file exploration and file interaction.
Arguments:
This - File explorer callback protocol pointer.
KeyValue - Key value to identify the type of data to expect.
Data - A pointer to the data being sent to the original exporting driver.
Packet - A pointer to a packet of information which a driver passes back to the browser.
Returns:
EFI_SUCCESS - Callback ended successfully.
Others - Contain some errors.
--*/
{
BMM_CALLBACK_DATA *Private;
FILE_EXPLORER_NV_DATA *NvRamMap;
EFI_STATUS Status;
Status = EFI_SUCCESS;
Private = FE_CALLBACK_DATA_FROM_THIS (This);
UpdateData->FormCallbackHandle = (EFI_PHYSICAL_ADDRESS) (UINTN) Private->FeCallbackHandle;
NvRamMap = (FILE_EXPLORER_NV_DATA *) Data->NvRamMap;
if (KEY_VALUE_SAVE_AND_EXIT == KeyValue) {
//
// Apply changes and exit formset.
//
if (ADD_BOOT_OPTION_STATE == Private->FeCurrentState) {
Status = Var_UpdateBootOption (Private, NvRamMap);
if (EFI_ERROR (Status)) {
return Status;
}
BOpt_GetBootOptions (Private);
CreateMenuStringToken (Private, Private->FeHiiHandle, &BootOptionMenu);
} else if (ADD_DRIVER_OPTION_STATE == 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);
}
CreateCallbackPacket (Packet, EXIT_REQUIRED | NV_NOT_CHANGED);
} else if (KEY_VALUE_NO_SAVE_AND_EXIT == KeyValue) {
//
// Discard changes and exit formset.
//
NvRamMap->OptionalData[0] = 0x0000;
NvRamMap->DescriptionData[0] = 0x0000;
CreateCallbackPacket (Packet, EXIT_REQUIRED | NV_NOT_CHANGED);
} else if (KeyValue < FILE_OPTION_OFFSET) {
//
// Exit File Explorer formset.
//
CreateCallbackPacket (Packet, EXIT_REQUIRED);
} else {
if (UpdateFileExplorer (Private, KeyValue)) {
CreateCallbackPacket (Packet, EXIT_REQUIRED);
}
}
return Status;
}