console.c

来自「Next BIOS Source code : Extensible Firmw」· C语言 代码 · 共 771 行 · 第 1/2 页

C
771
字号
/*++

Copyright (c)  1999 - 2002 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.


Module Name:

    console.c
    
Abstract:

    handles console redirection from bootmanager


Revision History

--*/

#include "menu.h"

typedef enum {
    UnusedMenuEntry,
    ConsoleMenuOut,
    ConsoleMenuIn,
    ConsoleMenuError
} TYPE_OF_DISPLAY_CONSOLE_MENU;

                
//
// BugBug: It smells like a lib function
//
//--------------------------------------
BOOLEAN
MatchDevicePaths (
    IN  EFI_DEVICE_PATH *Multi,
    IN  EFI_DEVICE_PATH *Single
    );

EFI_DEVICE_PATH *
DuplicateDevicePathInstance (
    IN EFI_DEVICE_PATH  *DevPath
    );
//----------------------------------------

EFI_STATUS
SetNvramForConsoleMenu (
    IN  EFI_MENU                        *Menu,
    IN  CHAR16                          *VarName,
    IN  TYPE_OF_DISPLAY_CONSOLE_MENU    MenuType
    );

BOOLEAN
CheckIfSelectionAllowed (
    IN  EFI_MENU                           *Menu,
    IN  TYPE_OF_DISPLAY_CONSOLE_MENU       CurrentMenuType,
    IN  CONSOLE_MENU_CONTEXT               *SelMenuContext
    );

BOOLEAN
VerifyDevicePaths (
    IN  EFI_DEVICE_PATH     *CurSelDevicePath,
    IN  EFI_DEVICE_PATH     *PrevSelDevicePath
);

VOID
ConsoleContextPrint (
     IN struct _MENU_OPTION *MenuOption,
     IN VOID                *Context,
     IN UINTN               *Row,
     IN UINTN               Column
     );

CONSOLE_MENU_CONTEXT *
AllocateSpecialMenuOption (
    IN EFI_MENU     *Menu,
    IN CHAR16       *String,
    IN UINTN        Attribute,
    IN UINTN        Option      
    );

EFI_STATUS
DisplayConsoleMenu (
    IN  TYPE_OF_DISPLAY_CONSOLE_MENU    MenuType,
    IN  CHAR16                          *Header,
    IN  CHAR16                          *Footer
    );

VOID
FreeConsoleMenu (
    IN EFI_MENU     *Menu
    );

EFI_DEVICE_PATH *
DuplicateDevicePathInstance (
    IN EFI_DEVICE_PATH  *DevPath
    );

VOID
ToggleSelectionStr(
    IN EFI_MENU             *Menu,
    IN CONSOLE_MENU_CONTEXT *SelMenuContext,
    IN BOOLEAN              Active
    );

EFI_MENU ConsoleMenu = {
    MENU_SIGNATURE, NULL,  
    4, CON_UNSELECTED, CON_ACTIVE_SELECTION, 
    TRUE, 10, 
    L"%ESelect an Operation\n\n", 
    L"    ", 4, 
    NULL, NULL, NULL, NULL, NULL, TRUE, 0, MENU_ENTRY_FORMAT
};

EFI_STATUS
Bmnt_DisplayConsoleOutMenu () 
{
    return DisplayConsoleMenu (
                ConsoleMenuOut, 
                L"Select the Console Output Device(s)\n\n",
                NULL
                );
}

EFI_STATUS
Bmnt_DisplayConsoleInMenu () 
{
    return DisplayConsoleMenu (
                ConsoleMenuIn,
                L"Select the Console Input Device(s)\n\n",
                NULL                
                );
}

EFI_STATUS
Bmnt_DisplayStdErrorMenu () 
{
    return DisplayConsoleMenu (
                ConsoleMenuError,
                L"Select the Standard Error Device\n\n",
                NULL
                );
}

EFI_DEVICE_PATH *
DuplicateDevicePathInstance (
    IN EFI_DEVICE_PATH  *DevPath
    )
{
    EFI_DEVICE_PATH     *NewDevPath,*DevicePathInst,*Temp;
    UINTN               Size;    

    //
    // get the size of an instance from the input
    //

    Temp = DevPath;
    DevicePathInst = DevicePathInstance (&Temp, &Size);
    
    //
    // Make a copy and set proper end type
    //
    NewDevPath = NULL;
    if (Size) { 
        NewDevPath = AllocatePool (Size + sizeof(EFI_DEVICE_PATH));
    }

    if (NewDevPath) {
        CopyMem (NewDevPath, DevicePathInst, Size);
        Temp = (EFI_DEVICE_PATH *) (((UINT8 *) NewDevPath) + Size);
        SetDevicePathEndNode(Temp);
    }

    return NewDevPath;
}

EFI_STATUS
InitializeConsoleMenuFromVariable (
    IN      TYPE_OF_DISPLAY_CONSOLE_MENU    MenuType,
    IN OUT  EFI_MENU                        *ConMenu
    )
{
    CHAR16                           Buffer[1];
    CONSOLE_MENU_CONTEXT             *Context;
    EFI_DEVICE_PATH                  *OutDevicePath;
    EFI_DEVICE_PATH                  *InpDevicePath;
    EFI_DEVICE_PATH                  *ErrDevicePath;
    EFI_DEVICE_PATH                  *PrevSelDevicePath, *AllDevicePath;
    EFI_DEVICE_PATH                  *Multi, *DevicePathInst;
    UINTN                            Size;
    CHAR16                           *VarString;
  
    OutDevicePath = LibGetVariable (VarConsoleOut, &EfiGlobalVariable);
    InpDevicePath = LibGetVariable (VarConsoleInp, &EfiGlobalVariable);
    ErrDevicePath = LibGetVariable (VarErrorOut, &EfiGlobalVariable);

    switch (MenuType) {
    case ConsoleMenuOut:
        PrevSelDevicePath = OutDevicePath;
        AllDevicePath = LibGetVariable (VarConsoleOutDev, &EfiGlobalVariable);
        VarString = VarConsoleOut;
        break;
    case ConsoleMenuIn:
        PrevSelDevicePath = InpDevicePath;
        AllDevicePath = LibGetVariable (VarConsoleInpDev, &EfiGlobalVariable);
        VarString = VarConsoleInp;
        break;
    case ConsoleMenuError:
        PrevSelDevicePath = ErrDevicePath;
        AllDevicePath = LibGetVariable (VarErrorOutDev, &EfiGlobalVariable);
        VarString = VarErrorOut;
        break;
    default:
        ASSERT(FALSE);
    };
   
    InitializeListHead (&ConMenu->Head);

    //
    // get all instances from the BS variable
    //
    Multi = AllDevicePath;    
    while (DevicePathInst = DevicePathInstance (&Multi, &Size)) {
        Context = AllocateZeroPool (sizeof(CONSOLE_MENU_CONTEXT));
        ASSERT (Context);

        Context->MenuOption = CON_MENU_CONSOLE;
        Context->DevicePath = DuplicateDevicePathInstance(DevicePathInst);
        Context->ActiveConsole = MatchDevicePaths (PrevSelDevicePath, Context->DevicePath);
        Context->Menu = AllocateMenuOption (ConMenu, Buffer, CON_UNSELECTED, Context);
    }

  
    if (AllDevicePath) {
      FreePool (AllDevicePath);
    }
    if (OutDevicePath) {
      FreePool (OutDevicePath);
    }
    if (InpDevicePath) {
      FreePool (InpDevicePath);
    }
    if (ErrDevicePath) {
      FreePool (ErrDevicePath);
    }
    return EFI_SUCCESS;
}

EFI_STATUS
DisplayConsoleMenu (
    IN  TYPE_OF_DISPLAY_CONSOLE_MENU    MenuType,
    IN  CHAR16                          *Header,
    IN  CHAR16                          *Footer
    ) 
{
    CHAR16                  Buffer[MAX_CHAR];
    CONSOLE_MENU_CONTEXT    *ResultContext;
    CONSOLE_MENU_CONTEXT    *PreviousResultContext;
    CONSOLE_MENU_CONTEXT    *Context;
    EFI_INPUT_KEY           Key;
    UINTN                   Attribute;
    EFI_DEVICE_PATH         *OutDevicePath;
    EFI_DEVICE_PATH         *InpDevicePath;
    EFI_DEVICE_PATH         *ErrDevicePath;
    EFI_DEVICE_PATH         *PrevSelDevicePath, *AllDevicePath;
    EFI_DEVICE_PATH         *Multi, *DevicePathInst;
    UINTN                   Size;
//    EFI_GUID                *CorGuid;
    BOOLEAN                 Done;
    UINTN                   ActiveConsoleCount;
//    EFI_GUID                *DeviceGuid;
    CHAR16                  *VarString;
    BOOLEAN                 NVRAMNeedsUpdating;
    UINTN                   MenuOption;
    EFI_STATUS              Status;

    OutDevicePath = LibGetVariable (VarConsoleOut, &EfiGlobalVariable);
    InpDevicePath = LibGetVariable (VarConsoleInp, &EfiGlobalVariable);
    ErrDevicePath = LibGetVariable (VarErrorOut, &EfiGlobalVariable);

    ActiveConsoleCount = 0;

    switch (MenuType) {
    case ConsoleMenuOut:
  //      DeviceGuid = &TextOutProtocol;
  //      CorGuid = &TextInProtocol;
        PrevSelDevicePath = OutDevicePath;
        AllDevicePath = LibGetVariable (VarConsoleOutDev, &EfiGlobalVariable);
        VarString = VarConsoleOut;
        break;
    case ConsoleMenuIn:
 //       DeviceGuid = &TextInProtocol, 
 //       CorGuid = &TextOutProtocol;
        PrevSelDevicePath = InpDevicePath;
        AllDevicePath = LibGetVariable (VarConsoleInpDev, &EfiGlobalVariable);
        VarString = VarConsoleInp;
        break;
    case ConsoleMenuError:
//        DeviceGuid = &TextOutProtocol, 
//        CorGuid = &TextInProtocol;
        PrevSelDevicePath = ErrDevicePath;
        AllDevicePath = LibGetVariable (VarErrorOutDev, &EfiGlobalVariable);
        VarString = VarErrorOut;
        break;
    default:
        ASSERT(FALSE);
    };
    
    ConsoleMenu.BottomOfPage = NULL;
    InitializeListHead (&ConsoleMenu.Head);

    //
    // get all instances from the BS variable
    //
    Multi = AllDevicePath;    
    while (DevicePathInst = DevicePathInstance (&Multi, &Size)) {
        Context = AllocateZeroPool (sizeof(CONSOLE_MENU_CONTEXT));
        ASSERT (Context);

        Context->MenuOption = CON_MENU_CONSOLE;
//        Context->Handle = Handles[Index];
        Context->DevicePath = DuplicateDevicePathInstance(DevicePathInst);
        Context->DevicePathStr = DevicePathToStr (Context->DevicePath);
        Context->ActiveConsole = MatchDevicePaths (PrevSelDevicePath, Context->DevicePath);
      
        Attribute = CON_UNSELECTED;

        Context->IsConIn  = MatchDevicePaths (InpDevicePath, Context->DevicePath);
        Context->IsConOut = MatchDevicePaths (OutDevicePath, Context->DevicePath);
        Context->IsStdErr = MatchDevicePaths (ErrDevicePath, Context->DevicePath);

        SPrint (Buffer, sizeof(Buffer), L"  %s", Context->DevicePathStr);
        Context->Menu = AllocateMenuOption (&ConsoleMenu, Buffer, Attribute, Context);
        Context->Menu->ContextPrint = ConsoleContextPrint;
        if (Context->ActiveConsole) { 
            ToggleSelectionStr(&ConsoleMenu,Context,Context->ActiveConsole);
////            Attribute = CON_SELECTED;
            ActiveConsoleCount++;
       } 
    }

    AllocateSpecialMenuOption (&ConsoleMenu, L"Save Settings to NVRAM", CON_UNSELECTED, CON_MENU_SAVE_NVRAM);
    AllocateSpecialMenuOption (&ConsoleMenu, L"Exit", CON_UNSELECTED, CON_MENU_EXIT);

    ConsoleMenu.Header = Header;
    ConsoleMenu.Footer = Footer;
    ConsoleMenu.Selection = NULL;
    NVRAMNeedsUpdating = FALSE;
    for (Done = FALSE, ResultContext = NULL; !Done;) {
        PreviousResultContext = ResultContext;
        ResultContext = MenuDisplay (&ConsoleMenu, &Key);
        if (!ResultContext) {
            Done = TRUE;
            break;
        }

        MenuOption = ResultContext->MenuOption;
        if (MenuOption == CON_MENU_EXIT) {
            if (NVRAMNeedsUpdating) {
                PrintAt (ResultContext->Menu->Col, ResultContext->Menu->Row + 2, L"NVRAM Not updated. Save NVRAM? [Y to save, N to ignore]");
                WaitForSingleEvent (ST->ConIn->WaitForKey, 0);
                ST->ConIn->ReadKeyStroke (ST->ConIn, &Key);
                if (Key.UnicodeChar == 'Y' || Key.UnicodeChar == 'y') {
                    MenuOption = CON_MENU_SAVE_NVRAM;
                }
            } 
            Done = TRUE;            
        }

        switch (MenuOption) {
        case CON_MENU_EXIT:
            break;           
        case CON_MENU_SAVE_NVRAM:
            Status = SetNvramForConsoleMenu (&ConsoleMenu, VarString, MenuType);
            if (EFI_ERROR(Status)) {
                PrintAt (ResultContext->Menu->Col, ResultContext->Menu->Row + 3, L"NVRAM update failed");
            } else {
                NVRAMNeedsUpdating = FALSE;
            }
            break;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?