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. 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 stoping 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<63>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<63>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);
|
||
}
|