terminal.c
来自「Next BIOS Source code : Extensible Firmw」· C语言 代码 · 共 1,176 行 · 第 1/3 页
C
1,176 行
/*++
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:
Terminal.c
Abstract:
Revision History:
--*/
#include "Terminal.h"
//
// Function Prototypes
//
EFI_STATUS
TerminalDriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
);
EFI_STATUS
TerminalDriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
);
EFI_STATUS
TerminalDriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
);
//
// Globals
//
EFI_DRIVER_BINDING_PROTOCOL gTerminalDriverBinding = {
TerminalDriverBindingSupported,
TerminalDriverBindingStart,
TerminalDriverBindingStop,
0x10,
NULL,
NULL
};
EFI_GUID gTerminalDriverGuid = {
0x10634d8e, 0x1c05, 0x46cb, 0xbb, 0xc, 0x5a, 0xfd, 0xc8, 0x29, 0xa8, 0xc8
};
//
// Body of the driver
//
EFI_DRIVER_ENTRY_POINT (InitializeTerminal)
EFI_STATUS
InitializeTerminal (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
/*++
Routine Description:
This function is the entry point of Terminal driver.
Arguments:
EFI_HANDLE IN ImageHandle
A handle for the image that is initializing this driver.
EFI_SYSTEM_TABLE IN *SystemTable
A pointer to the EFI system table.
Returns:
EFI_SUCCESS
only returns this status code.
--*/
{
//
// install driver binding protocol and component name protocol.
//
return EfiLibInstallAllDriverProtocols (
ImageHandle,
SystemTable,
&gTerminalDriverBinding,
ImageHandle,
&gTerminalComponentName,
NULL,
NULL
);
}
EFI_STATUS
TerminalDriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
/*++
Routine Description:
Arguments:
Returns:
--*/
{
EFI_STATUS Status;
EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
EFI_SERIAL_IO_PROTOCOL *SerialIo;
VENDOR_DEVICE_PATH *Node;
//
// If remaining device path is not NULL, then make sure it is a
// device path that describes a terminal communications protocol.
//
if (RemainingDevicePath != NULL) {
Node = (VENDOR_DEVICE_PATH *)RemainingDevicePath;
if (Node->Header.Type != MESSAGING_DEVICE_PATH ||
Node->Header.SubType != MSG_VENDOR_DP ||
DevicePathNodeLength(&Node->Header) != sizeof(VENDOR_DEVICE_PATH)) {
return EFI_UNSUPPORTED;
}
//
// only supports PC ANSI, VT100, VT100+ and VT-UTF8 terminal types
//
if (!EfiCompareGuid (&Node->Guid, &gEfiPcAnsiGuid) &&
!EfiCompareGuid (&Node->Guid, &gEfiVT100Guid) &&
!EfiCompareGuid (&Node->Guid, &gEfiVT100PlusGuid) &&
!EfiCompareGuid (&Node->Guid, &gEfiVTUTF8Guid)) {
return EFI_UNSUPPORTED;
}
}
//
// Open the IO Abstraction(s) needed to perform the supported test
//
Status = gBS->OpenProtocol (
Controller,
&gEfiDevicePathProtocolGuid,
(VOID **)&ParentDevicePath,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (Status == EFI_ALREADY_STARTED) {
return EFI_SUCCESS;
}
if (EFI_ERROR (Status)) {
return Status;
}
gBS->CloseProtocol (
Controller,
&gEfiDevicePathProtocolGuid,
This->DriverBindingHandle,
Controller
);
//
// The Controller must support the Serial I/O Protocol.
// This driver is a bus driver with at most 1 child device, so it is
// ok for it to be already started.
//
Status = gBS->OpenProtocol (
Controller,
&gEfiSerialIoProtocolGuid,
(VOID **)&SerialIo,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (Status == EFI_ALREADY_STARTED) {
return EFI_SUCCESS;
}
if (EFI_ERROR (Status)) {
return Status;
}
//
// Close the I/O Abstraction(s) used to perform the supported test
//
gBS->CloseProtocol (
Controller,
&gEfiSerialIoProtocolGuid,
This->DriverBindingHandle,
Controller
);
return Status;
}
EFI_STATUS
TerminalDriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
/*++
Routine Description:
Arguments:
Returns:
--*/
{
EFI_STATUS Status;
EFI_SERIAL_IO_PROTOCOL *SerialIo;
EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
VENDOR_DEVICE_PATH *Node;
EFI_SERIAL_IO_MODE *Mode;
UINTN SerialInTimeOut;
TERMINAL_DEV *TerminalDevice = NULL;
UINT8 TerminalType;
EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
UINTN EntryCount;
UINTN Index;
//
// Get the Device Path Protocol to build the device path of the child device
//
Status = gBS->OpenProtocol (
Controller,
&gEfiDevicePathProtocolGuid,
(VOID **)&ParentDevicePath,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
return Status;
}
//
// Open the Serial I/O Protocol BY_DRIVER. It might already be started.
//
Status = gBS->OpenProtocol (
Controller,
&gEfiSerialIoProtocolGuid,
(VOID **)&SerialIo,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
return Status;
}
if (Status != EFI_ALREADY_STARTED) {
//
// If Serial I/O is not already open by this driver, then tag the handle
// with the Terminal Driver GUID and update the ConInDev, ConOutDev, and
// StdErrDev variables with the list of possible terminal types on this
// serial port.
//
Status = gBS->OpenProtocol (
Controller,
&gTerminalDriverGuid,
NULL,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
);
if (EFI_ERROR (Status)) {
Status = gBS->InstallMultipleProtocolInterfaces (
&Controller,
&gTerminalDriverGuid,
EfiDuplicateDevicePath (ParentDevicePath),
NULL
);
if (EFI_ERROR (Status)) {
goto Error;
}
//
// if the serial device is a hot plug device, do not update the
// ConInDev, ConOutDev, and StdErrDev variables.
//
Status = gBS->OpenProtocol (
Controller,
&gEfiHotPlugDeviceGuid,
NULL,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
);
if (EFI_ERROR(Status)) {
TerminalUpdateConsoleDevVariable (VarConsoleInpDev, ParentDevicePath);
TerminalUpdateConsoleDevVariable (VarConsoleOutDev, ParentDevicePath);
TerminalUpdateConsoleDevVariable (VarErrorOutDev, ParentDevicePath);
}
}
}
//
// If RemainingDevicePath is NULL, then there is no enough information
// to create a child device, so return
//
if (RemainingDevicePath == NULL) {
return EFI_SUCCESS;
}
//
// Make sure a child handle does not already exist. This driver can only
// produce one child per serial port.
//
Status = gBS->OpenProtocolInformation (
Controller,
&gEfiSerialIoProtocolGuid,
&OpenInfoBuffer,
&EntryCount
);
if (!EFI_ERROR (Status)) {
Status = EFI_SUCCESS;
for (Index = 0; Index < EntryCount; Index++) {
if (OpenInfoBuffer[Index].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {
Status = EFI_ALREADY_STARTED;
}
}
gBS->FreePool (OpenInfoBuffer);
if (EFI_ERROR (Status)) {
return Status;
}
}
//
// Use the RemainingDevicePath to determine the terminal type
//
Node = (VENDOR_DEVICE_PATH *)RemainingDevicePath;
if (EfiCompareGuid (&Node->Guid, &gEfiPcAnsiGuid)) {
TerminalType = PcAnsiType;
} else if (EfiCompareGuid (&Node->Guid, &gEfiVT100Guid)) {
TerminalType = VT100Type;
} else if (EfiCompareGuid (&Node->Guid, &gEfiVT100PlusGuid)) {
TerminalType = VT100PlusType;
} else if (EfiCompareGuid (&Node->Guid, &gEfiVTUTF8Guid)) {
TerminalType = VTUTF8Type;
} else {
goto Error;
}
//
// Initialize the Terminal Dev
//
Status = gBS->AllocatePool (
EfiBootServicesData,
sizeof (TERMINAL_DEV),
(VOID **)&TerminalDevice
);
if (EFI_ERROR (Status)) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?