console.c
来自「Next BIOS Source code : Extensible Firmw」· C语言 代码 · 共 771 行 · 第 1/2 页
C
771 行
case CON_MENU_CONSOLE:
//
// Toggle selection
//
if (ResultContext->ActiveConsole) {
ResultContext->ActiveConsole = FALSE;
ResultContext->Menu->Attribute = CON_UNSELECTED;
} else {
ResultContext->ActiveConsole = CheckIfSelectionAllowed(&ConsoleMenu, MenuType, ResultContext);
if (ResultContext->ActiveConsole) {
ResultContext->Menu->Attribute = CON_UNSELECTED;
}
else
ResultContext->Menu->Attribute = CON_UNSELECTED;
}
ToggleSelectionStr(&ConsoleMenu,ResultContext,ResultContext->ActiveConsole);
/* if (MenuType == ConsoleMenuError) {
//
// If the menu only supports a single selection.
// Inactivate the previous selection.
//
if (PreviousResultContext && (PreviousResultContext != ResultContext)) {
PreviousResultContext->ActiveConsole = FALSE;
PreviousResultContext->Menu->Attribute = CON_UNSELECTED;
}
}
*/
//
// This variable was set with the orignal NVRAM setting so update the settings
//
switch (MenuType) {
case ConsoleMenuIn:
ResultContext->IsConIn = ResultContext->ActiveConsole;
break;
case ConsoleMenuOut:
ResultContext->IsConOut = ResultContext->ActiveConsole;
break;
case ConsoleMenuError:
ResultContext->IsStdErr = ResultContext->ActiveConsole;
break;
default:
break;
}
NVRAMNeedsUpdating = TRUE;
default:
break;
}
}
if (OutDevicePath) {
FreePool (OutDevicePath);
}
if (InpDevicePath) {
FreePool (InpDevicePath);
}
if (ErrDevicePath) {
FreePool (ErrDevicePath);
}
if (AllDevicePath) {
FreePool (AllDevicePath);
}
FreeConsoleMenu (&ConsoleMenu);
ST->ConOut->ClearScreen (ST->ConOut);
return EFI_SUCCESS;
}
VOID
ConsoleContextPrint (
IN struct _MENU_OPTION *MenuOption,
IN VOID *Context,
IN UINTN *Row,
IN UINTN Column
)
{
CONSOLE_MENU_CONTEXT *ConContext;
CHAR16 *Str1, *Str2, *Str3;
ConContext = (CONSOLE_MENU_CONTEXT *)Context;
Str1 = Str2 = Str3 = L"";
if (ConContext->MenuOption == CON_MENU_CONSOLE) {
if (ConContext->IsConIn) {
Str1 = L"Active Input Device. ";
}
if (ConContext->IsConOut) {
Str2 = L"Active Output Device. ";
}
if (ConContext->IsStdErr) {
Str3 = L"Active Standard Error Device.";
}
}
PrintAt (Column, *Row + 1, L"%s%s%-.80s", Str1, Str2, Str3);
*Row = *Row + 2;
}
CONSOLE_MENU_CONTEXT *
AllocateSpecialMenuOption (
IN EFI_MENU *Menu,
IN CHAR16 *String,
IN UINTN Attribute,
IN UINTN Option
)
{
CONSOLE_MENU_CONTEXT *Context;
Context = AllocateZeroPool (sizeof(CONSOLE_MENU_CONTEXT));
ASSERT (Context);
Context->MenuOption = Option;
Context->Menu = AllocateMenuOption (Menu, String, Attribute, Context);
Context->Menu->ContextPrint = ConsoleContextPrint;
return Context;
}
EFI_STATUS
SetNvramForConsoleMenu (
IN EFI_MENU *Menu,
IN CHAR16 *VarName,
IN TYPE_OF_DISPLAY_CONSOLE_MENU MenuType
)
{
MENU_OPTION *MenuOption;
CONSOLE_MENU_CONTEXT *MenuContext;
LIST_ENTRY *List;
EFI_DEVICE_PATH *DevicePath;
EFI_STATUS Status;
UINTN Size;
DevicePath = NULL;
List = Menu->Head.Flink;
while (List != &Menu->Head) {
MenuOption = CR(List, MENU_OPTION, Link, MENU_OPTION_SIGNATURE);
MenuContext = (CONSOLE_MENU_CONTEXT *)MenuOption->Context;
if (MenuContext != NULL) {
if (MenuContext->ActiveConsole) {
DevicePath = AppendDevicePathInstance (DevicePath, MenuContext->DevicePath);
}
//
// This variable was set with the orignal NVRAM setting so update the settings
//
switch (MenuType) {
case ConsoleMenuIn:
MenuContext->IsConIn = MenuContext->ActiveConsole;
break;
case ConsoleMenuOut:
MenuContext->IsConOut = MenuContext->ActiveConsole;
break;
case ConsoleMenuError:
MenuContext->IsStdErr = MenuContext->ActiveConsole;
break;
default:
break;
}
}
List = List->Flink;
}
Size = 0;
if (DevicePath) {
Size = DevicePathSize(DevicePath);
}
Status = RT->SetVariable (
VarName, &EfiGlobalVariable,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
Size, DevicePath
);
if (DevicePath) {
FreePool (DevicePath);
}
return Status;
}
VOID
FreeConsoleMenu (
IN EFI_MENU *Menu
)
{
MENU_OPTION *MenuOption;
CONSOLE_MENU_CONTEXT *MenuContext;
LIST_ENTRY *List;
//
// Delete the menu option's Context
//
List = Menu->Head.Flink;
while (List != &Menu->Head) {
MenuOption = CR(List, MENU_OPTION, Link, MENU_OPTION_SIGNATURE);
MenuContext = (CONSOLE_MENU_CONTEXT *)MenuOption->Context;
if (MenuContext != NULL) {
if (MenuContext->DevicePathStr) {
FreePool (MenuContext->DevicePathStr);
}
FreePool (MenuOption->Context);
}
List = List->Flink;
}
MenuFree (Menu);
}
BOOLEAN
MatchDevicePaths (
IN EFI_DEVICE_PATH *Multi,
IN EFI_DEVICE_PATH *Single
)
{
EFI_DEVICE_PATH *DevicePath, *DevicePathInst;
UINTN Size;
if (!Multi || !Single) {
return FALSE;
}
DevicePath = Multi;
while (DevicePathInst = DevicePathInstance (&DevicePath, &Size)) {
if (CompareMem (Single, DevicePathInst, Size) == 0) {
return TRUE;
}
}
return FALSE;
}
BOOLEAN
CheckIfSelectionAllowed (
IN EFI_MENU *Menu,
IN TYPE_OF_DISPLAY_CONSOLE_MENU CurrentMenuType,
IN CONSOLE_MENU_CONTEXT *SelMenuContext
)
{
MENU_OPTION *MenuOption;
CONSOLE_MENU_CONTEXT *MenuContext;
LIST_ENTRY *List;
EFI_MENU ConMenu;
EFI_MENU *TempMenu;
UINTN Index;
TYPE_OF_DISPLAY_CONSOLE_MENU MenuType;
//
// We should deal with two different cases here. The first case is we can not select a console
// (terminal) which has the same hardware device path part with an active one in the *same* menu.
// The second case is if we want to select a console which has the same hardware device path part
// with an active one in *another* two menu, we should make sure these two consoles' device path
// are identical.
//
for (Index = 0; Index < 3; Index++) {
switch (Index) {
case 0:
MenuType = ConsoleMenuIn;
break;
case 1:
MenuType = ConsoleMenuOut;
break;
case 2:
MenuType = ConsoleMenuError;
break;
default:
ASSERT(FALSE);
}
if (MenuType != CurrentMenuType) {
//
// Generate an undisplayed menu here to make the comparison easier.
//
InitializeConsoleMenuFromVariable (MenuType, &ConMenu);
TempMenu = &ConMenu;
} else {
TempMenu = Menu;
}
List = TempMenu->Head.Flink;
while (List != &TempMenu->Head) {
MenuOption = CR(List, MENU_OPTION, Link, MENU_OPTION_SIGNATURE);
MenuContext = (CONSOLE_MENU_CONTEXT *)MenuOption->Context;
if ((MenuContext != NULL) && (MenuContext != SelMenuContext)) {
if (MenuContext->ActiveConsole) {
if (!VerifyDevicePaths (SelMenuContext->DevicePath, MenuContext->DevicePath)) {
//
// Both device paths point to the same hardware location here.
//
if (MenuType != CurrentMenuType &&
( 0 == CompareMem (SelMenuContext->DevicePath, MenuContext->DevicePath, DevicePathSize (SelMenuContext->DevicePath)))) {
return TRUE;
} else {
return FALSE;
}
}
}
}
List = List->Flink;
} // end while
if (MenuType != CurrentMenuType) {
FreeConsoleMenu (&ConMenu);
}
}
return TRUE;
}
BOOLEAN
VerifyDevicePaths (
IN EFI_DEVICE_PATH *CurSelDevicePath,
IN EFI_DEVICE_PATH *PrevSelDevicePath
)
{
EFI_DEVICE_PATH *Src1, *Src1Subset;
EFI_DEVICE_PATH *Src2, *Src2Subset;
BOOLEAN StopSearch1,StopSearch2,NoMatch;
//
// The logic here is to search till the messaging_device_path
// is hit on both the inputs. Then a compare is made till that
// point. If there is a match then both device paths point to
// the same hardware location. Return TRUE if they don't match
//
Src1 = CurSelDevicePath;
Src2 = PrevSelDevicePath;
Src1Subset = NULL;
Src2Subset = NULL;
StopSearch1 = FALSE;
StopSearch2 = FALSE;
NoMatch = TRUE;
while (!IsDevicePathEnd(Src1) && !IsDevicePathEnd(Src2)) {
if(DevicePathType(Src1) != MESSAGING_DEVICE_PATH) {
Src1Subset = AppendDevicePathNode (Src1Subset, Src1);
Src1 = NextDevicePathNode(Src1);
}
else
StopSearch1 = TRUE;
if(DevicePathType(Src2) != MESSAGING_DEVICE_PATH) {
Src2Subset = AppendDevicePathNode (Src2Subset, Src2);
Src2 = NextDevicePathNode(Src2);
}
else
StopSearch2 = TRUE;
if(StopSearch1 && StopSearch2) {
NoMatch = (CompareMem(Src1Subset,Src2Subset,DevicePathSize(Src1Subset)) != 0);
FreePool(Src1Subset);
FreePool(Src2Subset);
break;
}
}// end while
return NoMatch;
}
VOID
ToggleSelectionStr(
IN EFI_MENU *Menu,
IN CONSOLE_MENU_CONTEXT *SelMenuContext,
IN BOOLEAN Active
)
{
MENU_OPTION *MenuOption;
CONSOLE_MENU_CONTEXT *MenuContext;
LIST_ENTRY *List;
List = Menu->Head.Flink;
while (List != &Menu->Head) {
MenuOption = CR(List, MENU_OPTION, Link, MENU_OPTION_SIGNATURE);
MenuContext = (CONSOLE_MENU_CONTEXT *)MenuOption->Context;
if (MenuContext == SelMenuContext ) {
if (Active) {
MenuOption->Description[0] = '*';
} else {
MenuOption->Description[0] = ' ';
}
break;
}
List = List->Flink;
} // end while
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?