| /** @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); | |
| } |