audk/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootOption.c

1756 lines
51 KiB
C

/** @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 "BootMaint.h"
#include "BBSsupport.h"
/**
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;
case BM_LEGACY_DEV_CONTEXT_SELECT:
ContextSize = sizeof (BM_LEGACY_DEVICE_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;
BM_LEGACY_DEVICE_CONTEXT *LegacyDevContext;
//
// 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);
FreePool (LoadContext->LoadOption);
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;
case BM_LEGACY_DEV_CONTEXT_SELECT:
LegacyDevContext = (BM_LEGACY_DEVICE_CONTEXT *) MenuEntry->VariableContext;
FreePool (LegacyDevContext);
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;
}
/**
This function build the FsOptionMenu list which records all
available file system in the system. They includes all instances
of EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, all instances of EFI_LOAD_FILE_SYSTEM
and all type of legacy boot device.
@param CallbackData BMM context data
@retval EFI_SUCCESS Success find the file system
@retval EFI_OUT_OF_RESOURCES Can not create menu entry
**/
EFI_STATUS
BOpt_FindFileSystem (
IN BMM_CALLBACK_DATA *CallbackData
)
{
UINTN NoBlkIoHandles;
UINTN NoSimpleFsHandles;
UINTN NoLoadFileHandles;
EFI_HANDLE *BlkIoHandle;
EFI_HANDLE *SimpleFsHandle;
EFI_HANDLE *LoadFileHandle;
UINT16 *VolumeLabel;
EFI_BLOCK_IO_PROTOCOL *BlkIo;
UINTN Index;
EFI_STATUS Status;
BM_MENU_ENTRY *MenuEntry;
BM_FILE_CONTEXT *FileContext;
UINT16 *TempStr;
UINTN OptionNumber;
VOID *Buffer;
EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
UINT16 DeviceType;
BBS_BBS_DEVICE_PATH BbsDevicePathNode;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
BOOLEAN RemovableMedia;
NoSimpleFsHandles = 0;
NoLoadFileHandles = 0;
OptionNumber = 0;
InitializeListHead (&FsOptionMenu.Head);
//
// Locate Handles that support BlockIo protocol
//
Status = gBS->LocateHandleBuffer (
ByProtocol,
&gEfiBlockIoProtocolGuid,
NULL,
&NoBlkIoHandles,
&BlkIoHandle
);
if (!EFI_ERROR (Status)) {
for (Index = 0; Index < NoBlkIoHandles; Index++) {
Status = gBS->HandleProtocol (
BlkIoHandle[Index],
&gEfiBlockIoProtocolGuid,
(VOID **) &BlkIo
);
if (EFI_ERROR (Status)) {
continue;
}
//
// Issue a dummy read to trigger reinstall of BlockIo protocol for removable media
//
if (BlkIo->Media->RemovableMedia) {
Buffer = AllocateZeroPool (BlkIo->Media->BlockSize);
if (NULL == Buffer) {
FreePool (BlkIoHandle);
return EFI_OUT_OF_RESOURCES;
}
BlkIo->ReadBlocks (
BlkIo,
BlkIo->Media->MediaId,
0,
BlkIo->Media->BlockSize,
Buffer
);
FreePool (Buffer);
}
}
FreePool (BlkIoHandle);
}
//
// Locate Handles that support Simple File System protocol
//
Status = gBS->LocateHandleBuffer (
ByProtocol,
&gEfiSimpleFileSystemProtocolGuid,
NULL,
&NoSimpleFsHandles,
&SimpleFsHandle
);
if (!EFI_ERROR (Status)) {
//
// Find all the instances of the File System prototocol
//
for (Index = 0; Index < NoSimpleFsHandles; Index++) {
Status = gBS->HandleProtocol (
SimpleFsHandle[Index],
&gEfiBlockIoProtocolGuid,
(VOID **) &BlkIo
);
if (EFI_ERROR (Status)) {
//
// If no block IO exists assume it's NOT a removable media
//
RemovableMedia = FALSE;
} else {
//
// If block IO exists check to see if it's remobable media
//
RemovableMedia = BlkIo->Media->RemovableMedia;
}
//
// Allocate pool for this load option
//
MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);
if (NULL == MenuEntry) {
FreePool (SimpleFsHandle);
return EFI_OUT_OF_RESOURCES;
}
FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;
FileContext->Handle = SimpleFsHandle[Index];
MenuEntry->OptionNumber = Index;
FileContext->FHandle = EfiLibOpenRoot (FileContext->Handle);
if (FileContext->FHandle == NULL) {
BOpt_DestroyMenuEntry (MenuEntry);
continue;
}
MenuEntry->HelpString = DevicePathToStr (DevicePathFromHandle (FileContext->Handle));
FileContext->Info = EfiLibFileSystemVolumeLabelInfo (FileContext->FHandle);
FileContext->FileName = EfiStrDuplicate (L"\\");
FileContext->DevicePath = FileDevicePath (
FileContext->Handle,
FileContext->FileName
);
FileContext->IsDir = TRUE;
FileContext->IsRoot = TRUE;
FileContext->IsRemovableMedia = RemovableMedia;
FileContext->IsLoadFile = FALSE;
//
// Get current file system's Volume Label
//
if (FileContext->Info == NULL) {
VolumeLabel = L"NO FILE SYSTEM INFO";
} else {
VolumeLabel = FileContext->Info->VolumeLabel;
if (*VolumeLabel == 0x0000) {
VolumeLabel = L"NO VOLUME LABEL";
}
}
TempStr = MenuEntry->HelpString;
MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR);
ASSERT (MenuEntry->DisplayString != NULL);
UnicodeSPrint (
MenuEntry->DisplayString,
MAX_CHAR,
L"%s, [%s]",
VolumeLabel,
TempStr
);
OptionNumber++;
InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);
}
}
if (NoSimpleFsHandles != 0) {
FreePool (SimpleFsHandle);
}
//
// Searching for handles that support Load File protocol
//
Status = gBS->LocateHandleBuffer (
ByProtocol,
&gEfiLoadFileProtocolGuid,
NULL,
&NoLoadFileHandles,
&LoadFileHandle
);
if (!EFI_ERROR (Status)) {
for (Index = 0; Index < NoLoadFileHandles; Index++) {
MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);
if (NULL == MenuEntry) {
FreePool (LoadFileHandle);
return EFI_OUT_OF_RESOURCES;
}
FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;
FileContext->IsRemovableMedia = FALSE;
FileContext->IsLoadFile = TRUE;
FileContext->Handle = LoadFileHandle[Index];
FileContext->IsRoot = TRUE;
FileContext->DevicePath = DevicePathFromHandle (FileContext->Handle);
FileContext->FileName = DevicePathToStr (FileContext->DevicePath);
MenuEntry->HelpString = DevicePathToStr (FileContext->DevicePath);
TempStr = MenuEntry->HelpString;
MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR);
ASSERT (MenuEntry->DisplayString != NULL);
UnicodeSPrint (
MenuEntry->DisplayString,
MAX_CHAR,
L"Load File [%s]",
TempStr
);
MenuEntry->OptionNumber = OptionNumber;
OptionNumber++;
InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);
}
}
if (NoLoadFileHandles != 0) {
FreePool (LoadFileHandle);
}
//
// Add Legacy Boot Option Support Here
//
Status = gBS->LocateProtocol (
&gEfiLegacyBiosProtocolGuid,
NULL,
(VOID **) &LegacyBios
);
if (!EFI_ERROR (Status)) {
for (Index = BBS_TYPE_FLOPPY; Index <= BBS_TYPE_EMBEDDED_NETWORK; Index++) {
MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);
if (NULL == MenuEntry) {
return EFI_OUT_OF_RESOURCES;
}
FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;
FileContext->IsRemovableMedia = FALSE;
FileContext->IsLoadFile = TRUE;
FileContext->IsBootLegacy = TRUE;
DeviceType = (UINT16) Index;
BbsDevicePathNode.Header.Type = BBS_DEVICE_PATH;
BbsDevicePathNode.Header.SubType = BBS_BBS_DP;
SetDevicePathNodeLength (
&BbsDevicePathNode.Header,
sizeof (BBS_BBS_DEVICE_PATH)
);
BbsDevicePathNode.DeviceType = DeviceType;
BbsDevicePathNode.StatusFlag = 0;
BbsDevicePathNode.String[0] = 0;
DevicePath = AppendDevicePathNode (
EndDevicePath,
(EFI_DEVICE_PATH_PROTOCOL *) &BbsDevicePathNode
);
FileContext->DevicePath = DevicePath;
MenuEntry->HelpString = DevicePathToStr (FileContext->DevicePath);
TempStr = MenuEntry->HelpString;
MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR);
ASSERT (MenuEntry->DisplayString != NULL);
UnicodeSPrint (
MenuEntry->DisplayString,
MAX_CHAR,
L"Boot Legacy [%s]",
TempStr
);
MenuEntry->OptionNumber = OptionNumber;
OptionNumber++;
InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);
}
}
//
// Remember how many file system options are here
//
FsOptionMenu.MenuNumber = OptionNumber;
return EFI_SUCCESS;
}
/**
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;
}
/**
Find files under current directory
All files and sub-directories in current directory
will be stored in DirectoryMenu for future use.
@param CallbackData The BMM context data.
@param MenuEntry The Menu Entry.
@retval EFI_SUCCESS Get files from current dir successfully.
@return Other value if can't get files from current dir.
**/
EFI_STATUS
BOpt_FindFiles (
IN BMM_CALLBACK_DATA *CallbackData,
IN BM_MENU_ENTRY *MenuEntry
)
{
EFI_FILE_HANDLE NewDir;
EFI_FILE_HANDLE Dir;
EFI_FILE_INFO *DirInfo;
UINTN BufferSize;
UINTN DirBufferSize;
BM_MENU_ENTRY *NewMenuEntry;
BM_FILE_CONTEXT *FileContext;
BM_FILE_CONTEXT *NewFileContext;
UINTN Pass;
EFI_STATUS Status;
UINTN OptionNumber;
FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;
Dir = FileContext->FHandle;
OptionNumber = 0;
//
// Open current directory to get files from it
//
Status = Dir->Open (
Dir,
&NewDir,
FileContext->FileName,
EFI_FILE_READ_ONLY,
0
);
if (!FileContext->IsRoot) {
Dir->Close (Dir);
}
if (EFI_ERROR (Status)) {
return Status;
}
DirInfo = EfiLibFileInfo (NewDir);
if (DirInfo == NULL) {
return EFI_NOT_FOUND;
}
if ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == 0) {
return EFI_INVALID_PARAMETER;
}
FileContext->DevicePath = FileDevicePath (
FileContext->Handle,
FileContext->FileName
);
DirBufferSize = sizeof (EFI_FILE_INFO) + 1024;
DirInfo = AllocateZeroPool (DirBufferSize);
if (DirInfo == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Get all files in current directory
// Pass 1 to get Directories
// Pass 2 to get files that are EFI images
//
for (Pass = 1; Pass <= 2; Pass++) {
NewDir->SetPosition (NewDir, 0);
for (;;) {
BufferSize = DirBufferSize;
Status = NewDir->Read (NewDir, &BufferSize, DirInfo);
if (EFI_ERROR (Status) || BufferSize == 0) {
break;
}
if (((DirInfo->Attribute & EFI_FILE_DIRECTORY) != 0 && Pass == 2) ||
((DirInfo->Attribute & EFI_FILE_DIRECTORY) == 0 && Pass == 1)
) {
//
// Pass 1 is for Directories
// Pass 2 is for file names
//
continue;
}
if (!(BOpt_IsEfiImageName (DirInfo->FileName) || (DirInfo->Attribute & EFI_FILE_DIRECTORY) != 0)) {
//
// Slip file unless it is a directory entry or a .EFI file
//
continue;
}
NewMenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);
if (NULL == NewMenuEntry) {
return EFI_OUT_OF_RESOURCES;
}
NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext;
NewFileContext->Handle = FileContext->Handle;
NewFileContext->FileName = BOpt_AppendFileName (
FileContext->FileName,
DirInfo->FileName
);
NewFileContext->FHandle = NewDir;
NewFileContext->DevicePath = FileDevicePath (
NewFileContext->Handle,
NewFileContext->FileName
);
NewMenuEntry->HelpString = NULL;
MenuEntry->DisplayStringToken = GetStringTokenFromDepository (
CallbackData,
FileOptionStrDepository
);
NewFileContext->IsDir = (BOOLEAN) ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY);
if (NewFileContext->IsDir) {
BufferSize = StrLen (DirInfo->FileName) * 2 + 6;
NewMenuEntry->DisplayString = AllocateZeroPool (BufferSize);
UnicodeSPrint (
NewMenuEntry->DisplayString,
BufferSize,
L"<%s>",
DirInfo->FileName
);
} else {
NewMenuEntry->DisplayString = EfiStrDuplicate (DirInfo->FileName);
}
NewFileContext->IsRoot = FALSE;
NewFileContext->IsLoadFile = FALSE;
NewFileContext->IsRemovableMedia = FALSE;
NewMenuEntry->OptionNumber = OptionNumber;
OptionNumber++;
InsertTailList (&DirectoryMenu.Head, &NewMenuEntry->Link);
}
}
DirectoryMenu.MenuNumber = OptionNumber;
FreePool (DirInfo);
return EFI_SUCCESS;
}
/**
Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios.GetBbsInfo().
@retval EFI_SUCCESS The function complete successfully.
@retval EFI_OUT_OF_RESOURCES No enough memory to complete this function.
**/
EFI_STATUS
BOpt_GetLegacyOptions (
VOID
)
{
BM_MENU_ENTRY *NewMenuEntry;
BM_LEGACY_DEVICE_CONTEXT *NewLegacyDevContext;
EFI_STATUS Status;
EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
UINT16 HddCount;
HDD_INFO *HddInfo;
UINT16 BbsCount;
BBS_TABLE *BbsTable;
UINT16 Index;
CHAR16 DescString[100];
UINTN FDNum;
UINTN HDNum;
UINTN CDNum;
UINTN NETNum;
UINTN BEVNum;
NewMenuEntry = NULL;
HddInfo = NULL;
BbsTable = NULL;
BbsCount = 0;
//
// Initialize Bbs Table Context from BBS info data
//
InitializeListHead (&LegacyFDMenu.Head);
InitializeListHead (&LegacyHDMenu.Head);
InitializeListHead (&LegacyCDMenu.Head);
InitializeListHead (&LegacyNETMenu.Head);
InitializeListHead (&LegacyBEVMenu.Head);
Status = gBS->LocateProtocol (
&gEfiLegacyBiosProtocolGuid,
NULL,
(VOID **) &LegacyBios
);
if (!EFI_ERROR (Status)) {
Status = LegacyBios->GetBbsInfo (
LegacyBios,
&HddCount,
&HddInfo,
&BbsCount,
&BbsTable
);
if (EFI_ERROR (Status)) {
return Status;
}
}
FDNum = 0;
HDNum = 0;
CDNum = 0;
NETNum = 0;
BEVNum = 0;
for (Index = 0; Index < BbsCount; Index++) {
if ((BBS_IGNORE_ENTRY == BbsTable[Index].BootPriority) ||
(BBS_DO_NOT_BOOT_FROM == BbsTable[Index].BootPriority)
) {
continue;
}
NewMenuEntry = BOpt_CreateMenuEntry (BM_LEGACY_DEV_CONTEXT_SELECT);
if (NULL == NewMenuEntry) {
break;
}
NewLegacyDevContext = (BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext;
NewLegacyDevContext->BbsEntry = &BbsTable[Index];
NewLegacyDevContext->BbsIndex = Index;
NewLegacyDevContext->BbsCount = BbsCount;
BdsBuildLegacyDevNameString (
&BbsTable[Index],
Index,
sizeof (DescString),
DescString
);
NewLegacyDevContext->Description = AllocateCopyPool (StrSize (DescString), DescString);
if (NULL == NewLegacyDevContext->Description) {
break;
}
NewMenuEntry->DisplayString = NewLegacyDevContext->Description;
NewMenuEntry->HelpString = NULL;
switch (BbsTable[Index].DeviceType) {
case BBS_FLOPPY:
InsertTailList (&LegacyFDMenu.Head, &NewMenuEntry->Link);
FDNum++;
break;
case BBS_HARDDISK:
InsertTailList (&LegacyHDMenu.Head, &NewMenuEntry->Link);
HDNum++;
break;
case BBS_CDROM:
InsertTailList (&LegacyCDMenu.Head, &NewMenuEntry->Link);
CDNum++;
break;
case BBS_EMBED_NETWORK:
InsertTailList (&LegacyNETMenu.Head, &NewMenuEntry->Link);
NETNum++;
break;
case BBS_BEV_DEVICE:
InsertTailList (&LegacyBEVMenu.Head, &NewMenuEntry->Link);
BEVNum++;
break;
}
}
if (Index != BbsCount) {
BOpt_FreeLegacyOptions ();
return EFI_OUT_OF_RESOURCES;
}
LegacyFDMenu.MenuNumber = FDNum;
LegacyHDMenu.MenuNumber = HDNum;
LegacyCDMenu.MenuNumber = CDNum;
LegacyNETMenu.MenuNumber = NETNum;
LegacyBEVMenu.MenuNumber = BEVNum;
return EFI_SUCCESS;
}
/**
Free out resouce allocated from Legacy Boot Options.
**/
VOID
BOpt_FreeLegacyOptions (
VOID
)
{
BOpt_FreeMenu (&LegacyFDMenu);
BOpt_FreeMenu (&LegacyHDMenu);
BOpt_FreeMenu (&LegacyCDMenu);
BOpt_FreeMenu (&LegacyNETMenu);
BOpt_FreeMenu (&LegacyBEVMenu);
}
/**
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;
UINT8 *LoadOption;
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;
MenuCount = 0;
BootOrderListSize = 0;
BootNextSize = 0;
BootOrderList = NULL;
BootNext = NULL;
LoadOptionFromVar = NULL;
BOpt_FreeMenu (&BootOptionMenu);
InitializeListHead (&BootOptionMenu.Head);
//
// Get the BootOrder from the Var
//
BootOrderList = BdsLibGetVariableAndSize (
L"BootOrder",
&gEfiGlobalVariableGuid,
&BootOrderListSize
);
if (BootOrderList == NULL) {
return EFI_NOT_FOUND;
}
//
// Get the BootNext from the Var
//
BootNext = BdsLibGetVariableAndSize (
L"BootNext",
&gEfiGlobalVariableGuid,
&BootNextSize
);
if (BootNext != NULL) {
if (BootNextSize != sizeof (UINT16)) {
FreePool (BootNext);
BootNext = NULL;
}
}
for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) {
UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", BootOrderList[Index]);
//
// Get all loadoptions from the VAR
//
LoadOptionFromVar = BdsLibGetVariableAndSize (
BootString,
&gEfiGlobalVariableGuid,
&BootOptionSize
);
if (LoadOptionFromVar == NULL) {
continue;
}
LoadOption = AllocateZeroPool (BootOptionSize);
if (LoadOption == NULL) {
continue;
}
CopyMem (LoadOption, LoadOptionFromVar, BootOptionSize);
FreePool (LoadOptionFromVar);
if (BootNext != NULL) {
BootNextFlag = (BOOLEAN) (*BootNext == BootOrderList[Index]);
} else {
BootNextFlag = FALSE;
}
if (0 == (*((UINT32 *) LoadOption) & LOAD_OPTION_ACTIVE)) {
FreePool (LoadOption);
continue;
}
//
// BUGBUG: could not return EFI_OUT_OF_RESOURCES here directly.
// the buffer allocated already should be freed before returning.
//
NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);
if (NULL == NewMenuEntry) {
return EFI_OUT_OF_RESOURCES;
}
NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
LoadOptionPtr = LoadOption;
LoadOptionEnd = LoadOption + BootOptionSize;
NewMenuEntry->OptionNumber = BootOrderList[Index];
NewLoadContext->LoadOptionModified = FALSE;
NewLoadContext->Deleted = FALSE;
NewLoadContext->IsBootNext = BootNextFlag;
//
// Is a Legacy Device?
//
Ptr = (UINT8 *) LoadOption;
//
// 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->LoadOption = LoadOption;
NewLoadContext->LoadOptionSize = BootOptionSize;
NewLoadContext->Attributes = *(UINT32 *) LoadOptionPtr;
NewLoadContext->IsActive = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_ACTIVE);
NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);
LoadOptionPtr += sizeof (UINT32);
NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr;
LoadOptionPtr += sizeof (UINT16);
StringSize = StrSize((UINT16*)LoadOptionPtr);
NewLoadContext->Description = AllocateCopyPool (StrSize((UINT16*)LoadOptionPtr), LoadOptionPtr);
ASSERT (NewLoadContext->Description != NULL);
NewMenuEntry->DisplayString = NewLoadContext->Description;
LoadOptionPtr += StringSize;
NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength);
ASSERT (NewLoadContext->FilePathList != NULL);
CopyMem (
NewLoadContext->FilePathList,
(EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr,
NewLoadContext->FilePathListLength
);
NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);
NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (
CallbackData,
BootOptionStrDepository
);
NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (
CallbackData,
BootOptionHelpStrDepository
);
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
);
NewLoadContext->OptionalDataSize = OptionalDataSize;
}
InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link);
MenuCount++;
}
if (BootNext != NULL) {
FreePool (BootNext);
}
if (BootOrderList != NULL) {
FreePool (BootOrderList);
}
BootOptionMenu.MenuNumber = MenuCount;
return EFI_SUCCESS;
}
/**
Append file name to existing file name.
@param Str1 The existing file name
@param Str2 The file name to be appended
@return Allocate a new string to hold the appended result.
Caller is responsible to free the returned string.
**/
CHAR16 *
BOpt_AppendFileName (
IN CHAR16 *Str1,
IN CHAR16 *Str2
)
{
UINTN Size1;
UINTN Size2;
UINTN MaxLen;
CHAR16 *Str;
CHAR16 *TmpStr;
CHAR16 *Ptr;
CHAR16 *LastSlash;
Size1 = StrSize (Str1);
Size2 = StrSize (Str2);
MaxLen = (Size1 + Size2 + sizeof (CHAR16)) / sizeof (CHAR16);
Str = AllocateZeroPool (MaxLen * sizeof (CHAR16));
ASSERT (Str != NULL);
TmpStr = AllocateZeroPool (MaxLen * sizeof (CHAR16));
ASSERT (TmpStr != NULL);
StrCatS (Str, MaxLen, Str1);
if (!((*Str == '\\') && (*(Str + 1) == 0))) {
StrCatS (Str, MaxLen, L"\\");
}
StrCatS (Str, MaxLen, Str2);
Ptr = Str;
LastSlash = Str;
while (*Ptr != 0) {
if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '.' && *(Ptr + 3) == L'\\') {
//
// Convert "\Name\..\" to "\"
// DO NOT convert the .. if it is at the end of the string. This will
// break the .. behavior in changing directories.
//
//
// Use TmpStr as a backup, as StrCpyS in BaseLib does not handle copy of two strings
// that overlap.
//
StrCpyS (TmpStr, MaxLen, Ptr + 3);
StrCpyS (LastSlash, MaxLen - ((UINTN) LastSlash - (UINTN) Str) / sizeof (CHAR16), TmpStr);
Ptr = LastSlash;
} else if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '\\') {
//
// Convert a "\.\" to a "\"
//
//
// Use TmpStr as a backup, as StrCpyS in BaseLib does not handle copy of two strings
// that overlap.
//
StrCpyS (TmpStr, MaxLen, Ptr + 2);
StrCpyS (Ptr, MaxLen - ((UINTN) Ptr - (UINTN) Str) / sizeof (CHAR16), TmpStr);
Ptr = LastSlash;
} else if (*Ptr == '\\') {
LastSlash = Ptr;
}
Ptr++;
}
FreePool (TmpStr);
return Str;
}
/**
Check whether current FileName point to a valid
Efi Image File.
@param FileName File need to be checked.
@retval TRUE Is Efi Image
@retval FALSE Not a valid Efi Image
**/
BOOLEAN
BOpt_IsEfiImageName (
IN UINT16 *FileName
)
{
//
// Search for ".efi" extension
//
while (*FileName != L'\0') {
if (FileName[0] == '.') {
if (FileName[1] == 'e' || FileName[1] == 'E') {
if (FileName[2] == 'f' || FileName[2] == 'F') {
if (FileName[3] == 'i' || FileName[3] == 'I') {
return TRUE;
} else if (FileName[3] == 0x0000) {
return FALSE;
}
} else if (FileName[2] == 0x0000) {
return FALSE;
}
} else if (FileName[1] == 0x0000) {
return FALSE;
}
}
FileName += 1;
}
return FALSE;
}
/**
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 = DevicePathToStr (NewHandleContext->DevicePath);
NewMenuEntry->HelpString = NULL;
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);
OrderList = BdsLibGetVariableAndSize (
StrTemp,
&gEfiGlobalVariableGuid,
&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((EFI_D_ERROR,"Option = %s\n", StrTemp));
OptionBuffer = BdsLibGetVariableAndSize (
StrTemp,
&gEfiGlobalVariableGuid,
&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;
UINT8 *LoadOption;
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
//
DriverOrderList = BdsLibGetVariableAndSize (
L"DriverOrder",
&gEfiGlobalVariableGuid,
&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
//
LoadOptionFromVar = BdsLibGetVariableAndSize (
DriverString,
&gEfiGlobalVariableGuid,
&DriverOptionSize
);
if (LoadOptionFromVar == NULL) {
continue;
}
LoadOption = AllocateZeroPool (DriverOptionSize);
if (LoadOption == NULL) {
continue;
}
CopyMem (LoadOption, LoadOptionFromVar, DriverOptionSize);
FreePool (LoadOptionFromVar);
NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);
if (NULL == NewMenuEntry) {
return EFI_OUT_OF_RESOURCES;
}
NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
LoadOptionPtr = LoadOption;
LoadOptionEnd = LoadOption + DriverOptionSize;
NewMenuEntry->OptionNumber = DriverOrderList[Index];
NewLoadContext->LoadOptionModified = FALSE;
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->LoadOption = LoadOption;
NewLoadContext->LoadOptionSize = DriverOptionSize;
NewLoadContext->Attributes = *(UINT32 *) LoadOptionPtr;
NewLoadContext->IsActive = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_ACTIVE);
NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);
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;
LoadOptionPtr += StringSize;
NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength);
ASSERT (NewLoadContext->FilePathList != NULL);
CopyMem (
NewLoadContext->FilePathList,
(EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr,
NewLoadContext->FilePathListLength
);
NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);
NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (
CallbackData,
DriverOptionStrDepository
);
NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (
CallbackData,
DriverOptionHelpStrDepository
);
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
);
NewLoadContext->OptionalDataSize = OptionalDataSize;
}
InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link);
}
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);
}
}
/**
According to LegacyDevOrder variable to get legacy FD\HD\CD\NET\BEV
devices list .
@param CallbackData The BMM context data.
**/
VOID
GetLegacyDeviceOrder (
IN BMM_CALLBACK_DATA *CallbackData
)
{
UINTN Index;
UINTN OptionIndex;
UINT16 PageIdList[5];
UINTN PageNum;
UINTN VarSize;
UINT8 *VarData;
UINT8 *WorkingVarData;
LEGACY_DEV_ORDER_ENTRY *DevOrder;
UINT16 VarDevOrder;
UINT8 *DisMap;
BM_MENU_OPTION *OptionMenu;
BBS_TYPE BbsType;
UINT8 *LegacyOrder;
UINT8 *OldData;
UINTN Pos;
UINTN Bit;
ASSERT (CallbackData != NULL);
PageIdList[0] = FORM_SET_FD_ORDER_ID;
PageIdList[1] = FORM_SET_HD_ORDER_ID;
PageIdList[2] = FORM_SET_CD_ORDER_ID;
PageIdList[3] = FORM_SET_NET_ORDER_ID;
PageIdList[4] = FORM_SET_BEV_ORDER_ID;
OptionMenu = NULL;
BbsType = 0;
LegacyOrder = NULL;
OldData = NULL;
DisMap = ZeroMem (CallbackData->BmmFakeNvData.DisableMap, sizeof (CallbackData->BmmFakeNvData.DisableMap));
PageNum = ARRAY_SIZE (PageIdList);
VarData = BdsLibGetVariableAndSize (
VAR_LEGACY_DEV_ORDER,
&gEfiLegacyDevOrderVariableGuid,
&VarSize
);
for (Index = 0; Index < PageNum; Index++) {
switch (PageIdList[Index]) {
case FORM_SET_FD_ORDER_ID:
OptionMenu = (BM_MENU_OPTION *) &LegacyFDMenu;
BbsType = BBS_FLOPPY;
LegacyOrder = CallbackData->BmmFakeNvData.LegacyFD;
OldData = CallbackData->BmmOldFakeNVData.LegacyFD;
break;
case FORM_SET_HD_ORDER_ID:
OptionMenu = (BM_MENU_OPTION *) &LegacyHDMenu;
BbsType = BBS_HARDDISK;
LegacyOrder = CallbackData->BmmFakeNvData.LegacyHD;
OldData = CallbackData->BmmOldFakeNVData.LegacyHD;
break;
case FORM_SET_CD_ORDER_ID:
OptionMenu = (BM_MENU_OPTION *) &LegacyCDMenu;
BbsType = BBS_CDROM;
LegacyOrder = CallbackData->BmmFakeNvData.LegacyCD;
OldData = CallbackData->BmmOldFakeNVData.LegacyCD;
break;
case FORM_SET_NET_ORDER_ID:
OptionMenu = (BM_MENU_OPTION *) &LegacyNETMenu;
BbsType = BBS_EMBED_NETWORK;
LegacyOrder = CallbackData->BmmFakeNvData.LegacyNET;
OldData = CallbackData->BmmOldFakeNVData.LegacyNET;
break;
default:
ASSERT (PageIdList[Index] == FORM_SET_BEV_ORDER_ID);
OptionMenu = (BM_MENU_OPTION *) &LegacyBEVMenu;
BbsType = BBS_BEV_DEVICE;
LegacyOrder = CallbackData->BmmFakeNvData.LegacyBEV;
OldData = CallbackData->BmmOldFakeNVData.LegacyBEV;
break;
}
if (NULL != VarData) {
WorkingVarData = VarData;
DevOrder = (LEGACY_DEV_ORDER_ENTRY *) WorkingVarData;
while (WorkingVarData < VarData + VarSize) {
if (DevOrder->BbsType == BbsType) {
break;
}
WorkingVarData = (UINT8 *)((UINTN)WorkingVarData + sizeof (BBS_TYPE));
WorkingVarData += *(UINT16 *) WorkingVarData;
DevOrder = (LEGACY_DEV_ORDER_ENTRY *) WorkingVarData;
}
for (OptionIndex = 0; OptionIndex < OptionMenu->MenuNumber; OptionIndex++) {
VarDevOrder = *(UINT16 *) ((UINTN) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16) + OptionIndex * sizeof (UINT16));
if (0xFF00 == (VarDevOrder & 0xFF00)) {
LegacyOrder[OptionIndex] = 0xFF;
Pos = (VarDevOrder & 0xFF) / 8;
Bit = 7 - ((VarDevOrder & 0xFF) % 8);
DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit));
} else {
LegacyOrder[OptionIndex] = (UINT8) (VarDevOrder & 0xFF);
}
}
CopyMem (OldData, LegacyOrder, 100);
}
}
}
/**
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);
}
}