/** @file | |
VGA Class Driver that managers VGA devices and produces Simple Text Output Protocol. | |
Copyright (c) 2006 - 2018, 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); | |
} |