mirror of https://github.com/acidanthera/audk.git
1289 lines
35 KiB
C
1289 lines
35 KiB
C
/** @file
|
|
VGA Class Driver that managers VGA devices and produces Simple Text Output Protocol.
|
|
|
|
Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
|
|
This program and the accompanying materials
|
|
are licensed and made available under the terms and conditions of the BSD License
|
|
which accompanies this distribution. The full text of the license may be found at
|
|
http://opensource.org/licenses/bsd-license.php
|
|
|
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
|
|
**/
|
|
|
|
#include "VgaClass.h"
|
|
|
|
//
|
|
// EFI Driver Binding Protocol for the VGA Class Driver
|
|
//
|
|
EFI_DRIVER_BINDING_PROTOCOL gVgaClassDriverBinding = {
|
|
VgaClassDriverBindingSupported,
|
|
VgaClassDriverBindingStart,
|
|
VgaClassDriverBindingStop,
|
|
0xa,
|
|
NULL,
|
|
NULL
|
|
};
|
|
|
|
//
|
|
// Local variables
|
|
//
|
|
CHAR16 CrLfString[3] = { CHAR_CARRIAGE_RETURN, CHAR_LINEFEED, CHAR_NULL };
|
|
|
|
//
|
|
// This list is used to define the valid extend chars.
|
|
// It also provides a mapping from Unicode to PCANSI or
|
|
// ASCII. The ASCII mapping we just made up.
|
|
//
|
|
//
|
|
UNICODE_TO_CHAR UnicodeToPcAnsiOrAscii[] = {
|
|
{
|
|
BOXDRAW_HORIZONTAL,
|
|
0xc4,
|
|
L'-'
|
|
},
|
|
{
|
|
BOXDRAW_VERTICAL,
|
|
0xb3,
|
|
L'|'
|
|
},
|
|
{
|
|
BOXDRAW_DOWN_RIGHT,
|
|
0xda,
|
|
L'/'
|
|
},
|
|
{
|
|
BOXDRAW_DOWN_LEFT,
|
|
0xbf,
|
|
L'\\'
|
|
},
|
|
{
|
|
BOXDRAW_UP_RIGHT,
|
|
0xc0,
|
|
L'\\'
|
|
},
|
|
{
|
|
BOXDRAW_UP_LEFT,
|
|
0xd9,
|
|
L'/'
|
|
},
|
|
{
|
|
BOXDRAW_VERTICAL_RIGHT,
|
|
0xc3,
|
|
L'|'
|
|
},
|
|
{
|
|
BOXDRAW_VERTICAL_LEFT,
|
|
0xb4,
|
|
L'|'
|
|
},
|
|
{
|
|
BOXDRAW_DOWN_HORIZONTAL,
|
|
0xc2,
|
|
L'+'
|
|
},
|
|
{
|
|
BOXDRAW_UP_HORIZONTAL,
|
|
0xc1,
|
|
L'+'
|
|
},
|
|
{
|
|
BOXDRAW_VERTICAL_HORIZONTAL,
|
|
0xc5,
|
|
L'+'
|
|
},
|
|
{
|
|
BOXDRAW_DOUBLE_HORIZONTAL,
|
|
0xcd,
|
|
L'-'
|
|
},
|
|
{
|
|
BOXDRAW_DOUBLE_VERTICAL,
|
|
0xba,
|
|
L'|'
|
|
},
|
|
{
|
|
BOXDRAW_DOWN_RIGHT_DOUBLE,
|
|
0xd5,
|
|
L'/'
|
|
},
|
|
{
|
|
BOXDRAW_DOWN_DOUBLE_RIGHT,
|
|
0xd6,
|
|
L'/'
|
|
},
|
|
{
|
|
BOXDRAW_DOUBLE_DOWN_RIGHT,
|
|
0xc9,
|
|
L'/'
|
|
},
|
|
{
|
|
BOXDRAW_DOWN_LEFT_DOUBLE,
|
|
0xb8,
|
|
L'\\'
|
|
},
|
|
{
|
|
BOXDRAW_DOWN_DOUBLE_LEFT,
|
|
0xb7,
|
|
L'\\'
|
|
},
|
|
{
|
|
BOXDRAW_DOUBLE_DOWN_LEFT,
|
|
0xbb,
|
|
L'\\'
|
|
},
|
|
{
|
|
BOXDRAW_UP_RIGHT_DOUBLE,
|
|
0xd4,
|
|
L'\\'
|
|
},
|
|
{
|
|
BOXDRAW_UP_DOUBLE_RIGHT,
|
|
0xd3,
|
|
L'\\'
|
|
},
|
|
{
|
|
BOXDRAW_DOUBLE_UP_RIGHT,
|
|
0xc8,
|
|
L'\\'
|
|
},
|
|
{
|
|
BOXDRAW_UP_LEFT_DOUBLE,
|
|
0xbe,
|
|
L'/'
|
|
},
|
|
{
|
|
BOXDRAW_UP_DOUBLE_LEFT,
|
|
0xbd,
|
|
L'/'
|
|
},
|
|
{
|
|
BOXDRAW_DOUBLE_UP_LEFT,
|
|
0xbc,
|
|
L'/'
|
|
},
|
|
{
|
|
BOXDRAW_VERTICAL_RIGHT_DOUBLE,
|
|
0xc6,
|
|
L'|'
|
|
},
|
|
{
|
|
BOXDRAW_VERTICAL_DOUBLE_RIGHT,
|
|
0xc7,
|
|
L'|'
|
|
},
|
|
{
|
|
BOXDRAW_DOUBLE_VERTICAL_RIGHT,
|
|
0xcc,
|
|
L'|'
|
|
},
|
|
{
|
|
BOXDRAW_VERTICAL_LEFT_DOUBLE,
|
|
0xb5,
|
|
L'|'
|
|
},
|
|
{
|
|
BOXDRAW_VERTICAL_DOUBLE_LEFT,
|
|
0xb6,
|
|
L'|'
|
|
},
|
|
{
|
|
BOXDRAW_DOUBLE_VERTICAL_LEFT,
|
|
0xb9,
|
|
L'|'
|
|
},
|
|
{
|
|
BOXDRAW_DOWN_HORIZONTAL_DOUBLE,
|
|
0xd1,
|
|
L'+'
|
|
},
|
|
{
|
|
BOXDRAW_DOWN_DOUBLE_HORIZONTAL,
|
|
0xd2,
|
|
L'+'
|
|
},
|
|
{
|
|
BOXDRAW_DOUBLE_DOWN_HORIZONTAL,
|
|
0xcb,
|
|
L'+'
|
|
},
|
|
{
|
|
BOXDRAW_UP_HORIZONTAL_DOUBLE,
|
|
0xcf,
|
|
L'+'
|
|
},
|
|
{
|
|
BOXDRAW_UP_DOUBLE_HORIZONTAL,
|
|
0xd0,
|
|
L'+'
|
|
},
|
|
{
|
|
BOXDRAW_DOUBLE_UP_HORIZONTAL,
|
|
0xca,
|
|
L'+'
|
|
},
|
|
{
|
|
BOXDRAW_VERTICAL_HORIZONTAL_DOUBLE,
|
|
0xd8,
|
|
L'+'
|
|
},
|
|
{
|
|
BOXDRAW_VERTICAL_DOUBLE_HORIZONTAL,
|
|
0xd7,
|
|
L'+'
|
|
},
|
|
{
|
|
BOXDRAW_DOUBLE_VERTICAL_HORIZONTAL,
|
|
0xce,
|
|
L'+'
|
|
},
|
|
|
|
{
|
|
BLOCKELEMENT_FULL_BLOCK,
|
|
0xdb,
|
|
L'*'
|
|
},
|
|
{
|
|
BLOCKELEMENT_LIGHT_SHADE,
|
|
0xb0,
|
|
L'+'
|
|
},
|
|
|
|
{
|
|
GEOMETRICSHAPE_UP_TRIANGLE,
|
|
0x1e,
|
|
L'^'
|
|
},
|
|
{
|
|
GEOMETRICSHAPE_RIGHT_TRIANGLE,
|
|
0x10,
|
|
L'>'
|
|
},
|
|
{
|
|
GEOMETRICSHAPE_DOWN_TRIANGLE,
|
|
0x1f,
|
|
L'v'
|
|
},
|
|
{
|
|
GEOMETRICSHAPE_LEFT_TRIANGLE,
|
|
0x11,
|
|
L'<'
|
|
},
|
|
|
|
{
|
|
ARROW_LEFT,
|
|
0x3c,
|
|
L'<'
|
|
},
|
|
|
|
{
|
|
ARROW_UP,
|
|
0x18,
|
|
L'^'
|
|
},
|
|
|
|
{
|
|
ARROW_RIGHT,
|
|
0x3e,
|
|
L'>'
|
|
},
|
|
|
|
{
|
|
ARROW_DOWN,
|
|
0x19,
|
|
L'v'
|
|
},
|
|
|
|
{
|
|
0x0000,
|
|
0x00,
|
|
0x00
|
|
}
|
|
};
|
|
|
|
/**
|
|
Entrypoint of this VGA Class Driver.
|
|
|
|
This function is the entrypoint of this VGA Class Driver. It installs Driver Binding
|
|
Protocols together with Component Name Protocols.
|
|
|
|
@param ImageHandle The firmware allocated handle for the EFI image.
|
|
@param SystemTable A pointer to the EFI System Table.
|
|
|
|
@retval EFI_SUCCESS The entry point is executed successfully.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
InitializeVgaClass(
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
//
|
|
// Install driver model protocol(s).
|
|
//
|
|
Status = EfiLibInstallDriverBindingComponentName2 (
|
|
ImageHandle,
|
|
SystemTable,
|
|
&gVgaClassDriverBinding,
|
|
ImageHandle,
|
|
&gVgaClassComponentName,
|
|
&gVgaClassComponentName2
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Internal worker function to program CRTC register via PCI I/O Protocol.
|
|
|
|
@param VgaClassDev device instance object
|
|
@param Address Address of register to write
|
|
@param Data Data to write to register.
|
|
|
|
**/
|
|
VOID
|
|
WriteCrtc (
|
|
IN VGA_CLASS_DEV *VgaClassDev,
|
|
IN UINT16 Address,
|
|
IN UINT8 Data
|
|
)
|
|
{
|
|
VgaClassDev->PciIo->Io.Write (
|
|
VgaClassDev->PciIo,
|
|
EfiPciIoWidthUint8,
|
|
VgaClassDev->VgaMiniPort->CrtcAddressRegisterBar,
|
|
VgaClassDev->VgaMiniPort->CrtcAddressRegisterOffset,
|
|
1,
|
|
&Address
|
|
);
|
|
|
|
VgaClassDev->PciIo->Io.Write (
|
|
VgaClassDev->PciIo,
|
|
EfiPciIoWidthUint8,
|
|
VgaClassDev->VgaMiniPort->CrtcDataRegisterBar,
|
|
VgaClassDev->VgaMiniPort->CrtcDataRegisterOffset,
|
|
1,
|
|
&Data
|
|
);
|
|
}
|
|
|
|
/**
|
|
Internal worker function to set cursor's position to VgaClass device
|
|
|
|
@param VgaClassDev Private data structure for device instance.
|
|
@param Column Colomn of position to set cursor to.
|
|
@param Row Row of position to set cursor to.
|
|
@param MaxColumn Max value of column.
|
|
|
|
**/
|
|
VOID
|
|
SetVideoCursorPosition (
|
|
IN VGA_CLASS_DEV *VgaClassDev,
|
|
IN UINTN Column,
|
|
IN UINTN Row,
|
|
IN UINTN MaxColumn
|
|
)
|
|
{
|
|
Column = Column & 0xff;
|
|
Row = Row & 0xff;
|
|
MaxColumn = MaxColumn & 0xff;
|
|
|
|
WriteCrtc (
|
|
VgaClassDev,
|
|
CRTC_CURSOR_LOCATION_HIGH,
|
|
(UINT8) ((Row * MaxColumn + Column) >> 8)
|
|
);
|
|
WriteCrtc (
|
|
VgaClassDev,
|
|
CRTC_CURSOR_LOCATION_LOW,
|
|
(UINT8) ((Row * MaxColumn + Column) & 0xff)
|
|
);
|
|
}
|
|
|
|
/**
|
|
Internal worker function to detect if a Unicode char is for Box Drawing text graphics.
|
|
|
|
@param Graphic Unicode char to test.
|
|
@param PcAnsi Pointer to PCANSI equivalent of Graphic for output.
|
|
If NULL, then PCANSI value is not returned.
|
|
@param Ascii Pointer to ASCII equivalent of Graphic for output.
|
|
If NULL, then ASCII value is not returned.
|
|
|
|
@retval TRUE Gpaphic is a supported Unicode Box Drawing character.
|
|
@retval FALSE Gpaphic is not a supported Unicode Box Drawing character.
|
|
|
|
**/
|
|
BOOLEAN
|
|
LibIsValidTextGraphics (
|
|
IN CHAR16 Graphic,
|
|
OUT CHAR8 *PcAnsi, OPTIONAL
|
|
OUT CHAR8 *Ascii OPTIONAL
|
|
)
|
|
{
|
|
UNICODE_TO_CHAR *Table;
|
|
|
|
//
|
|
// Unicode drawing code charts are all in the 0x25xx range, arrows are 0x21xx.
|
|
// So first filter out values not in these 2 ranges.
|
|
//
|
|
if ((((Graphic & 0xff00) != 0x2500) && ((Graphic & 0xff00) != 0x2100))) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Search UnicodeToPcAnsiOrAscii table for matching entry.
|
|
//
|
|
for (Table = UnicodeToPcAnsiOrAscii; Table->Unicode != 0x0000; Table++) {
|
|
if (Graphic == Table->Unicode) {
|
|
if (PcAnsi != NULL) {
|
|
*PcAnsi = Table->PcAnsi;
|
|
}
|
|
|
|
if (Ascii != NULL) {
|
|
*Ascii = Table->Ascii;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If value is not found in UnicodeToPcAnsiOrAscii table, then return FALSE.
|
|
//
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
Internal worker function to check whether input value is an ASCII char.
|
|
|
|
@param Char Character to check.
|
|
|
|
@retval TRUE Input value is an ASCII char.
|
|
@retval FALSE Input value is not an ASCII char.
|
|
|
|
**/
|
|
BOOLEAN
|
|
IsValidAscii (
|
|
IN CHAR16 Char
|
|
)
|
|
{
|
|
if ((Char >= 0x20) && (Char <= 0x7f)) {
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
Internal worker function to check whether input value is a unicode control char.
|
|
|
|
@param Char Character to check.
|
|
|
|
@retval TRUE Input value is a unicode control char.
|
|
@retval FALSE Input value is not a unicode control char.
|
|
|
|
**/
|
|
BOOLEAN
|
|
IsValidEfiCntlChar (
|
|
IN CHAR16 Char
|
|
)
|
|
{
|
|
if (Char == CHAR_NULL || Char == CHAR_BACKSPACE || Char == CHAR_LINEFEED || Char == CHAR_CARRIAGE_RETURN) {
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
Tests to see if this driver supports a given controller.
|
|
|
|
This function implments EFI_DRIVER_BINDING_PROTOCOL.Supported().
|
|
It Checks if this driver supports the controller specified. Any Controller
|
|
with VgaMiniPort Protocol and Pci I/O protocol can be supported.
|
|
|
|
@param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
|
|
@param ControllerHandle Handle of device to test
|
|
@param RemainingDevicePath Optional parameter use to pick a specific child
|
|
device to start.
|
|
|
|
@retval EFI_SUCCESS This driver supports this device.
|
|
@retval EFI_ALREADY_STARTED This driver is already running on this device.
|
|
@retval EFI_UNSUPPORTED This driver does not support this device.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
VgaClassDriverBindingSupported (
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE Controller,
|
|
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
//
|
|
// Checks if Abstraction(s) needed to perform the supported test
|
|
//
|
|
Status = gBS->OpenProtocol (
|
|
Controller,
|
|
&gEfiVgaMiniPortProtocolGuid,
|
|
NULL,
|
|
This->DriverBindingHandle,
|
|
Controller,
|
|
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
//
|
|
// Open the IO Abstraction(s) needed to perform the supported test
|
|
//
|
|
Status = gBS->OpenProtocol (
|
|
Controller,
|
|
&gEfiPciIoProtocolGuid,
|
|
NULL,
|
|
This->DriverBindingHandle,
|
|
Controller,
|
|
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Starts the device controller.
|
|
|
|
This function implments EFI_DRIVER_BINDING_PROTOCOL.Start().
|
|
It starts the device specified by Controller with the driver based on PCI I/O Protocol
|
|
and VgaMiniPort Protocol. It creates context for device instance and install EFI_SIMPLE_TEXT_OUT_PROTOCOL.
|
|
|
|
@param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
|
|
@param ControllerHandle Handle of device to bind driver to
|
|
@param RemainingDevicePath Optional parameter use to pick a specific child
|
|
device to start.
|
|
|
|
@retval EFI_SUCCESS The device was started.
|
|
@retval other Fail to start the device.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
VgaClassDriverBindingStart (
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE Controller,
|
|
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_VGA_MINI_PORT_PROTOCOL *VgaMiniPort;
|
|
EFI_PCI_IO_PROTOCOL *PciIo;
|
|
VGA_CLASS_DEV *VgaClassPrivate;
|
|
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
|
|
|
Status = gBS->HandleProtocol (
|
|
Controller,
|
|
&gEfiDevicePathProtocolGuid,
|
|
(VOID **) &DevicePath
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
//
|
|
// Report that VGA Class driver is being enabled
|
|
//
|
|
REPORT_STATUS_CODE_WITH_DEVICE_PATH (
|
|
EFI_PROGRESS_CODE,
|
|
EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_ENABLE,
|
|
DevicePath
|
|
);
|
|
|
|
//
|
|
// Open the PCI I/O Protocol
|
|
//
|
|
Status = gBS->OpenProtocol (
|
|
Controller,
|
|
&gEfiPciIoProtocolGuid,
|
|
(VOID **) &PciIo,
|
|
This->DriverBindingHandle,
|
|
Controller,
|
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
//
|
|
// Open the VGA Mini Port Protocol
|
|
//
|
|
Status = gBS->OpenProtocol (
|
|
Controller,
|
|
&gEfiVgaMiniPortProtocolGuid,
|
|
(VOID **) &VgaMiniPort,
|
|
This->DriverBindingHandle,
|
|
Controller,
|
|
EFI_OPEN_PROTOCOL_BY_DRIVER
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
//
|
|
// Allocate the private device structure
|
|
//
|
|
VgaClassPrivate = AllocateZeroPool (sizeof (VGA_CLASS_DEV));
|
|
ASSERT (VgaClassPrivate != NULL);
|
|
|
|
//
|
|
// Initialize the private device structure
|
|
//
|
|
VgaClassPrivate->Signature = VGA_CLASS_DEV_SIGNATURE;
|
|
VgaClassPrivate->Handle = Controller;
|
|
VgaClassPrivate->VgaMiniPort = VgaMiniPort;
|
|
VgaClassPrivate->PciIo = PciIo;
|
|
|
|
VgaClassPrivate->SimpleTextOut.Reset = VgaClassReset;
|
|
VgaClassPrivate->SimpleTextOut.OutputString = VgaClassOutputString;
|
|
VgaClassPrivate->SimpleTextOut.TestString = VgaClassTestString;
|
|
VgaClassPrivate->SimpleTextOut.ClearScreen = VgaClassClearScreen;
|
|
VgaClassPrivate->SimpleTextOut.SetAttribute = VgaClassSetAttribute;
|
|
VgaClassPrivate->SimpleTextOut.SetCursorPosition = VgaClassSetCursorPosition;
|
|
VgaClassPrivate->SimpleTextOut.EnableCursor = VgaClassEnableCursor;
|
|
VgaClassPrivate->SimpleTextOut.QueryMode = VgaClassQueryMode;
|
|
VgaClassPrivate->SimpleTextOut.SetMode = VgaClassSetMode;
|
|
|
|
VgaClassPrivate->SimpleTextOut.Mode = &VgaClassPrivate->SimpleTextOutputMode;
|
|
VgaClassPrivate->SimpleTextOutputMode.MaxMode = VgaMiniPort->MaxMode;
|
|
VgaClassPrivate->DevicePath = DevicePath;
|
|
|
|
//
|
|
// Initialize the VGA device.
|
|
//
|
|
Status = VgaClassPrivate->SimpleTextOut.SetAttribute (
|
|
&VgaClassPrivate->SimpleTextOut,
|
|
EFI_TEXT_ATTR (EFI_WHITE, EFI_BLACK)
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
goto ErrorExit;
|
|
}
|
|
|
|
Status = VgaClassPrivate->SimpleTextOut.Reset (
|
|
&VgaClassPrivate->SimpleTextOut,
|
|
FALSE
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
goto ErrorExit;
|
|
}
|
|
|
|
Status = VgaClassPrivate->SimpleTextOut.EnableCursor (
|
|
&VgaClassPrivate->SimpleTextOut,
|
|
TRUE
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
goto ErrorExit;
|
|
}
|
|
|
|
Status = gBS->InstallMultipleProtocolInterfaces (
|
|
&Controller,
|
|
&gEfiSimpleTextOutProtocolGuid,
|
|
&VgaClassPrivate->SimpleTextOut,
|
|
NULL
|
|
);
|
|
|
|
return Status;
|
|
|
|
ErrorExit:
|
|
REPORT_STATUS_CODE_WITH_DEVICE_PATH (
|
|
EFI_ERROR_CODE | EFI_ERROR_MINOR,
|
|
EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR,
|
|
DevicePath
|
|
);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
/**
|
|
Starts the device controller.
|
|
|
|
This function implments EFI_DRIVER_BINDING_PROTOCOL.Stop().
|
|
It stops this driver on Controller. Support stopping any child handles
|
|
created by this driver.
|
|
|
|
@param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
|
|
@param ControllerHandle A handle to the device being stopped.
|
|
@param NumberOfChildren The number of child device handles in ChildHandleBuffer.
|
|
@param ChildHandleBuffer An array of child handles to be freed.
|
|
|
|
@retval EFI_SUCCESS This driver is removed ControllerHandle
|
|
@retval other This driver was not removed from this device
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
VgaClassDriverBindingStop (
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE Controller,
|
|
IN UINTN NumberOfChildren,
|
|
IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut;
|
|
VGA_CLASS_DEV *VgaClassPrivate;
|
|
|
|
Status = gBS->OpenProtocol (
|
|
Controller,
|
|
&gEfiSimpleTextOutProtocolGuid,
|
|
(VOID **) &SimpleTextOut,
|
|
This->DriverBindingHandle,
|
|
Controller,
|
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
VgaClassPrivate = VGA_CLASS_DEV_FROM_THIS (SimpleTextOut);
|
|
|
|
//
|
|
// Report that VGA Class driver is being disabled
|
|
//
|
|
REPORT_STATUS_CODE_WITH_DEVICE_PATH (
|
|
EFI_PROGRESS_CODE,
|
|
EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_DISABLE,
|
|
VgaClassPrivate->DevicePath
|
|
);
|
|
|
|
Status = gBS->UninstallProtocolInterface (
|
|
Controller,
|
|
&gEfiSimpleTextOutProtocolGuid,
|
|
&VgaClassPrivate->SimpleTextOut
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
//
|
|
// Release PCI I/O and VGA Mini Port Protocols on the controller handle.
|
|
//
|
|
gBS->CloseProtocol (
|
|
Controller,
|
|
&gEfiPciIoProtocolGuid,
|
|
This->DriverBindingHandle,
|
|
Controller
|
|
);
|
|
|
|
gBS->CloseProtocol (
|
|
Controller,
|
|
&gEfiVgaMiniPortProtocolGuid,
|
|
This->DriverBindingHandle,
|
|
Controller
|
|
);
|
|
|
|
FreePool (VgaClassPrivate);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Resets the text output device hardware.
|
|
|
|
This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.Reset().
|
|
It resets the text output device hardware. The cursor position is set to (0, 0),
|
|
and the screen is cleared to the default background color for the output device.
|
|
|
|
@param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance.
|
|
@param ExtendedVerification Indicates that the driver may perform a more exhaustive
|
|
verification operation of the device during reset.
|
|
|
|
@retval EFI_SUCCESS The text output device was reset.
|
|
@retval EFI_DEVICE_ERROR The text output device is not functioning correctly and could not be reset.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
VgaClassReset (
|
|
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
|
|
IN BOOLEAN ExtendedVerification
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
VGA_CLASS_DEV *VgaClassPrivate;
|
|
|
|
VgaClassPrivate = VGA_CLASS_DEV_FROM_THIS (This);
|
|
|
|
REPORT_STATUS_CODE_WITH_DEVICE_PATH (
|
|
EFI_PROGRESS_CODE,
|
|
EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_RESET,
|
|
VgaClassPrivate->DevicePath
|
|
);
|
|
|
|
This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BACKGROUND_BLACK));
|
|
|
|
Status = This->SetMode (This, 0);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
return This->ClearScreen (This);
|
|
}
|
|
|
|
/**
|
|
Writes a Unicode string to the output device.
|
|
|
|
This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString().
|
|
It writes a Unicode string to the output device. This is the most basic output mechanism
|
|
on an output device.
|
|
|
|
@param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance.
|
|
@param String The Null-terminated Unicode string to be displayed on the output device(s).
|
|
|
|
@retval EFI_SUCCESS The string was output to the device.
|
|
@retval EFI_DEVICE_ERROR The device reported an error while attempting to output the text.
|
|
@retval EFI_UNSUPPORTED The output device's mode is not currently in a defined text mode.
|
|
@retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the characters in
|
|
the Unicode string could not be rendered and were skipped.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
VgaClassOutputString (
|
|
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
|
|
IN CHAR16 *String
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
VGA_CLASS_DEV *VgaClassDev;
|
|
EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode;
|
|
UINTN MaxColumn;
|
|
UINTN MaxRow;
|
|
UINT32 VideoChar;
|
|
CHAR8 GraphicChar;
|
|
|
|
VgaClassDev = VGA_CLASS_DEV_FROM_THIS (This);
|
|
Mode = This->Mode;
|
|
|
|
Status = This->QueryMode (
|
|
This,
|
|
Mode->Mode,
|
|
&MaxColumn,
|
|
&MaxRow
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Parse each character of the string to output
|
|
//
|
|
for (; *String != CHAR_NULL; String++) {
|
|
|
|
switch (*String) {
|
|
case CHAR_BACKSPACE:
|
|
if (Mode->CursorColumn > 0) {
|
|
Mode->CursorColumn--;
|
|
}
|
|
break;
|
|
|
|
case CHAR_LINEFEED:
|
|
if (Mode->CursorRow == (INT32) (MaxRow - 1)) {
|
|
//
|
|
// Scroll the screen by copying the contents
|
|
// of the VGA display up one line
|
|
//
|
|
VgaClassDev->PciIo->CopyMem (
|
|
VgaClassDev->PciIo,
|
|
EfiPciIoWidthUint32,
|
|
VgaClassDev->VgaMiniPort->VgaMemoryBar,
|
|
VgaClassDev->VgaMiniPort->VgaMemoryOffset,
|
|
VgaClassDev->VgaMiniPort->VgaMemoryBar,
|
|
VgaClassDev->VgaMiniPort->VgaMemoryOffset + MaxColumn * 2,
|
|
((MaxRow - 1) * MaxColumn) >> 1
|
|
);
|
|
|
|
//
|
|
// Print Blank Line of spaces with the current color attributes
|
|
//
|
|
VideoChar = (Mode->Attribute << 8) | ' ';
|
|
VideoChar = (VideoChar << 16) | VideoChar;
|
|
VgaClassDev->PciIo->Mem.Write (
|
|
VgaClassDev->PciIo,
|
|
EfiPciIoWidthFillUint32,
|
|
VgaClassDev->VgaMiniPort->VgaMemoryBar,
|
|
VgaClassDev->VgaMiniPort->VgaMemoryOffset + (MaxRow - 1) * MaxColumn * 2,
|
|
MaxColumn >> 1,
|
|
&VideoChar
|
|
);
|
|
}
|
|
|
|
if (Mode->CursorRow < (INT32) (MaxRow - 1)) {
|
|
Mode->CursorRow++;
|
|
}
|
|
break;
|
|
|
|
case CHAR_CARRIAGE_RETURN:
|
|
Mode->CursorColumn = 0;
|
|
break;
|
|
|
|
default:
|
|
if (!LibIsValidTextGraphics (*String, &GraphicChar, NULL)) {
|
|
//
|
|
// If this character is not ,Box Drawing text graphics, then convert it to ASCII.
|
|
//
|
|
GraphicChar = (CHAR8) *String;
|
|
if (!IsValidAscii (GraphicChar)) {
|
|
//
|
|
// If not valid ASCII char, convert it to "?"
|
|
//
|
|
GraphicChar = '?';
|
|
}
|
|
}
|
|
|
|
VideoChar = (Mode->Attribute << 8) | GraphicChar;
|
|
VgaClassDev->PciIo->Mem.Write (
|
|
VgaClassDev->PciIo,
|
|
EfiPciIoWidthUint16,
|
|
VgaClassDev->VgaMiniPort->VgaMemoryBar,
|
|
VgaClassDev->VgaMiniPort->VgaMemoryOffset + ((Mode->CursorRow * MaxColumn + Mode->CursorColumn) * 2),
|
|
1,
|
|
&VideoChar
|
|
);
|
|
|
|
if (Mode->CursorColumn >= (INT32) (MaxColumn - 1)) {
|
|
This->OutputString (This, CrLfString);
|
|
} else {
|
|
Mode->CursorColumn++;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
SetVideoCursorPosition (
|
|
VgaClassDev,
|
|
(UINTN) Mode->CursorColumn,
|
|
(UINTN) Mode->CursorRow,
|
|
MaxColumn
|
|
);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Verifies that all characters in a Unicode string can be output to the target device.
|
|
|
|
This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.TestString().
|
|
It verifies that all characters in a Unicode string can be output to the target device.
|
|
|
|
@param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance.
|
|
@param String The Null-terminated Unicode string to be examined for the output device(s).
|
|
|
|
@retval EFI_SUCCESS The device(s) are capable of rendering the output string.
|
|
@retval EFI_UNSUPPORTED Some of the characters in the Unicode string cannot be rendered by
|
|
one or more of the output devices mapped by the EFI handle.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
VgaClassTestString (
|
|
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
|
|
IN CHAR16 *String
|
|
)
|
|
{
|
|
while (*String != CHAR_NULL) {
|
|
if (!(IsValidAscii (*String) || IsValidEfiCntlChar (*String) || LibIsValidTextGraphics (*String, NULL, NULL))) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
String++;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Clears the output device(s) display to the currently selected background color.
|
|
|
|
This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.ClearScreen().
|
|
The ClearScreen() function clears the output device(s) display to the currently
|
|
selected background color. The cursor position is set to (0, 0).
|
|
|
|
@param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance.
|
|
|
|
@retval EFI_SUCESS The operation completed successfully.
|
|
@retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
|
|
@retval EFI_UNSUPPORTED The output device is not in a valid text mode.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
VgaClassClearScreen (
|
|
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
VGA_CLASS_DEV *VgaClassDev;
|
|
UINTN MaxRow;
|
|
UINTN MaxColumn;
|
|
UINT32 VideoChar;
|
|
|
|
VgaClassDev = VGA_CLASS_DEV_FROM_THIS (This);
|
|
|
|
Status = This->QueryMode (
|
|
This,
|
|
This->Mode->Mode,
|
|
&MaxColumn,
|
|
&MaxRow
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
VideoChar = (This->Mode->Attribute << 8) | ' ';
|
|
VideoChar = (VideoChar << 16) | VideoChar;
|
|
VgaClassDev->PciIo->Mem.Write (
|
|
VgaClassDev->PciIo,
|
|
EfiPciIoWidthFillUint32,
|
|
VgaClassDev->VgaMiniPort->VgaMemoryBar,
|
|
VgaClassDev->VgaMiniPort->VgaMemoryOffset,
|
|
(MaxRow * MaxColumn) >> 1,
|
|
&VideoChar
|
|
);
|
|
|
|
This->SetCursorPosition (This, 0, 0);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Sets the background and foreground colors for theOutputString() and ClearScreen() functions.
|
|
|
|
This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetAttribute().
|
|
It sets the background and foreground colors for the OutputString() and ClearScreen() functions.
|
|
The color mask can be set even when the device is in an invalid text mode.
|
|
Devices supporting a different number of text colors are required to emulate the above colors
|
|
to the best of the device's capabilities.
|
|
|
|
@param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance.
|
|
@param Attribute The attribute to set.
|
|
Bits 0..3 are the foreground color,
|
|
and bits 4..6 are the background color.
|
|
|
|
@retval EFI_SUCCESS The requested attributes were set.
|
|
@retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
VgaClassSetAttribute (
|
|
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
|
|
IN UINTN Attribute
|
|
)
|
|
{
|
|
if (Attribute <= EFI_MAX_ATTRIBUTE) {
|
|
This->Mode->Attribute = (INT32) Attribute;
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
/**
|
|
Sets the current coordinates of the cursor position.
|
|
|
|
This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetCursorPosition().
|
|
It sets the current coordinates of the cursor position.
|
|
The upper left corner of the screen is defined as coordinate (0, 0).
|
|
|
|
@param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance.
|
|
@param Column Column of position to set the cursor to.
|
|
@param Row Row of position to set the cursor to.
|
|
|
|
@retval EFI_SUCCESS The operation completed successfully.
|
|
@retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
|
|
@retval EFI_UNSUPPORTED The output device is not in a valid text mode, or the cursor
|
|
position is invalid for the current mode.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
VgaClassSetCursorPosition (
|
|
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
|
|
IN UINTN Column,
|
|
IN UINTN Row
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
VGA_CLASS_DEV *VgaClassDev;
|
|
UINTN MaxColumn;
|
|
UINTN MaxRow;
|
|
|
|
VgaClassDev = VGA_CLASS_DEV_FROM_THIS (This);
|
|
|
|
Status = This->QueryMode (
|
|
This,
|
|
This->Mode->Mode,
|
|
&MaxColumn,
|
|
&MaxRow
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
if (Column >= MaxColumn || Row >= MaxRow) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
SetVideoCursorPosition (VgaClassDev, Column, Row, MaxColumn);
|
|
|
|
This->Mode->CursorColumn = (INT32) Column;
|
|
This->Mode->CursorRow = (INT32) Row;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Makes the cursor visible or invisible.
|
|
|
|
This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.EnableCursor().
|
|
It makes the cursor visible or invisible.
|
|
|
|
@param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance.
|
|
@param Visible If TRUE, the cursor is set to be visible.
|
|
If FALSE, the cursor is set to be invisible.
|
|
|
|
@retval EFI_SUCESS The operation completed successfully.
|
|
@retval EFI_DEVICE_ERROR The device had an error and could not complete the request or the
|
|
device does not support changing the cursor mode.
|
|
@retval EFI_UNSUPPORTED The output device does not support visibility control of the cursor.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
VgaClassEnableCursor (
|
|
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
|
|
IN BOOLEAN Visible
|
|
)
|
|
{
|
|
VGA_CLASS_DEV *VgaClassDev;
|
|
|
|
VgaClassDev = VGA_CLASS_DEV_FROM_THIS (This);
|
|
if (Visible) {
|
|
if (This->Mode->Mode == 1) {
|
|
//
|
|
// 80 * 50
|
|
//
|
|
WriteCrtc (VgaClassDev, CRTC_CURSOR_START, 0x06);
|
|
WriteCrtc (VgaClassDev, CRTC_CURSOR_END, 0x07);
|
|
} else {
|
|
//
|
|
// 80 * 25
|
|
//
|
|
WriteCrtc (VgaClassDev, CRTC_CURSOR_START, 0x0e);
|
|
WriteCrtc (VgaClassDev, CRTC_CURSOR_END, 0x0f);
|
|
}
|
|
} else {
|
|
WriteCrtc (VgaClassDev, CRTC_CURSOR_START, 0x20);
|
|
}
|
|
|
|
This->Mode->CursorVisible = Visible;
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Returns information for an available text mode that the output device(s) supports.
|
|
|
|
This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.QueryMode().
|
|
It returns information for an available text mode that the output device(s) supports.
|
|
It is required that all output devices support at least 80x25 text mode. This mode is defined to be mode 0.
|
|
If the output devices support 80x50, that is defined to be mode 1.
|
|
|
|
@param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance.
|
|
@param ModeNumber The mode number to return information on.
|
|
@param Columns Columen in current mode number
|
|
@param Rows Row in current mode number.
|
|
|
|
@retval EFI_SUCCESS The requested mode information was returned.
|
|
@retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
|
|
@retval EFI_UNSUPPORTED The mode number was not valid.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
VgaClassQueryMode (
|
|
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
|
|
IN UINTN ModeNumber,
|
|
OUT UINTN *Columns,
|
|
OUT UINTN *Rows
|
|
)
|
|
{
|
|
if ((INT32) ModeNumber >= This->Mode->MaxMode) {
|
|
*Columns = 0;
|
|
*Rows = 0;
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
switch (ModeNumber) {
|
|
case 0:
|
|
*Columns = 80;
|
|
*Rows = 25;
|
|
break;
|
|
|
|
case 1:
|
|
*Columns = 80;
|
|
*Rows = 50;
|
|
break;
|
|
|
|
default:
|
|
*Columns = 0;
|
|
*Rows = 0;
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Sets the output device(s) to a specified mode.
|
|
|
|
This function implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.QueryMode().
|
|
It sets the output device(s) to the requested mode.
|
|
On success the device is in the geometry for the requested mode,
|
|
and the device has been cleared to the current background color with the cursor at (0,0).
|
|
|
|
@param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance.
|
|
@param ModeNumber The text mode to set.
|
|
|
|
@retval EFI_SUCCESS The requested text mode was set.
|
|
@retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
|
|
@retval EFI_UNSUPPORTED The mode number was not valid.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
VgaClassSetMode (
|
|
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
|
|
IN UINTN ModeNumber
|
|
)
|
|
{
|
|
VGA_CLASS_DEV *VgaClassDev;
|
|
|
|
VgaClassDev = VGA_CLASS_DEV_FROM_THIS (This);
|
|
|
|
if ((INT32) ModeNumber >= This->Mode->MaxMode) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
This->ClearScreen (This);
|
|
|
|
This->Mode->Mode = (INT32) ModeNumber;
|
|
|
|
return VgaClassDev->VgaMiniPort->SetMode (VgaClassDev->VgaMiniPort, ModeNumber);
|
|
}
|