| /**@file | |
| This driver produces a VGA console. | |
| Copyright (c) 2006, 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 | |
| }; | |
| /** | |
| The user Entry Point for module VgaClass. The user code starts with this function. | |
| @param[in] ImageHandle The firmware allocated handle for the EFI image. | |
| @param[in] SystemTable A pointer to the EFI System Table. | |
| @retval EFI_SUCCESS The entry point is executed successfully. | |
| @retval other Some error occurs when executing this entry point. | |
| **/ | |
| 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 Status; | |
| } | |
| // | |
| // Local variables | |
| // | |
| CHAR16 CrLfString[3] = { CHAR_CARRIAGE_RETURN, CHAR_LINEFEED, CHAR_NULL }; | |
| typedef struct { | |
| CHAR16 Unicode; | |
| CHAR8 PcAnsi; | |
| CHAR8 Ascii; | |
| } UNICODE_TO_CHAR; | |
| // | |
| // 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 | |
| } | |
| }; | |
| // | |
| // Private worker functions | |
| // | |
| VOID | |
| SetVideoCursorPosition ( | |
| IN VGA_CLASS_DEV *VgaClassDev, | |
| IN UINTN Column, | |
| IN UINTN Row, | |
| IN UINTN MaxColumn | |
| ); | |
| VOID | |
| WriteCrtc ( | |
| IN VGA_CLASS_DEV *VgaClassDev, | |
| IN UINT16 Address, | |
| IN UINT8 Data | |
| ); | |
| BOOLEAN | |
| LibIsValidTextGraphics ( | |
| IN CHAR16 Graphic, | |
| OUT CHAR8 *PcAnsi, OPTIONAL | |
| OUT CHAR8 *Ascii OPTIONAL | |
| ); | |
| BOOLEAN | |
| IsValidAscii ( | |
| IN CHAR16 Ascii | |
| ); | |
| BOOLEAN | |
| IsValidEfiCntlChar ( | |
| IN CHAR16 c | |
| ); | |
| /** | |
| Test to see if this driver supports ControllerHandle. Any ControllerHandle | |
| than contains a VgaMiniPort and PciIo protocol can be supported. | |
| @param This Protocol instance pointer. | |
| @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 other 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 | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| EFI_VGA_MINI_PORT_PROTOCOL *VgaMiniPort; | |
| // | |
| // Open the IO Abstraction(s) needed to perform the supported test | |
| // | |
| Status = gBS->OpenProtocol ( | |
| Controller, | |
| &gEfiVgaMiniPortProtocolGuid, | |
| (VOID **) &VgaMiniPort, | |
| 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; | |
| } | |
| /** | |
| Start this driver on ControllerHandle by opening a PciIo and VgaMiniPort | |
| protocol, creating VGA_CLASS_DEV device and install gEfiSimpleTextOutProtocolGuid | |
| finnally. | |
| @param This Protocol instance pointer. | |
| @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 This driver is added to ControllerHandle | |
| @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle | |
| @retval other This driver does not support this device | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| VgaClassDriverBindingStart ( | |
| IN EFI_DRIVER_BINDING_PROTOCOL *This, | |
| IN EFI_HANDLE Controller, | |
| IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath | |
| ) | |
| { | |
| 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 IO Abstraction(s) needed | |
| // | |
| Status = gBS->OpenProtocol ( | |
| Controller, | |
| &gEfiPciIoProtocolGuid, | |
| (VOID **) &PciIo, | |
| This->DriverBindingHandle, | |
| Controller, | |
| EFI_OPEN_PROTOCOL_GET_PROTOCOL | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| 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 | |
| // | |
| Status = gBS->AllocatePool ( | |
| EfiBootServicesData, | |
| sizeof (VGA_CLASS_DEV), | |
| (VOID **) &VgaClassPrivate | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| gBS->CloseProtocol ( | |
| Controller, | |
| &gEfiVgaMiniPortProtocolGuid, | |
| This->DriverBindingHandle, | |
| Controller | |
| ); | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| ZeroMem (VgaClassPrivate, sizeof (VGA_CLASS_DEV)); | |
| // | |
| // 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; | |
| 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; | |
| } | |
| /** | |
| Stop this driver on ControllerHandle. Support stoping any child handles | |
| created by this driver. | |
| @param This Protocol instance pointer. | |
| @param ControllerHandle Handle of device to stop driver on | |
| @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of | |
| children is zero stop the entire bus driver. | |
| @param ChildHandleBuffer List of Child Handles to Stop. | |
| @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 | |
| ) | |
| { | |
| 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 | |
| ); | |
| gBS->FreePool (VgaClassPrivate); | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Reset VgaClass device and clear output. | |
| @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL. | |
| @param ExtendedVerification Whether need additional judgement | |
| **/ | |
| 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); | |
| } | |
| /** | |
| Output a string to VgaClass device. | |
| @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL. | |
| @param WString wide chars. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| VgaClassOutputString ( | |
| IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, | |
| IN CHAR16 *WString | |
| ) | |
| { | |
| 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; | |
| } | |
| for (; *WString != CHAR_NULL; WString++) { | |
| switch (*WString) { | |
| 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 (*WString, &GraphicChar, NULL)) { | |
| // | |
| // Just convert to ASCII | |
| // | |
| GraphicChar = (CHAR8) *WString; | |
| if (!IsValidAscii (GraphicChar)) { | |
| // | |
| // Keep the API from supporting PCANSI Graphics chars | |
| // | |
| 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; | |
| } | |
| /** | |
| Detects if a Unicode char is for Box Drawing text graphics. | |
| @param This Pointer of EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL | |
| @param WString Unicode chars | |
| @return if a Unicode char is for Box Drawing text graphics. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| VgaClassTestString ( | |
| IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, | |
| IN CHAR16 *WString | |
| ) | |
| { | |
| while (*WString != 0x0000) { | |
| if (!(IsValidAscii (*WString) || IsValidEfiCntlChar (*WString) || LibIsValidTextGraphics (*WString, NULL, NULL))) { | |
| return EFI_UNSUPPORTED; | |
| } | |
| WString++; | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Clear Screen via VgaClass device | |
| @param This Pointer of EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL | |
| @retval EFI_SUCESS Success to clear screen | |
| @retval Others Wrong displaying 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; | |
| } | |
| /** | |
| Set displaying mode's attribute | |
| @param This Pointer of EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL | |
| @param Attribute Mode's attribute | |
| @param EFI_SUCCESS Success to set attribute | |
| @param EFI_UNSUPPORTED Wrong mode's attribute wanted to be set | |
| **/ | |
| 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; | |
| } | |
| /** | |
| Set cursor position. | |
| @param This Pointer of EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL | |
| @param Column Column of new cursor position. | |
| @param Row Row of new cursor position. | |
| @retval EFI_SUCCESS Sucess to set cursor's position. | |
| @retval Others Wrong current displaying 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; | |
| } | |
| /** | |
| Enable cursor to display or not. | |
| @param This Pointer of EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL | |
| @param Visible Display cursor or not. | |
| @retval EFI_SUCESS Success to display the cursor or not. | |
| **/ | |
| 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) { | |
| switch (This->Mode->Mode) { | |
| case 1: | |
| WriteCrtc (VgaClassDev, CRTC_CURSOR_START, 0x06); | |
| WriteCrtc (VgaClassDev, CRTC_CURSOR_END, 0x07); | |
| break; | |
| default: | |
| WriteCrtc (VgaClassDev, CRTC_CURSOR_START, 0x0e); | |
| WriteCrtc (VgaClassDev, CRTC_CURSOR_END, 0x0f); | |
| break; | |
| } | |
| } else { | |
| WriteCrtc (VgaClassDev, CRTC_CURSOR_START, 0x20); | |
| } | |
| This->Mode->CursorVisible = Visible; | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Query colum and row according displaying mode number | |
| The mode: | |
| 0: 80 * 25 | |
| 1: 80 * 50 | |
| @param This Pointer of EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL | |
| @param ModeNumber Mode number | |
| @param Columns return the columen in current mode number | |
| @param Rows return the row in current mode number. | |
| @return EFI_SUCCESS Sucess to get columns and rows according to mode number | |
| @return EFI_UNSUPPORTED Unsupported mode number | |
| **/ | |
| 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; | |
| } | |
| /** | |
| Set displaying mode number | |
| @param This Pointer of EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL | |
| @param ModeNumber mode number | |
| @retval EFI_UNSUPPORTED Unsupported mode number in parameter | |
| @retval EFI_SUCCESS Success to set the mode number. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| VgaClassSetMode ( | |
| IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, | |
| IN UINTN ModeNumber | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| 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; | |
| Status = VgaClassDev->VgaMiniPort->SetMode (VgaClassDev->VgaMiniPort, ModeNumber); | |
| return Status; | |
| } | |
| /** | |
| Set logic cursor's position to VgaClass device | |
| @param VgaClassDev device instance object | |
| @param Column cursor logic position. | |
| @param Row cursor logic position. | |
| @param MaxColumn max logic 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) | |
| ); | |
| } | |
| /** | |
| Program CRTC register via PCI IO. | |
| @param VgaClassDev device instance object | |
| @param Address address | |
| @param Data data | |
| **/ | |
| 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 | |
| ); | |
| } | |
| /** | |
| Detects if a Unicode char is for Box Drawing text graphics. | |
| @param Grphic Unicode char to test. | |
| @param PcAnsi Optional pointer to return PCANSI equivalent of Graphic. | |
| @param Asci Optional pointer to return Ascii equivalent of Graphic. | |
| @return TRUE if Gpaphic is a supported Unicode Box Drawing character. | |
| **/ | |
| BOOLEAN | |
| LibIsValidTextGraphics ( | |
| IN CHAR16 Graphic, | |
| OUT CHAR8 *PcAnsi, OPTIONAL | |
| OUT CHAR8 *Ascii OPTIONAL | |
| ) | |
| { | |
| UNICODE_TO_CHAR *Table; | |
| if ((((Graphic & 0xff00) != 0x2500) && ((Graphic & 0xff00) != 0x2100))) { | |
| // | |
| // Unicode drawing code charts are all in the 0x25xx range, | |
| // arrows are 0x21xx | |
| // | |
| return FALSE; | |
| } | |
| for (Table = UnicodeToPcAnsiOrAscii; Table->Unicode != 0x0000; Table++) { | |
| if (Graphic == Table->Unicode) { | |
| if (PcAnsi) { | |
| *PcAnsi = Table->PcAnsi; | |
| } | |
| if (Ascii) { | |
| *Ascii = Table->Ascii; | |
| } | |
| return TRUE; | |
| } | |
| } | |
| return FALSE; | |
| } | |
| /** | |
| Judge whether is an ASCII char. | |
| @param Ascii character | |
| @return whether is an ASCII char. | |
| **/ | |
| BOOLEAN | |
| IsValidAscii ( | |
| IN CHAR16 Ascii | |
| ) | |
| { | |
| if ((Ascii >= 0x20) && (Ascii <= 0x7f)) { | |
| return TRUE; | |
| } | |
| return FALSE; | |
| } | |
| /** | |
| Judge whether is diplaying control character. | |
| @param c character | |
| @return whether is diplaying control character. | |
| **/ | |
| BOOLEAN | |
| IsValidEfiCntlChar ( | |
| IN CHAR16 c | |
| ) | |
| { | |
| if (c == CHAR_NULL || c == CHAR_BACKSPACE || c == CHAR_LINEFEED || c == CHAR_CARRIAGE_RETURN) { | |
| return TRUE; | |
| } | |
| return FALSE; | |
| } | |