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 + -
显示快捷键?