| /**@file | |
| This is the main routine for initializing the Graphics Console support routines. | |
| Remaining Tasks | |
| Add all standard Glyphs from EFI 1.02 Specification | |
| Implement optimal automatic Mode creation algorithm | |
| Solve palette issues for mixed graphics and text | |
| When does this protocol reset the palette? | |
| Copyright (c) 2006 - 2007 Intel Corporation. <BR> | |
| 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 "GraphicsConsole.h" | |
| STATIC | |
| EFI_STATUS | |
| GetTextColors ( | |
| IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, | |
| OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Foreground, | |
| OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Background | |
| ); | |
| STATIC | |
| EFI_STATUS | |
| DrawUnicodeWeightAtCursorN ( | |
| IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, | |
| IN CHAR16 *UnicodeWeight, | |
| IN UINTN Count | |
| ); | |
| STATIC | |
| EFI_STATUS | |
| EraseCursor ( | |
| IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This | |
| ); | |
| // | |
| // Globals | |
| // | |
| GRAPHICS_CONSOLE_DEV mGraphicsConsoleDevTemplate = { | |
| GRAPHICS_CONSOLE_DEV_SIGNATURE, | |
| (EFI_GRAPHICS_OUTPUT_PROTOCOL *) NULL, | |
| (EFI_UGA_DRAW_PROTOCOL *) NULL, | |
| { | |
| GraphicsConsoleConOutReset, | |
| GraphicsConsoleConOutOutputString, | |
| GraphicsConsoleConOutTestString, | |
| GraphicsConsoleConOutQueryMode, | |
| GraphicsConsoleConOutSetMode, | |
| GraphicsConsoleConOutSetAttribute, | |
| GraphicsConsoleConOutClearScreen, | |
| GraphicsConsoleConOutSetCursorPosition, | |
| GraphicsConsoleConOutEnableCursor, | |
| (EFI_SIMPLE_TEXT_OUTPUT_MODE *) NULL | |
| }, | |
| { | |
| 0, | |
| 0, | |
| EFI_TEXT_ATTR(EFI_LIGHTGRAY, EFI_BLACK), | |
| 0, | |
| 0, | |
| TRUE | |
| }, | |
| { | |
| { 80, 25, 0, 0, 0, 0 }, // Mode 0 | |
| { 80, 50, 0, 0, 0, 0 }, // Mode 1 | |
| { 0, 0, 0, 0, 0, 0 } // Mode 2 | |
| }, | |
| (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) NULL, | |
| (EFI_HII_HANDLE) 0 | |
| }; | |
| EFI_HII_PROTOCOL *mHii; | |
| static CHAR16 mCrLfString[3] = { CHAR_CARRIAGE_RETURN, CHAR_LINEFEED, CHAR_NULL }; | |
| static EFI_GRAPHICS_OUTPUT_BLT_PIXEL mEfiColors[16] = { | |
| // | |
| // B G R | |
| // | |
| {0x00, 0x00, 0x00, 0x00}, // BLACK | |
| {0x98, 0x00, 0x00, 0x00}, // BLUE | |
| {0x00, 0x98, 0x00, 0x00}, // GREEN | |
| {0x98, 0x98, 0x00, 0x00}, // CYAN | |
| {0x00, 0x00, 0x98, 0x00}, // RED | |
| {0x98, 0x00, 0x98, 0x00}, // MAGENTA | |
| {0x00, 0x98, 0x98, 0x00}, // BROWN | |
| {0x98, 0x98, 0x98, 0x00}, // LIGHTGRAY | |
| {0x30, 0x30, 0x30, 0x00}, // DARKGRAY - BRIGHT BLACK | |
| {0xff, 0x00, 0x00, 0x00}, // LIGHTBLUE - ? | |
| {0x00, 0xff, 0x00, 0x00}, // LIGHTGREEN - ? | |
| {0xff, 0xff, 0x00, 0x00}, // LIGHTCYAN | |
| {0x00, 0x00, 0xff, 0x00}, // LIGHTRED | |
| {0xff, 0x00, 0xff, 0x00}, // LIGHTMAGENTA | |
| {0x00, 0xff, 0xff, 0x00}, // LIGHTBROWN | |
| {0xff, 0xff, 0xff, 0x00} // WHITE | |
| }; | |
| static EFI_NARROW_GLYPH mCursorGlyph = { | |
| 0x0000, | |
| 0x00, | |
| { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF } | |
| }; | |
| EFI_DRIVER_BINDING_PROTOCOL gGraphicsConsoleDriverBinding = { | |
| GraphicsConsoleControllerDriverSupported, | |
| GraphicsConsoleControllerDriverStart, | |
| GraphicsConsoleControllerDriverStop, | |
| 0xa, | |
| NULL, | |
| NULL | |
| }; | |
| EFI_STATUS | |
| EFIAPI | |
| GraphicsConsoleControllerDriverSupported ( | |
| IN EFI_DRIVER_BINDING_PROTOCOL *This, | |
| IN EFI_HANDLE Controller, | |
| IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; | |
| EFI_UGA_DRAW_PROTOCOL *UgaDraw; | |
| EFI_DEVICE_PATH_PROTOCOL *DevicePath; | |
| UgaDraw = NULL; | |
| // | |
| // Open the IO Abstraction(s) needed to perform the supported test | |
| // | |
| Status = gBS->OpenProtocol ( | |
| Controller, | |
| &gEfiGraphicsOutputProtocolGuid, | |
| (VOID **) &GraphicsOutput, | |
| This->DriverBindingHandle, | |
| Controller, | |
| EFI_OPEN_PROTOCOL_BY_DRIVER | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| GraphicsOutput = NULL; | |
| // | |
| // Open Graphics Output Protocol failed, try to open UGA Draw Protocol | |
| // | |
| Status = gBS->OpenProtocol ( | |
| Controller, | |
| &gEfiUgaDrawProtocolGuid, | |
| (VOID **) &UgaDraw, | |
| This->DriverBindingHandle, | |
| Controller, | |
| EFI_OPEN_PROTOCOL_BY_DRIVER | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| } | |
| // | |
| // We need to ensure that we do not layer on top of a virtual handle. | |
| // We need to ensure that the handles produced by the conspliter do not | |
| // get used. | |
| // | |
| Status = gBS->OpenProtocol ( | |
| Controller, | |
| &gEfiDevicePathProtocolGuid, | |
| (VOID **) &DevicePath, | |
| This->DriverBindingHandle, | |
| Controller, | |
| EFI_OPEN_PROTOCOL_BY_DRIVER | |
| ); | |
| if (!EFI_ERROR (Status)) { | |
| gBS->CloseProtocol ( | |
| Controller, | |
| &gEfiDevicePathProtocolGuid, | |
| This->DriverBindingHandle, | |
| Controller | |
| ); | |
| } else { | |
| goto Error; | |
| } | |
| // | |
| // Does Hii Exist? If not, we aren't ready to run | |
| // | |
| Status = EfiLocateHiiProtocol (); | |
| // | |
| // Close the I/O Abstraction(s) used to perform the supported test | |
| // | |
| Error: | |
| if (GraphicsOutput != NULL) { | |
| gBS->CloseProtocol ( | |
| Controller, | |
| &gEfiGraphicsOutputProtocolGuid, | |
| This->DriverBindingHandle, | |
| Controller | |
| ); | |
| } else { | |
| gBS->CloseProtocol ( | |
| Controller, | |
| &gEfiUgaDrawProtocolGuid, | |
| This->DriverBindingHandle, | |
| Controller | |
| ); | |
| } | |
| return Status; | |
| } | |
| EFI_STATUS | |
| EFIAPI | |
| GraphicsConsoleControllerDriverStart ( | |
| IN EFI_DRIVER_BINDING_PROTOCOL *This, | |
| IN EFI_HANDLE Controller, | |
| IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath | |
| ) | |
| /*++ | |
| Routine Description: | |
| Start the controller. | |
| Arguments: | |
| This - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. | |
| Controller - The handle of the controller to start. | |
| RemainingDevicePath - A pointer to the remaining portion of a devcie path. | |
| Returns: | |
| EFI_SUCCESS - Return successfully. | |
| EFI_OUT_OF_RESOURCES - Out of resources. | |
| --*/ | |
| { | |
| EFI_STATUS Status; | |
| GRAPHICS_CONSOLE_DEV *Private; | |
| EFI_HII_PACKAGES *Package; | |
| EFI_HII_FONT_PACK *FontPack; | |
| UINTN NarrowFontSize; | |
| UINT32 HorizontalResolution; | |
| UINT32 VerticalResolution; | |
| UINT32 ColorDepth; | |
| UINT32 RefreshRate; | |
| UINTN MaxMode; | |
| UINTN Columns; | |
| UINTN Rows; | |
| UINT8 *Location; | |
| UINT32 ModeNumber; | |
| UINTN SizeOfInfo; | |
| EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; | |
| ModeNumber = 0; | |
| // | |
| // Initialize the Graphics Console device instance | |
| // | |
| Private = AllocateCopyPool ( | |
| sizeof (GRAPHICS_CONSOLE_DEV), | |
| &mGraphicsConsoleDevTemplate | |
| ); | |
| if (Private == NULL) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| Private->SimpleTextOutput.Mode = &(Private->SimpleTextOutputMode); | |
| Status = gBS->OpenProtocol ( | |
| Controller, | |
| &gEfiGraphicsOutputProtocolGuid, | |
| (VOID **) &Private->GraphicsOutput, | |
| This->DriverBindingHandle, | |
| Controller, | |
| EFI_OPEN_PROTOCOL_BY_DRIVER | |
| ); | |
| if (EFI_ERROR(Status)) { | |
| Private->GraphicsOutput = NULL; | |
| Status = gBS->OpenProtocol ( | |
| Controller, | |
| &gEfiUgaDrawProtocolGuid, | |
| (VOID **) &Private->UgaDraw, | |
| This->DriverBindingHandle, | |
| Controller, | |
| EFI_OPEN_PROTOCOL_BY_DRIVER | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| goto Error; | |
| } | |
| } | |
| // | |
| // Get the HII protocol. If Supported() succeeds, do we really | |
| // need to get HII protocol again? | |
| // | |
| Status = EfiLocateHiiProtocol (); | |
| if (EFI_ERROR (Status)) { | |
| goto Error; | |
| } | |
| NarrowFontSize = ReturnNarrowFontSize (); | |
| FontPack = AllocateZeroPool (sizeof (EFI_HII_FONT_PACK) + NarrowFontSize); | |
| ASSERT (FontPack); | |
| FontPack->Header.Length = (UINT32) (sizeof (EFI_HII_FONT_PACK) + NarrowFontSize); | |
| FontPack->Header.Type = EFI_HII_FONT; | |
| FontPack->NumberOfNarrowGlyphs = (UINT16) (NarrowFontSize / sizeof (EFI_NARROW_GLYPH)); | |
| Location = (UINT8 *) (&FontPack->NumberOfWideGlyphs + sizeof (UINT8)); | |
| CopyMem (Location, UsStdNarrowGlyphData, NarrowFontSize); | |
| // | |
| // Register our Fonts into the global database | |
| // | |
| Package = PreparePackages (1, NULL, FontPack); | |
| mHii->NewPack (mHii, Package, &(Private->HiiHandle)); | |
| FreePool (Package); | |
| // | |
| // Free the font database | |
| // | |
| FreePool (FontPack); | |
| // | |
| // If the current mode information can not be retrieved, then attemp to set the default mode | |
| // of 800x600, 32 bit colot, 60 Hz refresh. | |
| // | |
| HorizontalResolution = 800; | |
| VerticalResolution = 600; | |
| if (Private->GraphicsOutput != NULL) { | |
| // | |
| // The console is build on top of Graphics Output Protocol, find the mode number for 800x600 | |
| // | |
| for (ModeNumber = 0; ModeNumber < Private->GraphicsOutput->Mode->MaxMode; ModeNumber++) { | |
| Status = Private->GraphicsOutput->QueryMode ( | |
| Private->GraphicsOutput, | |
| ModeNumber, | |
| &SizeOfInfo, | |
| &Info | |
| ); | |
| if (!EFI_ERROR (Status)) { | |
| if ((Info->HorizontalResolution == 800) && | |
| (Info->VerticalResolution == 600)) { | |
| Status = Private->GraphicsOutput->SetMode (Private->GraphicsOutput, ModeNumber); | |
| if (!EFI_ERROR (Status)) { | |
| FreePool (Info); | |
| break; | |
| } | |
| } | |
| FreePool (Info); | |
| } | |
| } | |
| if (EFI_ERROR (Status) || (ModeNumber == Private->GraphicsOutput->Mode->MaxMode)) { | |
| // | |
| // Set default mode failed or device don't support default mode, then get the current mode information | |
| // | |
| HorizontalResolution = Private->GraphicsOutput->Mode->Info->HorizontalResolution; | |
| VerticalResolution = Private->GraphicsOutput->Mode->Info->VerticalResolution; | |
| ModeNumber = Private->GraphicsOutput->Mode->Mode; | |
| } | |
| } else { | |
| // | |
| // The console is build on top of UGA Draw Protocol | |
| // | |
| ColorDepth = 32; | |
| RefreshRate = 60; | |
| Status = Private->UgaDraw->SetMode ( | |
| Private->UgaDraw, | |
| HorizontalResolution, | |
| VerticalResolution, | |
| ColorDepth, | |
| RefreshRate | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| // | |
| // Get the current mode information from the UGA Draw Protocol | |
| // | |
| Status = Private->UgaDraw->GetMode ( | |
| Private->UgaDraw, | |
| &HorizontalResolution, | |
| &VerticalResolution, | |
| &ColorDepth, | |
| &RefreshRate | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| goto Error; | |
| } | |
| } | |
| } | |
| // | |
| // Compute the maximum number of text Rows and Columns that this current graphics mode can support | |
| // | |
| Columns = HorizontalResolution / GLYPH_WIDTH; | |
| Rows = VerticalResolution / GLYPH_HEIGHT; | |
| // | |
| // See if the mode is too small to support the required 80x25 text mode | |
| // | |
| if (Columns < 80 || Rows < 25) { | |
| goto Error; | |
| } | |
| // | |
| // Add Mode #0 that must be 80x25 | |
| // | |
| MaxMode = 0; | |
| Private->ModeData[MaxMode].GopWidth = HorizontalResolution; | |
| Private->ModeData[MaxMode].GopHeight = VerticalResolution; | |
| Private->ModeData[MaxMode].GopModeNumber = ModeNumber; | |
| Private->ModeData[MaxMode].DeltaX = (HorizontalResolution - (80 * GLYPH_WIDTH)) >> 1; | |
| Private->ModeData[MaxMode].DeltaY = (VerticalResolution - (25 * GLYPH_HEIGHT)) >> 1; | |
| MaxMode++; | |
| // | |
| // If it is possible to support Mode #1 - 80x50, than add it as an active mode | |
| // | |
| if (Rows >= 50) { | |
| Private->ModeData[MaxMode].GopWidth = HorizontalResolution; | |
| Private->ModeData[MaxMode].GopHeight = VerticalResolution; | |
| Private->ModeData[MaxMode].GopModeNumber = ModeNumber; | |
| Private->ModeData[MaxMode].DeltaX = (HorizontalResolution - (80 * GLYPH_WIDTH)) >> 1; | |
| Private->ModeData[MaxMode].DeltaY = (VerticalResolution - (50 * GLYPH_HEIGHT)) >> 1; | |
| MaxMode++; | |
| } | |
| // | |
| // If the graphics mode is 800x600, than add a text mode that uses the entire display | |
| // | |
| if (HorizontalResolution == 800 && VerticalResolution == 600) { | |
| if (MaxMode < 2) { | |
| Private->ModeData[MaxMode].Columns = 0; | |
| Private->ModeData[MaxMode].Rows = 0; | |
| Private->ModeData[MaxMode].GopWidth = 800; | |
| Private->ModeData[MaxMode].GopHeight = 600; | |
| Private->ModeData[MaxMode].GopModeNumber = ModeNumber; | |
| Private->ModeData[MaxMode].DeltaX = 0; | |
| Private->ModeData[MaxMode].DeltaY = 0; | |
| MaxMode++; | |
| } | |
| Private->ModeData[MaxMode].Columns = 800 / GLYPH_WIDTH; | |
| Private->ModeData[MaxMode].Rows = 600 / GLYPH_HEIGHT; | |
| Private->ModeData[MaxMode].GopWidth = 800; | |
| Private->ModeData[MaxMode].GopHeight = 600; | |
| Private->ModeData[MaxMode].GopModeNumber = ModeNumber; | |
| Private->ModeData[MaxMode].DeltaX = (800 % GLYPH_WIDTH) >> 1; | |
| Private->ModeData[MaxMode].DeltaY = (600 % GLYPH_HEIGHT) >> 1; | |
| MaxMode++; | |
| } | |
| // | |
| // Update the maximum number of modes | |
| // | |
| Private->SimpleTextOutputMode.MaxMode = (INT32) MaxMode; | |
| // | |
| // Determine the number of text modes that this protocol can support | |
| // | |
| Status = GraphicsConsoleConOutSetMode (&Private->SimpleTextOutput, 0); | |
| if (EFI_ERROR (Status)) { | |
| goto Error; | |
| } | |
| DEBUG_CODE_BEGIN (); | |
| GraphicsConsoleConOutOutputString (&Private->SimpleTextOutput, (CHAR16 *)L"Graphics Console Started\n\r"); | |
| DEBUG_CODE_END (); | |
| // | |
| // Install protocol interfaces for the Graphics Console device. | |
| // | |
| Status = gBS->InstallMultipleProtocolInterfaces ( | |
| &Controller, | |
| &gEfiSimpleTextOutProtocolGuid, | |
| &Private->SimpleTextOutput, | |
| NULL | |
| ); | |
| Error: | |
| if (EFI_ERROR (Status)) { | |
| // | |
| // Close the GOP or UGA IO Protocol | |
| // | |
| if (Private->GraphicsOutput != NULL) { | |
| gBS->CloseProtocol ( | |
| Controller, | |
| &gEfiGraphicsOutputProtocolGuid, | |
| This->DriverBindingHandle, | |
| Controller | |
| ); | |
| } else { | |
| gBS->CloseProtocol ( | |
| Controller, | |
| &gEfiUgaDrawProtocolGuid, | |
| This->DriverBindingHandle, | |
| Controller | |
| ); | |
| } | |
| // | |
| // Free private data | |
| // | |
| if (Private != NULL) { | |
| if (Private->LineBuffer != NULL) { | |
| FreePool (Private->LineBuffer); | |
| } | |
| FreePool (Private); | |
| } | |
| } | |
| return Status; | |
| } | |
| EFI_STATUS | |
| EFIAPI | |
| GraphicsConsoleControllerDriverStop ( | |
| 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 *SimpleTextOutput; | |
| GRAPHICS_CONSOLE_DEV *Private; | |
| Status = gBS->OpenProtocol ( | |
| Controller, | |
| &gEfiSimpleTextOutProtocolGuid, | |
| (VOID **) &SimpleTextOutput, | |
| This->DriverBindingHandle, | |
| Controller, | |
| EFI_OPEN_PROTOCOL_GET_PROTOCOL | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| return EFI_NOT_STARTED; | |
| } | |
| Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (SimpleTextOutput); | |
| Status = gBS->UninstallProtocolInterface ( | |
| Controller, | |
| &gEfiSimpleTextOutProtocolGuid, | |
| &Private->SimpleTextOutput | |
| ); | |
| if (!EFI_ERROR (Status)) { | |
| // | |
| // Close the GOP or UGA IO Protocol | |
| // | |
| if (Private->GraphicsOutput != NULL) { | |
| gBS->CloseProtocol ( | |
| Controller, | |
| &gEfiGraphicsOutputProtocolGuid, | |
| This->DriverBindingHandle, | |
| Controller | |
| ); | |
| } else { | |
| gBS->CloseProtocol ( | |
| Controller, | |
| &gEfiUgaDrawProtocolGuid, | |
| This->DriverBindingHandle, | |
| Controller | |
| ); | |
| } | |
| // | |
| // Remove the font pack | |
| // | |
| mHii->RemovePack (mHii, Private->HiiHandle); | |
| // | |
| // Free our instance data | |
| // | |
| if (Private != NULL) { | |
| FreePool (Private->LineBuffer); | |
| FreePool (Private); | |
| } | |
| } | |
| return Status; | |
| } | |
| EFI_STATUS | |
| EfiLocateHiiProtocol ( | |
| VOID | |
| ) | |
| /*++ | |
| Routine Description: | |
| Find if the HII protocol is available. If yes, locate the HII protocol | |
| Arguments: | |
| Returns: | |
| --*/ | |
| { | |
| EFI_HANDLE Handle; | |
| UINTN Size; | |
| EFI_STATUS Status; | |
| // | |
| // There should only be one - so buffer size is this | |
| // | |
| Size = sizeof (EFI_HANDLE); | |
| Status = gBS->LocateHandle ( | |
| ByProtocol, | |
| &gEfiHiiProtocolGuid, | |
| NULL, | |
| &Size, | |
| &Handle | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| Status = gBS->HandleProtocol ( | |
| Handle, | |
| &gEfiHiiProtocolGuid, | |
| (VOID **)&mHii | |
| ); | |
| return Status; | |
| } | |
| // | |
| // Body of the STO functions | |
| // | |
| EFI_STATUS | |
| EFIAPI | |
| GraphicsConsoleConOutReset ( | |
| IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, | |
| IN BOOLEAN ExtendedVerification | |
| ) | |
| /*++ | |
| Routine Description: | |
| Implements SIMPLE_TEXT_OUTPUT.Reset(). | |
| If ExtendeVerification is TRUE, then perform dependent Graphics Console | |
| device reset, and set display mode to mode 0. | |
| If ExtendedVerification is FALSE, only set display mode to mode 0. | |
| Arguments: | |
| This - Indicates the calling context. | |
| ExtendedVerification - Indicates that the driver may perform a more exhaustive | |
| verification operation of the device during reset. | |
| Returns: | |
| EFI_SUCCESS | |
| The reset operation succeeds. | |
| EFI_DEVICE_ERROR | |
| The Graphics Console is not functioning correctly | |
| --*/ | |
| { | |
| This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BACKGROUND_BLACK)); | |
| return This->SetMode (This, 0); | |
| } | |
| EFI_STATUS | |
| EFIAPI | |
| GraphicsConsoleConOutOutputString ( | |
| IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, | |
| IN CHAR16 *WString | |
| ) | |
| /*++ | |
| Routine Description: | |
| Implements SIMPLE_TEXT_OUTPUT.OutputString(). | |
| The Unicode string will be converted to Glyphs and will be | |
| sent to the Graphics Console. | |
| Arguments: | |
| This - Indicates the calling context. | |
| WString - The Null-terminated Unicode string to be displayed on | |
| the Graphics Console. | |
| Returns: | |
| EFI_SUCCESS | |
| The string is output successfully. | |
| EFI_DEVICE_ERROR | |
| The Graphics Console failed to send the string out. | |
| EFI_WARN_UNKNOWN_GLYPH | |
| Indicates that some of the characters in the Unicode string could not | |
| be rendered and are skipped. | |
| --*/ | |
| { | |
| GRAPHICS_CONSOLE_DEV *Private; | |
| EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; | |
| EFI_UGA_DRAW_PROTOCOL *UgaDraw; | |
| INTN Mode; | |
| UINTN MaxColumn; | |
| UINTN MaxRow; | |
| UINTN Width; | |
| UINTN Height; | |
| UINTN Delta; | |
| EFI_STATUS Status; | |
| BOOLEAN Warning; | |
| EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground; | |
| EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background; | |
| UINTN DeltaX; | |
| UINTN DeltaY; | |
| UINTN Count; | |
| UINTN Index; | |
| INT32 OriginAttribute; | |
| EFI_TPL OldTpl; | |
| CHAR16 SpaceStr[] = { NARROW_CHAR, ' ', 0 }; | |
| Status = EFI_SUCCESS; | |
| OldTpl = gBS->RaiseTPL (TPL_NOTIFY); | |
| // | |
| // Current mode | |
| // | |
| Mode = This->Mode->Mode; | |
| Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This); | |
| GraphicsOutput = Private->GraphicsOutput; | |
| UgaDraw = Private->UgaDraw; | |
| MaxColumn = Private->ModeData[Mode].Columns; | |
| MaxRow = Private->ModeData[Mode].Rows; | |
| DeltaX = Private->ModeData[Mode].DeltaX; | |
| DeltaY = Private->ModeData[Mode].DeltaY; | |
| Width = MaxColumn * GLYPH_WIDTH; | |
| Height = (MaxRow - 1) * GLYPH_HEIGHT; | |
| Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL); | |
| // | |
| // The Attributes won't change when during the time OutputString is called | |
| // | |
| GetTextColors (This, &Foreground, &Background); | |
| EraseCursor (This); | |
| Warning = FALSE; | |
| // | |
| // Backup attribute | |
| // | |
| OriginAttribute = This->Mode->Attribute; | |
| while (*WString) { | |
| if (*WString == CHAR_BACKSPACE) { | |
| // | |
| // If the cursor is at the left edge of the display, then move the cursor | |
| // one row up. | |
| // | |
| if (This->Mode->CursorColumn == 0 && This->Mode->CursorRow > 0) { | |
| This->Mode->CursorRow--; | |
| This->Mode->CursorColumn = (INT32) (MaxColumn - 1); | |
| This->OutputString (This, SpaceStr); | |
| EraseCursor (This); | |
| This->Mode->CursorRow--; | |
| This->Mode->CursorColumn = (INT32) (MaxColumn - 1); | |
| } else if (This->Mode->CursorColumn > 0) { | |
| // | |
| // If the cursor is not at the left edge of the display, then move the cursor | |
| // left one column. | |
| // | |
| This->Mode->CursorColumn--; | |
| This->OutputString (This, SpaceStr); | |
| EraseCursor (This); | |
| This->Mode->CursorColumn--; | |
| } | |
| WString++; | |
| } else if (*WString == CHAR_LINEFEED) { | |
| // | |
| // If the cursor is at the bottom of the display, then scroll the display one | |
| // row, and do not update the cursor position. Otherwise, move the cursor | |
| // down one row. | |
| // | |
| if (This->Mode->CursorRow == (INT32) (MaxRow - 1)) { | |
| if (GraphicsOutput != NULL) { | |
| // | |
| // Scroll Screen Up One Row | |
| // | |
| GraphicsOutput->Blt ( | |
| GraphicsOutput, | |
| NULL, | |
| EfiBltVideoToVideo, | |
| DeltaX, | |
| DeltaY + GLYPH_HEIGHT, | |
| DeltaX, | |
| DeltaY, | |
| Width, | |
| Height, | |
| Delta | |
| ); | |
| // | |
| // Print Blank Line at last line | |
| // | |
| GraphicsOutput->Blt ( | |
| GraphicsOutput, | |
| &Background, | |
| EfiBltVideoFill, | |
| 0, | |
| 0, | |
| DeltaX, | |
| DeltaY + Height, | |
| Width, | |
| GLYPH_HEIGHT, | |
| Delta | |
| ); | |
| } else { | |
| // | |
| // Scroll Screen Up One Row | |
| // | |
| UgaDraw->Blt ( | |
| UgaDraw, | |
| NULL, | |
| EfiUgaVideoToVideo, | |
| DeltaX, | |
| DeltaY + GLYPH_HEIGHT, | |
| DeltaX, | |
| DeltaY, | |
| Width, | |
| Height, | |
| Delta | |
| ); | |
| // | |
| // Print Blank Line at last line | |
| // | |
| UgaDraw->Blt ( | |
| UgaDraw, | |
| (EFI_UGA_PIXEL *) (UINTN) &Background, | |
| EfiUgaVideoFill, | |
| 0, | |
| 0, | |
| DeltaX, | |
| DeltaY + Height, | |
| Width, | |
| GLYPH_HEIGHT, | |
| Delta | |
| ); | |
| } | |
| } else { | |
| This->Mode->CursorRow++; | |
| } | |
| WString++; | |
| } else if (*WString == CHAR_CARRIAGE_RETURN) { | |
| // | |
| // Move the cursor to the beginning of the current row. | |
| // | |
| This->Mode->CursorColumn = 0; | |
| WString++; | |
| } else if (*WString == WIDE_CHAR) { | |
| This->Mode->Attribute |= EFI_WIDE_ATTRIBUTE; | |
| WString++; | |
| } else if (*WString == NARROW_CHAR) { | |
| This->Mode->Attribute &= (~ (UINT32) EFI_WIDE_ATTRIBUTE); | |
| WString++; | |
| } else { | |
| // | |
| // Print the character at the current cursor position and move the cursor | |
| // right one column. If this moves the cursor past the right edge of the | |
| // display, then the line should wrap to the beginning of the next line. This | |
| // is equivalent to inserting a CR and an LF. Note that if the cursor is at the | |
| // bottom of the display, and the line wraps, then the display will be scrolled | |
| // one line. | |
| // If wide char is going to be displayed, need to display one character at a time | |
| // Or, need to know the display length of a certain string. | |
| // | |
| // Index is used to determine how many character width units (wide = 2, narrow = 1) | |
| // Count is used to determine how many characters are used regardless of their attributes | |
| // | |
| for (Count = 0, Index = 0; (This->Mode->CursorColumn + Index) < MaxColumn; Count++, Index++) { | |
| if (WString[Count] == CHAR_NULL) { | |
| break; | |
| } | |
| if (WString[Count] == CHAR_BACKSPACE) { | |
| break; | |
| } | |
| if (WString[Count] == CHAR_LINEFEED) { | |
| break; | |
| } | |
| if (WString[Count] == CHAR_CARRIAGE_RETURN) { | |
| break; | |
| } | |
| if (WString[Count] == WIDE_CHAR) { | |
| break; | |
| } | |
| if (WString[Count] == NARROW_CHAR) { | |
| break; | |
| } | |
| // | |
| // Is the wide attribute on? | |
| // | |
| if (This->Mode->Attribute & EFI_WIDE_ATTRIBUTE) { | |
| // | |
| // If wide, add one more width unit than normal since we are going to increment at the end of the for loop | |
| // | |
| Index++; | |
| // | |
| // This is the end-case where if we are at column 79 and about to print a wide character | |
| // We should prevent this from happening because we will wrap inappropriately. We should | |
| // not print this character until the next line. | |
| // | |
| if ((This->Mode->CursorColumn + Index + 1) > MaxColumn) { | |
| Index++; | |
| break; | |
| } | |
| } | |
| } | |
| Status = DrawUnicodeWeightAtCursorN (This, WString, Count); | |
| if (EFI_ERROR (Status)) { | |
| Warning = TRUE; | |
| } | |
| // | |
| // At the end of line, output carriage return and line feed | |
| // | |
| WString += Count; | |
| This->Mode->CursorColumn += (INT32) Index; | |
| if (This->Mode->CursorColumn > (INT32) MaxColumn) { | |
| This->Mode->CursorColumn -= 2; | |
| This->OutputString (This, SpaceStr); | |
| } | |
| if (This->Mode->CursorColumn >= (INT32) MaxColumn) { | |
| EraseCursor (This); | |
| This->OutputString (This, mCrLfString); | |
| EraseCursor (This); | |
| } | |
| } | |
| } | |
| This->Mode->Attribute = OriginAttribute; | |
| EraseCursor (This); | |
| if (Warning) { | |
| Status = EFI_WARN_UNKNOWN_GLYPH; | |
| } | |
| gBS->RestoreTPL (OldTpl); | |
| return Status; | |
| } | |
| EFI_STATUS | |
| EFIAPI | |
| GraphicsConsoleConOutTestString ( | |
| IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, | |
| IN CHAR16 *WString | |
| ) | |
| /*++ | |
| Routine Description: | |
| Implements SIMPLE_TEXT_OUTPUT.TestString(). | |
| If one of the characters in the *Wstring is | |
| neither valid valid Unicode drawing characters, | |
| not ASCII code, then this function will return | |
| EFI_UNSUPPORTED. | |
| Arguments: | |
| This - Indicates the calling context. | |
| WString - The Null-terminated Unicode string to be tested. | |
| Returns: | |
| EFI_SUCCESS | |
| The Graphics Console is capable of rendering the output string. | |
| EFI_UNSUPPORTED | |
| Some of the characters in the Unicode string cannot be rendered. | |
| --*/ | |
| { | |
| EFI_STATUS Status; | |
| UINT16 GlyphWidth; | |
| UINT32 GlyphStatus; | |
| UINT16 Count; | |
| GLYPH_UNION *Glyph; | |
| GlyphStatus = 0; | |
| Count = 0; | |
| while (WString[Count]) { | |
| Status = mHii->GetGlyph ( | |
| mHii, | |
| WString, | |
| &Count, | |
| (UINT8 **) &Glyph, | |
| &GlyphWidth, | |
| &GlyphStatus | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| return EFI_UNSUPPORTED; | |
| } | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| EFI_STATUS | |
| EFIAPI | |
| GraphicsConsoleConOutQueryMode ( | |
| IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, | |
| IN UINTN ModeNumber, | |
| OUT UINTN *Columns, | |
| OUT UINTN *Rows | |
| ) | |
| /*++ | |
| Routine Description: | |
| Implements SIMPLE_TEXT_OUTPUT.QueryMode(). | |
| It returnes information for an available text mode | |
| that the Graphics Console supports. | |
| In this driver,we only support text mode 80x25, which is | |
| defined as mode 0. | |
| Arguments: | |
| This - Indicates the calling context. | |
| ModeNumber - The mode number to return information on. | |
| Columns - The returned columns of the requested mode. | |
| Rows - The returned rows of the requested mode. | |
| Returns: | |
| EFI_SUCCESS | |
| The requested mode information is returned. | |
| EFI_UNSUPPORTED | |
| The mode number is not valid. | |
| --*/ | |
| { | |
| GRAPHICS_CONSOLE_DEV *Private; | |
| EFI_STATUS Status; | |
| EFI_TPL OldTpl; | |
| if (ModeNumber >= (UINTN) This->Mode->MaxMode) { | |
| return EFI_UNSUPPORTED; | |
| } | |
| OldTpl = gBS->RaiseTPL (TPL_NOTIFY); | |
| Status = EFI_SUCCESS; | |
| Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This); | |
| *Columns = Private->ModeData[ModeNumber].Columns; | |
| *Rows = Private->ModeData[ModeNumber].Rows; | |
| if (*Columns <= 0 && *Rows <= 0) { | |
| Status = EFI_UNSUPPORTED; | |
| goto Done; | |
| } | |
| Done: | |
| gBS->RestoreTPL (OldTpl); | |
| return Status; | |
| } | |
| EFI_STATUS | |
| EFIAPI | |
| GraphicsConsoleConOutSetMode ( | |
| IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, | |
| IN UINTN ModeNumber | |
| ) | |
| /*++ | |
| Routine Description: | |
| Implements SIMPLE_TEXT_OUTPUT.SetMode(). | |
| Set the Graphics Console to a specified mode. | |
| In this driver, we only support mode 0. | |
| Arguments: | |
| This - Indicates the calling context. | |
| ModeNumber - The text mode to set. | |
| Returns: | |
| EFI_SUCCESS | |
| The requested text mode is set. | |
| EFI_DEVICE_ERROR | |
| The requested text mode cannot be set because of Graphics Console device error. | |
| EFI_UNSUPPORTED | |
| The text mode number is not valid. | |
| --*/ | |
| { | |
| EFI_STATUS Status; | |
| GRAPHICS_CONSOLE_DEV *Private; | |
| GRAPHICS_CONSOLE_MODE_DATA *ModeData; | |
| EFI_GRAPHICS_OUTPUT_BLT_PIXEL *NewLineBuffer; | |
| UINT32 HorizontalResolution; | |
| UINT32 VerticalResolution; | |
| EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; | |
| EFI_UGA_DRAW_PROTOCOL *UgaDraw; | |
| UINT32 ColorDepth; | |
| UINT32 RefreshRate; | |
| EFI_TPL OldTpl; | |
| OldTpl = gBS->RaiseTPL (TPL_NOTIFY); | |
| Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This); | |
| GraphicsOutput = Private->GraphicsOutput; | |
| UgaDraw = Private->UgaDraw; | |
| ModeData = &(Private->ModeData[ModeNumber]); | |
| if (ModeData->Columns <= 0 && ModeData->Rows <= 0) { | |
| Status = EFI_UNSUPPORTED; | |
| goto Done; | |
| } | |
| // | |
| // Make sure the requested mode number is supported | |
| // | |
| if (ModeNumber >= (UINTN) This->Mode->MaxMode) { | |
| Status = EFI_UNSUPPORTED; | |
| goto Done; | |
| } | |
| if (ModeData->Columns <= 0 && ModeData->Rows <= 0) { | |
| Status = EFI_UNSUPPORTED; | |
| goto Done; | |
| } | |
| // | |
| // Attempt to allocate a line buffer for the requested mode number | |
| // | |
| NewLineBuffer = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * ModeData->Columns * GLYPH_WIDTH * GLYPH_HEIGHT); | |
| if (NewLineBuffer == NULL) { | |
| // | |
| // The new line buffer could not be allocated, so return an error. | |
| // No changes to the state of the current console have been made, so the current console is still valid | |
| // | |
| Status = EFI_OUT_OF_RESOURCES; | |
| goto Done; | |
| } | |
| // | |
| // If the mode has been set at least one other time, then LineBuffer will not be NULL | |
| // | |
| if (Private->LineBuffer != NULL) { | |
| // | |
| // Clear the current text window on the current graphics console | |
| // | |
| This->ClearScreen (This); | |
| // | |
| // If the new mode is the same as the old mode, then just return EFI_SUCCESS | |
| // | |
| if ((INT32) ModeNumber == This->Mode->Mode) { | |
| FreePool (NewLineBuffer); | |
| Status = EFI_SUCCESS; | |
| goto Done; | |
| } | |
| // | |
| // Otherwise, the size of the text console and/or the UGA mode will be changed, | |
| // so turn off the cursor, and free the LineBuffer for the current mode | |
| // | |
| This->EnableCursor (This, FALSE); | |
| FreePool (Private->LineBuffer); | |
| } | |
| // | |
| // Assign the current line buffer to the newly allocated line buffer | |
| // | |
| Private->LineBuffer = NewLineBuffer; | |
| if (GraphicsOutput != NULL) { | |
| if (ModeData->GopModeNumber != GraphicsOutput->Mode->Mode) { | |
| // | |
| // Either no graphics mode is currently set, or it is set to the wrong resolution, so set the new grapghics mode | |
| // | |
| Status = GraphicsOutput->SetMode (GraphicsOutput, ModeData->GopModeNumber); | |
| if (EFI_ERROR (Status)) { | |
| // | |
| // The mode set operation failed | |
| // | |
| goto Done; | |
| } | |
| } else { | |
| // | |
| // The current graphics mode is correct, so simply clear the entire display | |
| // | |
| Status = GraphicsOutput->Blt ( | |
| GraphicsOutput, | |
| &mEfiColors[0], | |
| EfiBltVideoFill, | |
| 0, | |
| 0, | |
| 0, | |
| 0, | |
| ModeData->GopWidth, | |
| ModeData->GopHeight, | |
| 0 | |
| ); | |
| } | |
| } else { | |
| // | |
| // Get the current UGA Draw mode information | |
| // | |
| Status = UgaDraw->GetMode ( | |
| UgaDraw, | |
| &HorizontalResolution, | |
| &VerticalResolution, | |
| &ColorDepth, | |
| &RefreshRate | |
| ); | |
| if (EFI_ERROR (Status) || HorizontalResolution != ModeData->GopWidth || VerticalResolution != ModeData->GopHeight) { | |
| // | |
| // Either no graphics mode is currently set, or it is set to the wrong resolution, so set the new grapghics mode | |
| // | |
| Status = UgaDraw->SetMode ( | |
| UgaDraw, | |
| ModeData->GopWidth, | |
| ModeData->GopHeight, | |
| 32, | |
| 60 | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| // | |
| // The mode set operation failed | |
| // | |
| goto Done; | |
| } | |
| } else { | |
| // | |
| // The current graphics mode is correct, so simply clear the entire display | |
| // | |
| Status = UgaDraw->Blt ( | |
| UgaDraw, | |
| (EFI_UGA_PIXEL *) (UINTN) &mEfiColors[0], | |
| EfiUgaVideoFill, | |
| 0, | |
| 0, | |
| 0, | |
| 0, | |
| ModeData->GopWidth, | |
| ModeData->GopHeight, | |
| 0 | |
| ); | |
| } | |
| } | |
| // | |
| // The new mode is valid, so commit the mode change | |
| // | |
| This->Mode->Mode = (INT32) ModeNumber; | |
| // | |
| // Move the text cursor to the upper left hand corner of the displat and enable it | |
| // | |
| This->SetCursorPosition (This, 0, 0); | |
| This->EnableCursor (This, TRUE); | |
| Status = EFI_SUCCESS; | |
| Done: | |
| gBS->RestoreTPL (OldTpl); | |
| return Status; | |
| } | |
| EFI_STATUS | |
| EFIAPI | |
| GraphicsConsoleConOutSetAttribute ( | |
| IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, | |
| IN UINTN Attribute | |
| ) | |
| /*++ | |
| Routine Description: | |
| Implements SIMPLE_TEXT_OUTPUT.SetAttribute(). | |
| Arguments: | |
| This - Indicates the calling context. | |
| Attrubute - The attribute to set. Only bit0..6 are valid, all other bits | |
| are undefined and must be zero. | |
| Returns: | |
| EFI_SUCCESS | |
| The requested attribute is set. | |
| EFI_DEVICE_ERROR | |
| The requested attribute cannot be set due to Graphics Console port error. | |
| EFI_UNSUPPORTED | |
| The attribute requested is not defined by EFI spec. | |
| --*/ | |
| { | |
| EFI_TPL OldTpl; | |
| if ((Attribute | 0xFF) != 0xFF) { | |
| return EFI_UNSUPPORTED; | |
| } | |
| if ((INT32) Attribute == This->Mode->Attribute) { | |
| return EFI_SUCCESS; | |
| } | |
| OldTpl = gBS->RaiseTPL (TPL_NOTIFY); | |
| EraseCursor (This); | |
| This->Mode->Attribute = (INT32) Attribute; | |
| EraseCursor (This); | |
| gBS->RestoreTPL (OldTpl); | |
| return EFI_SUCCESS; | |
| } | |
| EFI_STATUS | |
| EFIAPI | |
| GraphicsConsoleConOutClearScreen ( | |
| IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This | |
| ) | |
| /*++ | |
| Routine Description: | |
| Implements SIMPLE_TEXT_OUTPUT.ClearScreen(). | |
| It clears the Graphics Console's display to the | |
| currently selected background color. | |
| Arguments: | |
| This - Indicates the calling context. | |
| Returns: | |
| EFI_SUCCESS | |
| The operation completed successfully. | |
| EFI_DEVICE_ERROR | |
| The Graphics Console cannot be cleared due to Graphics Console device error. | |
| EFI_UNSUPPORTED | |
| The Graphics Console is not in a valid text mode. | |
| --*/ | |
| { | |
| EFI_STATUS Status; | |
| GRAPHICS_CONSOLE_DEV *Private; | |
| GRAPHICS_CONSOLE_MODE_DATA *ModeData; | |
| EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; | |
| EFI_UGA_DRAW_PROTOCOL *UgaDraw; | |
| EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground; | |
| EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background; | |
| EFI_TPL OldTpl; | |
| OldTpl = gBS->RaiseTPL (TPL_NOTIFY); | |
| Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This); | |
| GraphicsOutput = Private->GraphicsOutput; | |
| UgaDraw = Private->UgaDraw; | |
| ModeData = &(Private->ModeData[This->Mode->Mode]); | |
| GetTextColors (This, &Foreground, &Background); | |
| if (GraphicsOutput != NULL) { | |
| Status = GraphicsOutput->Blt ( | |
| GraphicsOutput, | |
| &Background, | |
| EfiBltVideoFill, | |
| 0, | |
| 0, | |
| 0, | |
| 0, | |
| ModeData->GopWidth, | |
| ModeData->GopHeight, | |
| 0 | |
| ); | |
| } else { | |
| Status = UgaDraw->Blt ( | |
| UgaDraw, | |
| (EFI_UGA_PIXEL *) (UINTN) &Background, | |
| EfiUgaVideoFill, | |
| 0, | |
| 0, | |
| 0, | |
| 0, | |
| ModeData->GopWidth, | |
| ModeData->GopHeight, | |
| 0 | |
| ); | |
| } | |
| This->Mode->CursorColumn = 0; | |
| This->Mode->CursorRow = 0; | |
| EraseCursor (This); | |
| gBS->RestoreTPL (OldTpl); | |
| return Status; | |
| } | |
| EFI_STATUS | |
| EFIAPI | |
| GraphicsConsoleConOutSetCursorPosition ( | |
| IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, | |
| IN UINTN Column, | |
| IN UINTN Row | |
| ) | |
| /*++ | |
| Routine Description: | |
| Implements SIMPLE_TEXT_OUTPUT.SetCursorPosition(). | |
| Arguments: | |
| This - Indicates the calling context. | |
| Column - The row to set cursor to. | |
| Row - The column to set cursor to. | |
| Returns: | |
| EFI_SUCCESS | |
| The operation completed successfully. | |
| EFI_DEVICE_ERROR | |
| The request fails due to Graphics Console device error. | |
| EFI_UNSUPPORTED | |
| The Graphics Console is not in a valid text mode, or the cursor position | |
| is invalid for current mode. | |
| --*/ | |
| { | |
| GRAPHICS_CONSOLE_DEV *Private; | |
| GRAPHICS_CONSOLE_MODE_DATA *ModeData; | |
| EFI_STATUS Status; | |
| EFI_TPL OldTpl; | |
| Status = EFI_SUCCESS; | |
| OldTpl = gBS->RaiseTPL (TPL_NOTIFY); | |
| Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This); | |
| ModeData = &(Private->ModeData[This->Mode->Mode]); | |
| if ((Column >= ModeData->Columns) || (Row >= ModeData->Rows)) { | |
| Status = EFI_UNSUPPORTED; | |
| goto Done; | |
| } | |
| if (((INT32) Column == This->Mode->CursorColumn) && ((INT32) Row == This->Mode->CursorRow)) { | |
| Status = EFI_SUCCESS; | |
| goto Done; | |
| } | |
| EraseCursor (This); | |
| This->Mode->CursorColumn = (INT32) Column; | |
| This->Mode->CursorRow = (INT32) Row; | |
| EraseCursor (This); | |
| Done: | |
| gBS->RestoreTPL (OldTpl); | |
| return Status; | |
| } | |
| EFI_STATUS | |
| EFIAPI | |
| GraphicsConsoleConOutEnableCursor ( | |
| IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, | |
| IN BOOLEAN Visible | |
| ) | |
| /*++ | |
| Routine Description: | |
| Implements SIMPLE_TEXT_OUTPUT.EnableCursor(). | |
| In this driver, the cursor cannot be hidden. | |
| Arguments: | |
| This - Indicates the calling context. | |
| Visible - If TRUE, the cursor is set to be visible, | |
| If FALSE, the cursor is set to be invisible. | |
| Returns: | |
| EFI_SUCCESS | |
| The request is valid. | |
| EFI_UNSUPPORTED | |
| The Graphics Console does not support a hidden cursor. | |
| --*/ | |
| { | |
| EFI_TPL OldTpl; | |
| OldTpl = gBS->RaiseTPL (TPL_NOTIFY); | |
| EraseCursor (This); | |
| This->Mode->CursorVisible = Visible; | |
| EraseCursor (This); | |
| gBS->RestoreTPL (OldTpl); | |
| return EFI_SUCCESS; | |
| } | |
| STATIC | |
| EFI_STATUS | |
| GetTextColors ( | |
| IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, | |
| OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Foreground, | |
| OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Background | |
| ) | |
| { | |
| INTN Attribute; | |
| Attribute = This->Mode->Attribute & 0x7F; | |
| *Foreground = mEfiColors[Attribute & 0x0f]; | |
| *Background = mEfiColors[Attribute >> 4]; | |
| return EFI_SUCCESS; | |
| } | |
| STATIC | |
| EFI_STATUS | |
| DrawUnicodeWeightAtCursorN ( | |
| IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, | |
| IN CHAR16 *UnicodeWeight, | |
| IN UINTN Count | |
| ) | |
| { | |
| GRAPHICS_CONSOLE_DEV *Private; | |
| EFI_STATUS Status; | |
| EFI_STATUS ReturnStatus; | |
| GLYPH_UNION *Glyph; | |
| GLYPH_UNION GlyphData; | |
| INTN GlyphX; | |
| INTN GlyphY; | |
| EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; | |
| EFI_UGA_DRAW_PROTOCOL *UgaDraw; | |
| EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground; | |
| EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background; | |
| UINTN Index; | |
| UINTN ArrayIndex; | |
| UINTN Counts; | |
| UINT16 GlyphWidth; | |
| UINT32 GlyphStatus; | |
| Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This); | |
| ReturnStatus = EFI_SUCCESS; | |
| GlyphStatus = 0; | |
| GlyphWidth = 0x08; | |
| GetTextColors (This, &Foreground, &Background); | |
| Index = 0; | |
| ArrayIndex = 0; | |
| while (Index < Count) { | |
| if (This->Mode->Attribute & EFI_WIDE_ATTRIBUTE) { | |
| GlyphStatus = WIDE_CHAR; | |
| } else { | |
| GlyphStatus = NARROW_CHAR; | |
| } | |
| Status = mHii->GetGlyph ( | |
| mHii, | |
| UnicodeWeight, | |
| (UINT16 *) &Index, | |
| (UINT8 **) &Glyph, | |
| &GlyphWidth, | |
| &GlyphStatus | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| ReturnStatus = Status; | |
| } | |
| Counts = 0; | |
| CopyMem (&GlyphData, Glyph, sizeof (GLYPH_UNION)); | |
| do { | |
| // | |
| // We are creating the second half of the wide character's BLT buffer | |
| // | |
| if (GlyphWidth == 0x10 && Counts == 1) { | |
| CopyMem (&GlyphData.NarrowGlyph.GlyphCol1, &Glyph->WideGlyph.GlyphCol2, sizeof (Glyph->WideGlyph.GlyphCol2)); | |
| } | |
| Counts++; | |
| if (GlyphWidth == 0x10) { | |
| mHii->GlyphToBlt ( | |
| mHii, | |
| (UINT8 *) &GlyphData, | |
| Foreground, | |
| Background, | |
| Count * 2, | |
| GLYPH_WIDTH, | |
| GLYPH_HEIGHT, | |
| &Private->LineBuffer[ArrayIndex * GLYPH_WIDTH] | |
| ); | |
| } else { | |
| mHii->GlyphToBlt ( | |
| mHii, | |
| (UINT8 *) &GlyphData, | |
| Foreground, | |
| Background, | |
| Count, | |
| GLYPH_WIDTH, | |
| GLYPH_HEIGHT, | |
| &Private->LineBuffer[ArrayIndex * GLYPH_WIDTH] | |
| ); | |
| } | |
| ArrayIndex++; | |
| } while (Counts < 2 && GlyphWidth == 0x10); | |
| } | |
| // | |
| // If we are printing Wide characters, treat the BLT as if it is twice as many characters | |
| // | |
| if (GlyphWidth == 0x10) { | |
| Count = Count * 2; | |
| } | |
| // | |
| // Blt a character to the screen | |
| // | |
| GlyphX = This->Mode->CursorColumn * GLYPH_WIDTH; | |
| GlyphY = This->Mode->CursorRow * GLYPH_HEIGHT; | |
| GraphicsOutput = Private->GraphicsOutput; | |
| UgaDraw = Private->UgaDraw; | |
| if (GraphicsOutput != NULL) { | |
| GraphicsOutput->Blt ( | |
| GraphicsOutput, | |
| Private->LineBuffer, | |
| EfiBltBufferToVideo, | |
| 0, | |
| 0, | |
| GlyphX + Private->ModeData[This->Mode->Mode].DeltaX, | |
| GlyphY + Private->ModeData[This->Mode->Mode].DeltaY, | |
| GLYPH_WIDTH * Count, | |
| GLYPH_HEIGHT, | |
| GLYPH_WIDTH * Count * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) | |
| ); | |
| } else { | |
| UgaDraw->Blt ( | |
| UgaDraw, | |
| (EFI_UGA_PIXEL *) (UINTN) Private->LineBuffer, | |
| EfiUgaBltBufferToVideo, | |
| 0, | |
| 0, | |
| GlyphX + Private->ModeData[This->Mode->Mode].DeltaX, | |
| GlyphY + Private->ModeData[This->Mode->Mode].DeltaY, | |
| GLYPH_WIDTH * Count, | |
| GLYPH_HEIGHT, | |
| GLYPH_WIDTH * Count * sizeof (EFI_UGA_PIXEL) | |
| ); | |
| } | |
| return ReturnStatus; | |
| } | |
| STATIC | |
| EFI_STATUS | |
| EraseCursor ( | |
| IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This | |
| ) | |
| { | |
| GRAPHICS_CONSOLE_DEV *Private; | |
| EFI_SIMPLE_TEXT_OUTPUT_MODE *CurrentMode; | |
| INTN GlyphX; | |
| INTN GlyphY; | |
| EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; | |
| EFI_UGA_DRAW_PROTOCOL *UgaDraw; | |
| EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Foreground; | |
| EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Background; | |
| EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION BltChar[GLYPH_HEIGHT][GLYPH_WIDTH]; | |
| UINTN X; | |
| UINTN Y; | |
| CurrentMode = This->Mode; | |
| if (!CurrentMode->CursorVisible) { | |
| return EFI_SUCCESS; | |
| } | |
| Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This); | |
| GraphicsOutput = Private->GraphicsOutput; | |
| UgaDraw = Private->UgaDraw; | |
| // | |
| // BUGBUG - we need to think about what to do with wide and narrow character deletions. | |
| // | |
| // | |
| // Blt a character to the screen | |
| // | |
| GlyphX = (CurrentMode->CursorColumn * GLYPH_WIDTH) + Private->ModeData[CurrentMode->Mode].DeltaX; | |
| GlyphY = (CurrentMode->CursorRow * GLYPH_HEIGHT) + Private->ModeData[CurrentMode->Mode].DeltaY; | |
| if (GraphicsOutput != NULL) { | |
| GraphicsOutput->Blt ( | |
| GraphicsOutput, | |
| (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltChar, | |
| EfiBltVideoToBltBuffer, | |
| GlyphX, | |
| GlyphY, | |
| 0, | |
| 0, | |
| GLYPH_WIDTH, | |
| GLYPH_HEIGHT, | |
| GLYPH_WIDTH * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) | |
| ); | |
| } else { | |
| UgaDraw->Blt ( | |
| UgaDraw, | |
| (EFI_UGA_PIXEL *) (UINTN) BltChar, | |
| EfiUgaVideoToBltBuffer, | |
| GlyphX, | |
| GlyphY, | |
| 0, | |
| 0, | |
| GLYPH_WIDTH, | |
| GLYPH_HEIGHT, | |
| GLYPH_WIDTH * sizeof (EFI_UGA_PIXEL) | |
| ); | |
| } | |
| GetTextColors (This, &Foreground.Pixel, &Background.Pixel); | |
| // | |
| // Convert Monochrome bitmap of the Glyph to BltBuffer structure | |
| // | |
| for (Y = 0; Y < GLYPH_HEIGHT; Y++) { | |
| for (X = 0; X < GLYPH_WIDTH; X++) { | |
| if ((mCursorGlyph.GlyphCol1[Y] & (1 << X)) != 0) { | |
| BltChar[Y][GLYPH_WIDTH - X - 1].Raw ^= Foreground.Raw; | |
| } | |
| } | |
| } | |
| if (GraphicsOutput != NULL) { | |
| GraphicsOutput->Blt ( | |
| GraphicsOutput, | |
| (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltChar, | |
| EfiBltBufferToVideo, | |
| 0, | |
| 0, | |
| GlyphX, | |
| GlyphY, | |
| GLYPH_WIDTH, | |
| GLYPH_HEIGHT, | |
| GLYPH_WIDTH * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) | |
| ); | |
| } else { | |
| UgaDraw->Blt ( | |
| UgaDraw, | |
| (EFI_UGA_PIXEL *) (UINTN) BltChar, | |
| EfiUgaBltBufferToVideo, | |
| 0, | |
| 0, | |
| GlyphX, | |
| GlyphY, | |
| GLYPH_WIDTH, | |
| GLYPH_HEIGHT, | |
| GLYPH_WIDTH * sizeof (EFI_UGA_PIXEL) | |
| ); | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| The user Entry Point for module GraphicsConsole. 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 | |
| InitializeGraphicsConsole ( | |
| IN EFI_HANDLE ImageHandle, | |
| IN EFI_SYSTEM_TABLE *SystemTable | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| // | |
| // Install driver model protocol(s). | |
| // | |
| Status = EfiLibInstallAllDriverProtocols ( | |
| ImageHandle, | |
| SystemTable, | |
| &gGraphicsConsoleDriverBinding, | |
| ImageHandle, | |
| &gGraphicsConsoleComponentName, | |
| NULL, | |
| NULL | |
| ); | |
| ASSERT_EFI_ERROR (Status); | |
| return Status; | |
| } | |