blob: e22aaf3039f13d5a4d222ee06e61c75f3d6554bd [file] [log] [blame]
/** @file
Provide boot option support for Application "BootMaint"
Include file system navigation, system handle selection
Boot option manipulation
Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "BootMaintenanceManager.h"
///
/// Define the maximum characters that will be accepted.
///
#define MAX_CHAR 480
/**
Check whether a reset is needed, if reset is needed, Popup a menu to notice user.
**/
VOID
BmmSetupResetReminder (
VOID
)
{
EFI_INPUT_KEY Key;
CHAR16 *StringBuffer1;
CHAR16 *StringBuffer2;
EFI_STATUS Status;
EDKII_FORM_BROWSER_EXTENSION2_PROTOCOL *FormBrowserEx2;
//
// Use BrowserEx2 protocol to check whether reset is required.
//
Status = gBS->LocateProtocol (&gEdkiiFormBrowserEx2ProtocolGuid, NULL, (VOID **)&FormBrowserEx2);
//
// check any reset required change is applied? if yes, reset system
//
if (!EFI_ERROR (Status) && FormBrowserEx2->IsResetRequired ()) {
StringBuffer1 = AllocateZeroPool (MAX_CHAR * sizeof (CHAR16));
ASSERT (StringBuffer1 != NULL);
StringBuffer2 = AllocateZeroPool (MAX_CHAR * sizeof (CHAR16));
ASSERT (StringBuffer2 != NULL);
StrCpyS (StringBuffer1, MAX_CHAR, L"Configuration changed. Reset to apply it Now.");
StrCpyS (StringBuffer2, MAX_CHAR, L"Press ENTER to reset");
//
// Popup a menu to notice user
//
do {
CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, StringBuffer1, StringBuffer2, NULL);
} while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
FreePool (StringBuffer1);
FreePool (StringBuffer2);
gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
}
}
/**
Create a menu entry by given menu type.
@param MenuType The Menu type to be created.
@retval NULL If failed to create the menu.
@return the new menu entry.
**/
BM_MENU_ENTRY *
BOpt_CreateMenuEntry (
UINTN MenuType
)
{
BM_MENU_ENTRY *MenuEntry;
UINTN ContextSize;
//
// Get context size according to menu type
//
switch (MenuType) {
case BM_LOAD_CONTEXT_SELECT:
ContextSize = sizeof (BM_LOAD_CONTEXT);
break;
case BM_FILE_CONTEXT_SELECT:
ContextSize = sizeof (BM_FILE_CONTEXT);
break;
case BM_CONSOLE_CONTEXT_SELECT:
ContextSize = sizeof (BM_CONSOLE_CONTEXT);
break;
case BM_TERMINAL_CONTEXT_SELECT:
ContextSize = sizeof (BM_TERMINAL_CONTEXT);
break;
case BM_HANDLE_CONTEXT_SELECT:
ContextSize = sizeof (BM_HANDLE_CONTEXT);
break;
default:
ContextSize = 0;
break;
}
if (ContextSize == 0) {
return NULL;
}
//
// Create new menu entry
//
MenuEntry = AllocateZeroPool (sizeof (BM_MENU_ENTRY));
if (MenuEntry == NULL) {
return NULL;
}
MenuEntry->VariableContext = AllocateZeroPool (ContextSize);
if (MenuEntry->VariableContext == NULL) {
FreePool (MenuEntry);
return NULL;
}
MenuEntry->Signature = BM_MENU_ENTRY_SIGNATURE;
MenuEntry->ContextSelection = MenuType;
return MenuEntry;
}
/**
Free up all resource allocated for a BM_MENU_ENTRY.
@param MenuEntry A pointer to BM_MENU_ENTRY.
**/
VOID
BOpt_DestroyMenuEntry (
BM_MENU_ENTRY *MenuEntry
)
{
BM_LOAD_CONTEXT *LoadContext;
BM_FILE_CONTEXT *FileContext;
BM_CONSOLE_CONTEXT *ConsoleContext;
BM_TERMINAL_CONTEXT *TerminalContext;
BM_HANDLE_CONTEXT *HandleContext;
//
// Select by the type in Menu entry for current context type
//
switch (MenuEntry->ContextSelection) {
case BM_LOAD_CONTEXT_SELECT:
LoadContext = (BM_LOAD_CONTEXT *)MenuEntry->VariableContext;
FreePool (LoadContext->FilePathList);
if (LoadContext->OptionalData != NULL) {
FreePool (LoadContext->OptionalData);
}
FreePool (LoadContext);
break;
case BM_FILE_CONTEXT_SELECT:
FileContext = (BM_FILE_CONTEXT *)MenuEntry->VariableContext;
if (!FileContext->IsRoot) {
FreePool (FileContext->DevicePath);
} else {
if (FileContext->FHandle != NULL) {
FileContext->FHandle->Close (FileContext->FHandle);
}
}
if (FileContext->FileName != NULL) {
FreePool (FileContext->FileName);
}
if (FileContext->Info != NULL) {
FreePool (FileContext->Info);
}
FreePool (FileContext);
break;
case BM_CONSOLE_CONTEXT_SELECT:
ConsoleContext = (BM_CONSOLE_CONTEXT *)MenuEntry->VariableContext;
FreePool (ConsoleContext->DevicePath);
FreePool (ConsoleContext);
break;
case BM_TERMINAL_CONTEXT_SELECT:
TerminalContext = (BM_TERMINAL_CONTEXT *)MenuEntry->VariableContext;
FreePool (TerminalContext->DevicePath);
FreePool (TerminalContext);
break;
case BM_HANDLE_CONTEXT_SELECT:
HandleContext = (BM_HANDLE_CONTEXT *)MenuEntry->VariableContext;
FreePool (HandleContext);
break;
default:
break;
}
FreePool (MenuEntry->DisplayString);
if (MenuEntry->HelpString != NULL) {
FreePool (MenuEntry->HelpString);
}
FreePool (MenuEntry);
}
/**
Get the Menu Entry from the list in Menu Entry List.
If MenuNumber is great or equal to the number of Menu
Entry in the list, then ASSERT.
@param MenuOption The Menu Entry List to read the menu entry.
@param MenuNumber The index of Menu Entry.
@return The Menu Entry.
**/
BM_MENU_ENTRY *
BOpt_GetMenuEntry (
BM_MENU_OPTION *MenuOption,
UINTN MenuNumber
)
{
BM_MENU_ENTRY *NewMenuEntry;
UINTN Index;
LIST_ENTRY *List;
ASSERT (MenuNumber < MenuOption->MenuNumber);
List = MenuOption->Head.ForwardLink;
for (Index = 0; Index < MenuNumber; Index++) {
List = List->ForwardLink;
}
NewMenuEntry = CR (List, BM_MENU_ENTRY, Link, BM_MENU_ENTRY_SIGNATURE);
return NewMenuEntry;
}
/**
Free resources allocated in Allocate Rountine.
@param FreeMenu Menu to be freed
**/
VOID
BOpt_FreeMenu (
BM_MENU_OPTION *FreeMenu
)
{
BM_MENU_ENTRY *MenuEntry;
while (!IsListEmpty (&FreeMenu->Head)) {
MenuEntry = CR (
FreeMenu->Head.ForwardLink,
BM_MENU_ENTRY,
Link,
BM_MENU_ENTRY_SIGNATURE
);
RemoveEntryList (&MenuEntry->Link);
BOpt_DestroyMenuEntry (MenuEntry);
}
FreeMenu->MenuNumber = 0;
}
/**
Build the BootOptionMenu according to BootOrder Variable.
This Routine will access the Boot#### to get EFI_LOAD_OPTION.
@param CallbackData The BMM context data.
@return EFI_NOT_FOUND Fail to find "BootOrder" variable.
@return EFI_SUCESS Success build boot option menu.
**/
EFI_STATUS
BOpt_GetBootOptions (
IN BMM_CALLBACK_DATA *CallbackData
)
{
UINTN Index;
UINT16 BootString[10];
UINT8 *LoadOptionFromVar;
UINTN BootOptionSize;
BOOLEAN BootNextFlag;
UINT16 *BootOrderList;
UINTN BootOrderListSize;
UINT16 *BootNext;
UINTN BootNextSize;
BM_MENU_ENTRY *NewMenuEntry;
BM_LOAD_CONTEXT *NewLoadContext;
UINT8 *LoadOptionPtr;
UINTN StringSize;
UINTN OptionalDataSize;
UINT8 *LoadOptionEnd;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
UINTN MenuCount;
UINT8 *Ptr;
EFI_BOOT_MANAGER_LOAD_OPTION *BootOption;
UINTN BootOptionCount;
MenuCount = 0;
BootOrderListSize = 0;
BootNextSize = 0;
BootOrderList = NULL;
BootNext = NULL;
LoadOptionFromVar = NULL;
BOpt_FreeMenu (&BootOptionMenu);
InitializeListHead (&BootOptionMenu.Head);
//
// Get the BootOrder from the Var
//
GetEfiGlobalVariable2 (L"BootOrder", (VOID **)&BootOrderList, &BootOrderListSize);
if (BootOrderList == NULL) {
return EFI_NOT_FOUND;
}
//
// Get the BootNext from the Var
//
GetEfiGlobalVariable2 (L"BootNext", (VOID **)&BootNext, &BootNextSize);
if (BootNext != NULL) {
if (BootNextSize != sizeof (UINT16)) {
FreePool (BootNext);
BootNext = NULL;
}
}
BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) {
//
// Don't display the hidden/inactive boot option
//
if (((BootOption[Index].Attributes & LOAD_OPTION_HIDDEN) != 0) || ((BootOption[Index].Attributes & LOAD_OPTION_ACTIVE) == 0)) {
continue;
}
UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", BootOrderList[Index]);
//
// Get all loadoptions from the VAR
//
GetEfiGlobalVariable2 (BootString, (VOID **)&LoadOptionFromVar, &BootOptionSize);
if (LoadOptionFromVar == NULL) {
continue;
}
if (BootNext != NULL) {
BootNextFlag = (BOOLEAN)(*BootNext == BootOrderList[Index]);
} else {
BootNextFlag = FALSE;
}
NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);
ASSERT (NULL != NewMenuEntry);
NewLoadContext = (BM_LOAD_CONTEXT *)NewMenuEntry->VariableContext;
LoadOptionPtr = LoadOptionFromVar;
LoadOptionEnd = LoadOptionFromVar + BootOptionSize;
NewMenuEntry->OptionNumber = BootOrderList[Index];
NewLoadContext->Deleted = FALSE;
NewLoadContext->IsBootNext = BootNextFlag;
//
// Is a Legacy Device?
//
Ptr = (UINT8 *)LoadOptionFromVar;
//
// Attribute = *(UINT32 *)Ptr;
//
Ptr += sizeof (UINT32);
//
// FilePathSize = *(UINT16 *)Ptr;
//
Ptr += sizeof (UINT16);
//
// Description = (CHAR16 *)Ptr;
//
Ptr += StrSize ((CHAR16 *)Ptr);
//
// Now Ptr point to Device Path
//
DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)Ptr;
if ((BBS_DEVICE_PATH == DevicePath->Type) && (BBS_BBS_DP == DevicePath->SubType)) {
NewLoadContext->IsLegacy = TRUE;
} else {
NewLoadContext->IsLegacy = FALSE;
}
//
// LoadOption is a pointer type of UINT8
// for easy use with following LOAD_OPTION
// embedded in this struct
//
NewLoadContext->Attributes = *(UINT32 *)LoadOptionPtr;
LoadOptionPtr += sizeof (UINT32);
NewLoadContext->FilePathListLength = *(UINT16 *)LoadOptionPtr;
LoadOptionPtr += sizeof (UINT16);
StringSize = StrSize ((UINT16 *)LoadOptionPtr);
NewLoadContext->Description = AllocateZeroPool (StrSize ((UINT16 *)LoadOptionPtr));
ASSERT (NewLoadContext->Description != NULL);
StrCpyS (NewLoadContext->Description, StrSize ((UINT16 *)LoadOptionPtr) / sizeof (UINT16), (UINT16 *)LoadOptionPtr);
ASSERT (NewLoadContext->Description != NULL);
NewMenuEntry->DisplayString = NewLoadContext->Description;
NewMenuEntry->DisplayStringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, NewMenuEntry->DisplayString, NULL);
LoadOptionPtr += StringSize;
NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength);
ASSERT (NewLoadContext->FilePathList != NULL);
CopyMem (
NewLoadContext->FilePathList,
(EFI_DEVICE_PATH_PROTOCOL *)LoadOptionPtr,
NewLoadContext->FilePathListLength
);
NewMenuEntry->HelpString = UiDevicePathToStr (NewLoadContext->FilePathList);
NewMenuEntry->HelpStringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, NewMenuEntry->HelpString, NULL);
LoadOptionPtr += NewLoadContext->FilePathListLength;
if (LoadOptionPtr < LoadOptionEnd) {
OptionalDataSize = BootOptionSize -
sizeof (UINT32) -
sizeof (UINT16) -
StringSize -
NewLoadContext->FilePathListLength;
NewLoadContext->OptionalData = AllocateZeroPool (OptionalDataSize);
ASSERT (NewLoadContext->OptionalData != NULL);
CopyMem (
NewLoadContext->OptionalData,
LoadOptionPtr,
OptionalDataSize
);
}
InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link);
MenuCount++;
FreePool (LoadOptionFromVar);
}
EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount);
if (BootNext != NULL) {
FreePool (BootNext);
}
if (BootOrderList != NULL) {
FreePool (BootOrderList);
}
BootOptionMenu.MenuNumber = MenuCount;
return EFI_SUCCESS;
}
/**
Find drivers that will be added as Driver#### variables from handles
in current system environment
All valid handles in the system except those consume SimpleFs, LoadFile
are stored in DriverMenu for future use.
@retval EFI_SUCCESS The function complets successfully.
@return Other value if failed to build the DriverMenu.
**/
EFI_STATUS
BOpt_FindDrivers (
VOID
)
{
UINTN NoDevicePathHandles;
EFI_HANDLE *DevicePathHandle;
UINTN Index;
EFI_STATUS Status;
BM_MENU_ENTRY *NewMenuEntry;
BM_HANDLE_CONTEXT *NewHandleContext;
EFI_HANDLE CurHandle;
UINTN OptionNumber;
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFs;
EFI_LOAD_FILE_PROTOCOL *LoadFile;
SimpleFs = NULL;
LoadFile = NULL;
InitializeListHead (&DriverMenu.Head);
//
// At first, get all handles that support Device Path
// protocol which is the basic requirement for
// Driver####
//
Status = gBS->LocateHandleBuffer (
ByProtocol,
&gEfiDevicePathProtocolGuid,
NULL,
&NoDevicePathHandles,
&DevicePathHandle
);
if (EFI_ERROR (Status)) {
return Status;
}
OptionNumber = 0;
for (Index = 0; Index < NoDevicePathHandles; Index++) {
CurHandle = DevicePathHandle[Index];
Status = gBS->HandleProtocol (
CurHandle,
&gEfiSimpleFileSystemProtocolGuid,
(VOID **)&SimpleFs
);
if (Status == EFI_SUCCESS) {
continue;
}
Status = gBS->HandleProtocol (
CurHandle,
&gEfiLoadFileProtocolGuid,
(VOID **)&LoadFile
);
if (Status == EFI_SUCCESS) {
continue;
}
NewMenuEntry = BOpt_CreateMenuEntry (BM_HANDLE_CONTEXT_SELECT);
if (NULL == NewMenuEntry) {
FreePool (DevicePathHandle);
return EFI_OUT_OF_RESOURCES;
}
NewHandleContext = (BM_HANDLE_CONTEXT *)NewMenuEntry->VariableContext;
NewHandleContext->Handle = CurHandle;
NewHandleContext->DevicePath = DevicePathFromHandle (CurHandle);
NewMenuEntry->DisplayString = UiDevicePathToStr (NewHandleContext->DevicePath);
NewMenuEntry->DisplayStringToken = HiiSetString (mBmmCallbackInfo->BmmHiiHandle, 0, NewMenuEntry->DisplayString, NULL);
NewMenuEntry->HelpString = NULL;
NewMenuEntry->HelpStringToken = NewMenuEntry->DisplayStringToken;
NewMenuEntry->OptionNumber = OptionNumber;
OptionNumber++;
InsertTailList (&DriverMenu.Head, &NewMenuEntry->Link);
}
if (DevicePathHandle != NULL) {
FreePool (DevicePathHandle);
}
DriverMenu.MenuNumber = OptionNumber;
return EFI_SUCCESS;
}
/**
Get the Option Number that has not been allocated for use.
@param Type The type of Option.
@return The available Option Number.
**/
UINT16
BOpt_GetOptionNumber (
CHAR16 *Type
)
{
UINT16 *OrderList;
UINTN OrderListSize;
UINTN Index;
CHAR16 StrTemp[20];
UINT16 *OptionBuffer;
UINT16 OptionNumber;
UINTN OptionSize;
OrderListSize = 0;
OrderList = NULL;
OptionNumber = 0;
Index = 0;
UnicodeSPrint (StrTemp, sizeof (StrTemp), L"%sOrder", Type);
GetEfiGlobalVariable2 (StrTemp, (VOID **)&OrderList, &OrderListSize);
for (OptionNumber = 0; ; OptionNumber++) {
if (OrderList != NULL) {
for (Index = 0; Index < OrderListSize / sizeof (UINT16); Index++) {
if (OptionNumber == OrderList[Index]) {
break;
}
}
}
if (Index < OrderListSize / sizeof (UINT16)) {
//
// The OptionNumber occurs in the OrderList, continue to use next one
//
continue;
}
UnicodeSPrint (StrTemp, sizeof (StrTemp), L"%s%04x", Type, (UINTN)OptionNumber);
DEBUG ((DEBUG_ERROR, "Option = %s\n", StrTemp));
GetEfiGlobalVariable2 (StrTemp, (VOID **)&OptionBuffer, &OptionSize);
if (NULL == OptionBuffer) {
//
// The Boot[OptionNumber] / Driver[OptionNumber] NOT occurs, we found it
//
break;
}
}
return OptionNumber;
}
/**
Get the Option Number for Boot#### that does not used.
@return The available Option Number.
**/
UINT16
BOpt_GetBootOptionNumber (
VOID
)
{
return BOpt_GetOptionNumber (L"Boot");
}
/**
Get the Option Number for Driver#### that does not used.
@return The unused Option Number.
**/
UINT16
BOpt_GetDriverOptionNumber (
VOID
)
{
return BOpt_GetOptionNumber (L"Driver");
}
/**
Build up all DriverOptionMenu
@param CallbackData The BMM context data.
@retval EFI_SUCESS The functin completes successfully.
@retval EFI_OUT_OF_RESOURCES Not enough memory to compete the operation.
@retval EFI_NOT_FOUND Fail to get "DriverOrder" variable.
**/
EFI_STATUS
BOpt_GetDriverOptions (
IN BMM_CALLBACK_DATA *CallbackData
)
{
UINTN Index;
UINT16 DriverString[12];
UINT8 *LoadOptionFromVar;
UINTN DriverOptionSize;
UINT16 *DriverOrderList;
UINTN DriverOrderListSize;
BM_MENU_ENTRY *NewMenuEntry;
BM_LOAD_CONTEXT *NewLoadContext;
UINT8 *LoadOptionPtr;
UINTN StringSize;
UINTN OptionalDataSize;
UINT8 *LoadOptionEnd;
DriverOrderListSize = 0;
DriverOrderList = NULL;
DriverOptionSize = 0;
LoadOptionFromVar = NULL;
BOpt_FreeMenu (&DriverOptionMenu);
InitializeListHead (&DriverOptionMenu.Head);
//
// Get the DriverOrder from the Var
//
GetEfiGlobalVariable2 (L"DriverOrder", (VOID **)&DriverOrderList, &DriverOrderListSize);
if (DriverOrderList == NULL) {
return EFI_NOT_FOUND;
}
for (Index = 0; Index < DriverOrderListSize / sizeof (UINT16); Index++) {
UnicodeSPrint (
DriverString,
sizeof (DriverString),
L"Driver%04x",
DriverOrderList[Index]
);
//
// Get all loadoptions from the VAR
//
GetEfiGlobalVariable2 (DriverString, (VOID **)&LoadOptionFromVar, &DriverOptionSize);
if (LoadOptionFromVar == NULL) {
continue;
}
NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);
if (NULL == NewMenuEntry) {
return EFI_OUT_OF_RESOURCES;
}
NewLoadContext = (BM_LOAD_CONTEXT *)NewMenuEntry->VariableContext;
LoadOptionPtr = LoadOptionFromVar;
LoadOptionEnd = LoadOptionFromVar + DriverOptionSize;
NewMenuEntry->OptionNumber = DriverOrderList[Index];
NewLoadContext->Deleted = FALSE;
NewLoadContext->IsLegacy = FALSE;
//
// LoadOption is a pointer type of UINT8
// for easy use with following LOAD_OPTION
// embedded in this struct
//
NewLoadContext->Attributes = *(UINT32 *)LoadOptionPtr;
LoadOptionPtr += sizeof (UINT32);
NewLoadContext->FilePathListLength = *(UINT16 *)LoadOptionPtr;
LoadOptionPtr += sizeof (UINT16);
StringSize = StrSize ((UINT16 *)LoadOptionPtr);
NewLoadContext->Description = AllocateZeroPool (StringSize);
ASSERT (NewLoadContext->Description != NULL);
CopyMem (
NewLoadContext->Description,
(UINT16 *)LoadOptionPtr,
StringSize
);
NewMenuEntry->DisplayString = NewLoadContext->Description;
NewMenuEntry->DisplayStringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, NewMenuEntry->DisplayString, NULL);
LoadOptionPtr += StringSize;
NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength);
ASSERT (NewLoadContext->FilePathList != NULL);
CopyMem (
NewLoadContext->FilePathList,
(EFI_DEVICE_PATH_PROTOCOL *)LoadOptionPtr,
NewLoadContext->FilePathListLength
);
NewMenuEntry->HelpString = UiDevicePathToStr (NewLoadContext->FilePathList);
NewMenuEntry->HelpStringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, NewMenuEntry->HelpString, NULL);
LoadOptionPtr += NewLoadContext->FilePathListLength;
if (LoadOptionPtr < LoadOptionEnd) {
OptionalDataSize = DriverOptionSize -
sizeof (UINT32) -
sizeof (UINT16) -
StringSize -
NewLoadContext->FilePathListLength;
NewLoadContext->OptionalData = AllocateZeroPool (OptionalDataSize);
ASSERT (NewLoadContext->OptionalData != NULL);
CopyMem (
NewLoadContext->OptionalData,
LoadOptionPtr,
OptionalDataSize
);
}
InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link);
FreePool (LoadOptionFromVar);
}
if (DriverOrderList != NULL) {
FreePool (DriverOrderList);
}
DriverOptionMenu.MenuNumber = Index;
return EFI_SUCCESS;
}
/**
Get option number according to Boot#### and BootOrder variable.
The value is saved as #### + 1.
@param CallbackData The BMM context data.
**/
VOID
GetBootOrder (
IN BMM_CALLBACK_DATA *CallbackData
)
{
BMM_FAKE_NV_DATA *BmmConfig;
UINT16 Index;
UINT16 OptionOrderIndex;
UINTN DeviceType;
BM_MENU_ENTRY *NewMenuEntry;
BM_LOAD_CONTEXT *NewLoadContext;
ASSERT (CallbackData != NULL);
DeviceType = (UINTN)-1;
BmmConfig = &CallbackData->BmmFakeNvData;
ZeroMem (BmmConfig->BootOptionOrder, sizeof (BmmConfig->BootOptionOrder));
for (Index = 0, OptionOrderIndex = 0; ((Index < BootOptionMenu.MenuNumber) &&
(OptionOrderIndex < (sizeof (BmmConfig->BootOptionOrder) / sizeof (BmmConfig->BootOptionOrder[0]))));
Index++)
{
NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);
NewLoadContext = (BM_LOAD_CONTEXT *)NewMenuEntry->VariableContext;
if (NewLoadContext->IsLegacy) {
if (((BBS_BBS_DEVICE_PATH *)NewLoadContext->FilePathList)->DeviceType != DeviceType) {
DeviceType = ((BBS_BBS_DEVICE_PATH *)NewLoadContext->FilePathList)->DeviceType;
} else {
//
// Only show one legacy boot option for the same device type
// assuming the boot options are grouped by the device type
//
continue;
}
}
BmmConfig->BootOptionOrder[OptionOrderIndex++] = (UINT32)(NewMenuEntry->OptionNumber + 1);
}
}
/**
Get driver option order from globalc DriverOptionMenu.
@param CallbackData The BMM context data.
**/
VOID
GetDriverOrder (
IN BMM_CALLBACK_DATA *CallbackData
)
{
BMM_FAKE_NV_DATA *BmmConfig;
UINT16 Index;
UINT16 OptionOrderIndex;
UINTN DeviceType;
BM_MENU_ENTRY *NewMenuEntry;
BM_LOAD_CONTEXT *NewLoadContext;
ASSERT (CallbackData != NULL);
DeviceType = (UINTN)-1;
BmmConfig = &CallbackData->BmmFakeNvData;
ZeroMem (BmmConfig->DriverOptionOrder, sizeof (BmmConfig->DriverOptionOrder));
for (Index = 0, OptionOrderIndex = 0; ((Index < DriverOptionMenu.MenuNumber) &&
(OptionOrderIndex < (sizeof (BmmConfig->DriverOptionOrder) / sizeof (BmmConfig->DriverOptionOrder[0]))));
Index++)
{
NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index);
NewLoadContext = (BM_LOAD_CONTEXT *)NewMenuEntry->VariableContext;
if (NewLoadContext->IsLegacy) {
if (((BBS_BBS_DEVICE_PATH *)NewLoadContext->FilePathList)->DeviceType != DeviceType) {
DeviceType = ((BBS_BBS_DEVICE_PATH *)NewLoadContext->FilePathList)->DeviceType;
} else {
//
// Only show one legacy boot option for the same device type
// assuming the boot options are grouped by the device type
//
continue;
}
}
BmmConfig->DriverOptionOrder[OptionOrderIndex++] = (UINT32)(NewMenuEntry->OptionNumber + 1);
}
}
/**
Boot the file specified by the input file path info.
@param FilePath Point to the file path.
@retval TRUE Exit caller function.
@retval FALSE Not exit caller function.
**/
BOOLEAN
EFIAPI
BootFromFile (
IN EFI_DEVICE_PATH_PROTOCOL *FilePath
)
{
EFI_STATUS Status;
EFI_BOOT_MANAGER_LOAD_OPTION BootOption;
CHAR16 *FileName;
Status = EFI_NOT_STARTED;
FileName = NULL;
FileName = ExtractFileNameFromDevicePath (FilePath);
if (FileName != NULL) {
Status = EfiBootManagerInitializeLoadOption (
&BootOption,
0,
LoadOptionTypeBoot,
LOAD_OPTION_ACTIVE,
FileName,
FilePath,
NULL,
0
);
}
if (!EFI_ERROR (Status)) {
//
// Since current no boot from removable media directly is allowed */
//
gST->ConOut->ClearScreen (gST->ConOut);
//
// Check whether need to reset system.
//
BmmSetupResetReminder ();
BmmSetConsoleMode (FALSE);
EfiBootManagerBoot (&BootOption);
BmmSetConsoleMode (TRUE);
FreePool (FileName);
EfiBootManagerFreeLoadOption (&BootOption);
}
return FALSE;
}
/**
Display the form base on the selected file.
@param FilePath Point to the file path.
@param FormId The form need to display.
**/
BOOLEAN
ReSendForm (
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
IN EFI_FORM_ID FormId
)
{
gBootMaintenancePrivate.LoadContext->FilePathList = FilePath;
UpdateOptionPage (&gBootMaintenancePrivate, FormId, FilePath);
gBootMaintenancePrivate.FormBrowser2->SendForm (
gBootMaintenancePrivate.FormBrowser2,
&gBootMaintenancePrivate.BmmHiiHandle,
1,
&mBootMaintGuid,
FormId,
NULL,
NULL
);
return TRUE;
}
/**
Create boot option base on the input file path info.
@param FilePath Point to the file path.
@retval TRUE Exit caller function.
@retval FALSE Not exit caller function.
**/
BOOLEAN
EFIAPI
CreateBootOptionFromFile (
IN EFI_DEVICE_PATH_PROTOCOL *FilePath
)
{
return ReSendForm (FilePath, FORM_BOOT_ADD_ID);
}
/**
Create driver option base on the input file path info.
@param FilePath Point to the file path.
@retval TRUE Exit caller function.
@retval FALSE Not exit caller function.
**/
BOOLEAN
EFIAPI
CreateDriverOptionFromFile (
IN EFI_DEVICE_PATH_PROTOCOL *FilePath
)
{
return ReSendForm (FilePath, FORM_DRV_ADD_FILE_ID);
}