summaryrefslogtreecommitdiff
path: root/EdkModulePkg/Universal/Console/GraphicsConsole/Dxe/GraphicsConsole.c
diff options
context:
space:
mode:
authorbbahnsen <bbahnsen@6f19259b-4bc3-4df7-8a09-765794883524>2006-04-21 22:54:32 +0000
committerbbahnsen <bbahnsen@6f19259b-4bc3-4df7-8a09-765794883524>2006-04-21 22:54:32 +0000
commit878ddf1fc3540a715f63594ed22b6929e881afb4 (patch)
treec56c44dac138137b510e1fba7c3efe5e4d84bea2 /EdkModulePkg/Universal/Console/GraphicsConsole/Dxe/GraphicsConsole.c
downloadedk2-platforms-878ddf1fc3540a715f63594ed22b6929e881afb4.tar.xz
Initial import.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'EdkModulePkg/Universal/Console/GraphicsConsole/Dxe/GraphicsConsole.c')
-rw-r--r--EdkModulePkg/Universal/Console/GraphicsConsole/Dxe/GraphicsConsole.c1566
1 files changed, 1566 insertions, 0 deletions
diff --git a/EdkModulePkg/Universal/Console/GraphicsConsole/Dxe/GraphicsConsole.c b/EdkModulePkg/Universal/Console/GraphicsConsole/Dxe/GraphicsConsole.c
new file mode 100644
index 0000000000..a475723dfd
--- /dev/null
+++ b/EdkModulePkg/Universal/Console/GraphicsConsole/Dxe/GraphicsConsole.c
@@ -0,0 +1,1566 @@
+/*++
+
+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.
+
+Module Name:
+
+ GraphicsConsole.c
+
+Abstract:
+
+ This is the main routine for initializing the Graphics Console support routines.
+
+Revision History
+
+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?
+
+--*/
+
+#include "GraphicsConsole.h"
+
+//
+// Function Prototypes
+//
+EFI_STATUS
+EFIAPI
+GraphicsConsoleControllerDriverSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+EFI_STATUS
+EFIAPI
+GraphicsConsoleControllerDriverStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+EFI_STATUS
+EFIAPI
+GraphicsConsoleControllerDriverStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+EFI_STATUS
+GetTextColors (
+ IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This,
+ OUT EFI_UGA_PIXEL *Foreground,
+ OUT EFI_UGA_PIXEL *Background
+ );
+
+EFI_STATUS
+DrawUnicodeWeightAtCursor (
+ IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This,
+ IN CHAR16 UnicodeWeight
+ );
+
+EFI_STATUS
+DrawUnicodeWeightAtCursorN (
+ IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This,
+ IN CHAR16 *UnicodeWeight,
+ IN UINTN Count
+ );
+
+EFI_STATUS
+EraseCursor (
+ IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This
+ );
+
+//
+// Globals
+//
+GRAPHICS_CONSOLE_DEV mGraphicsConsoleDevTemplate = {
+ GRAPHICS_CONSOLE_DEV_SIGNATURE,
+ (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
+ { 0, 0, 0, 0, 0, 0 }, // Mode 1
+ { 0, 0, 0, 0, 0, 0 } // Mode 2
+ },
+ (EFI_UGA_PIXEL *) NULL,
+ (EFI_HII_HANDLE) 0
+};
+
+EFI_HII_PROTOCOL *mHii;
+
+static CHAR16 mCrLfString[3] = { CHAR_CARRIAGE_RETURN, CHAR_LINEFEED, CHAR_NULL };
+
+static EFI_UGA_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 }
+};
+
+static CHAR16 SpaceStr[] = { (CHAR16)NARROW_CHAR, ' ', 0 };
+
+
+EFI_DRIVER_BINDING_PROTOCOL gGraphicsConsoleDriverBinding = {
+ GraphicsConsoleControllerDriverSupported,
+ GraphicsConsoleControllerDriverStart,
+ GraphicsConsoleControllerDriverStop,
+ 0x10,
+ 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_UGA_DRAW_PROTOCOL *UgaDraw;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ //
+ // Open the IO Abstraction(s) needed to perform the supported test
+ //
+ 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:
+ 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;
+ //
+ // 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,
+ &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));
+ gBS->FreePool (Package);
+
+ //
+ // Free the font database
+ //
+ gBS->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;
+ 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].UgaWidth = HorizontalResolution;
+ Private->ModeData[MaxMode].UgaHeight = VerticalResolution;
+ 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].UgaWidth = HorizontalResolution;
+ Private->ModeData[MaxMode].UgaHeight = VerticalResolution;
+ 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].UgaWidth = 800;
+ Private->ModeData[MaxMode].UgaHeight = 600;
+ 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].UgaWidth = 800;
+ Private->ModeData[MaxMode].UgaHeight = 600;
+ 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 (
+ GraphicsConsoleConOutOutputString (&Private->SimpleTextOutput, (CHAR16 *)L"Graphics Console Started\n\r");
+ );
+
+ //
+ // Install protocol interfaces for the Graphics Console device.
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Controller,
+ &gEfiSimpleTextOutProtocolGuid,
+ &Private->SimpleTextOutput,
+ NULL
+ );
+
+Error:
+ if (EFI_ERROR (Status)) {
+ //
+ // Close the UGA IO Protocol
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUgaDrawProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ //
+ // Free private data
+ //
+ if (Private != NULL) {
+ gBS->FreePool (Private->LineBuffer);
+ gBS->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_OUT_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 UGA IO Protocol
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUgaDrawProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ //
+ // Remove the font pack
+ //
+ mHii->RemovePack (mHii, Private->HiiHandle);
+
+ //
+ // Free our instance data
+ //
+ if (Private != NULL) {
+ gBS->FreePool (Private->LineBuffer);
+ gBS->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_OUT_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_OUT_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_UGA_DRAW_PROTOCOL *UgaDraw;
+ INTN Mode;
+ UINTN MaxColumn;
+ UINTN MaxRow;
+ UINTN Width;
+ UINTN Height;
+ UINTN Delta;
+ EFI_STATUS Status;
+ BOOLEAN Warning;
+ EFI_UGA_PIXEL Foreground;
+ EFI_UGA_PIXEL Background;
+ UINTN DeltaX;
+ UINTN DeltaY;
+ UINTN Count;
+ UINTN Index;
+ INT32 OriginAttribute;
+
+ //
+ // Current mode
+ //
+ Mode = This->Mode->Mode;
+ Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
+ 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_UGA_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)) {
+ //
+ // 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,
+ &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) {
+ return EFI_WARN_UNKNOWN_GLYPH;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+GraphicsConsoleConOutTestString (
+ IN EFI_SIMPLE_TEXT_OUT_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;
+ GRAPHICS_CONSOLE_DEV *Private;
+ GLYPH_UNION *Glyph;
+
+ Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
+ 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_OUT_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;
+
+ if (ModeNumber >= (UINTN) This->Mode->MaxMode) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
+
+ *Columns = Private->ModeData[ModeNumber].Columns;
+ *Rows = Private->ModeData[ModeNumber].Rows;
+
+ if (*Columns <= 0 && *Rows <= 0) {
+ return EFI_UNSUPPORTED;
+
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+GraphicsConsoleConOutSetMode (
+ IN EFI_SIMPLE_TEXT_OUT_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;
+ EFI_UGA_DRAW_PROTOCOL *UgaDraw;
+ GRAPHICS_CONSOLE_MODE_DATA *ModeData;
+ EFI_UGA_PIXEL *NewLineBuffer;
+ UINT32 HorizontalResolution;
+ UINT32 VerticalResolution;
+ UINT32 ColorDepth;
+ UINT32 RefreshRate;
+
+ Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
+ UgaDraw = Private->UgaDraw;
+ ModeData = &(Private->ModeData[ModeNumber]);
+
+ //
+ // Make sure the requested mode number is supported
+ //
+ if (ModeNumber >= (UINTN) This->Mode->MaxMode) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (ModeData->Columns <= 0 && ModeData->Rows <= 0) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Attempt to allocate a line buffer for the requested mode number
+ //
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof (EFI_UGA_PIXEL) * ModeData->Columns * GLYPH_WIDTH * GLYPH_HEIGHT,
+ (VOID **) &NewLineBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // 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
+ //
+ return Status;
+ }
+ //
+ // 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) {
+ gBS->FreePool (NewLineBuffer);
+ return EFI_SUCCESS;
+ }
+ //
+ // 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);
+
+ gBS->FreePool (Private->LineBuffer);
+ }
+ //
+ // Assign the current line buffer to the newly allocated line buffer
+ //
+ Private->LineBuffer = NewLineBuffer;
+
+ //
+ // Get the current UGA Draw mode information
+ //
+ Status = UgaDraw->GetMode (
+ UgaDraw,
+ &HorizontalResolution,
+ &VerticalResolution,
+ &ColorDepth,
+ &RefreshRate
+ );
+ if (EFI_ERROR (Status) || HorizontalResolution != ModeData->UgaWidth || VerticalResolution != ModeData->UgaHeight) {
+ //
+ // 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->UgaWidth,
+ ModeData->UgaHeight,
+ 32,
+ 60
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // The mode set operation failed
+ //
+ return Status;
+ }
+ } else {
+ //
+ // The current graphics mode is correct, so simply clear the entire display
+ //
+ Status = UgaDraw->Blt (
+ UgaDraw,
+ &mEfiColors[0],
+ EfiUgaVideoFill,
+ 0,
+ 0,
+ 0,
+ 0,
+ ModeData->UgaWidth,
+ ModeData->UgaHeight,
+ 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);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+GraphicsConsoleConOutSetAttribute (
+ IN EFI_SIMPLE_TEXT_OUT_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.
+
+--*/
+{
+ if ((Attribute | 0xFF) != 0xFF) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if ((INT32) Attribute == This->Mode->Attribute) {
+ return EFI_SUCCESS;
+ }
+
+ EraseCursor (This);
+
+ This->Mode->Attribute = (INT32) Attribute;
+
+ EraseCursor (This);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+GraphicsConsoleConOutClearScreen (
+ IN EFI_SIMPLE_TEXT_OUT_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_UGA_DRAW_PROTOCOL *UgaDraw;
+ EFI_UGA_PIXEL Foreground;
+ EFI_UGA_PIXEL Background;
+
+ Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
+ UgaDraw = Private->UgaDraw;
+ ModeData = &(Private->ModeData[This->Mode->Mode]);
+
+ GetTextColors (This, &Foreground, &Background);
+
+ Status = UgaDraw->Blt (
+ UgaDraw,
+ &Background,
+ EfiUgaVideoFill,
+ 0,
+ 0,
+ 0,
+ 0,
+ ModeData->UgaWidth,
+ ModeData->UgaHeight,
+ 0
+ );
+
+ This->Mode->CursorColumn = 0;
+ This->Mode->CursorRow = 0;
+
+ EraseCursor (This);
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+GraphicsConsoleConOutSetCursorPosition (
+ IN EFI_SIMPLE_TEXT_OUT_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;
+
+ Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
+ ModeData = &(Private->ModeData[This->Mode->Mode]);
+
+ if ((Column >= ModeData->Columns) || (Row >= ModeData->Rows)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (((INT32) Column == This->Mode->CursorColumn) && ((INT32) Row == This->Mode->CursorRow)) {
+ return EFI_SUCCESS;
+ }
+
+ EraseCursor (This);
+
+ This->Mode->CursorColumn = (INT32) Column;
+ This->Mode->CursorRow = (INT32) Row;
+
+ EraseCursor (This);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+GraphicsConsoleConOutEnableCursor (
+ IN EFI_SIMPLE_TEXT_OUT_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.
+
+--*/
+{
+ EraseCursor (This);
+
+ This->Mode->CursorVisible = Visible;
+
+ EraseCursor (This);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetTextColors (
+ IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This,
+ OUT EFI_UGA_PIXEL *Foreground,
+ OUT EFI_UGA_PIXEL *Background
+ )
+{
+ INTN Attribute;
+
+ Attribute = This->Mode->Attribute & 0x7F;
+
+ *Foreground = mEfiColors[Attribute & 0x0f];
+ *Background = mEfiColors[Attribute >> 4];
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+DrawUnicodeWeightAtCursorN (
+ IN EFI_SIMPLE_TEXT_OUT_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_UGA_DRAW_PROTOCOL *UgaDraw;
+ EFI_UGA_PIXEL Foreground;
+ EFI_UGA_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;
+ UgaDraw = Private->UgaDraw;
+ UgaDraw->Blt (
+ UgaDraw,
+ 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;
+}
+
+EFI_STATUS
+EraseCursor (
+ IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This
+ )
+{
+ GRAPHICS_CONSOLE_DEV *Private;
+ EFI_SIMPLE_TEXT_OUTPUT_MODE *CurrentMode;
+ INTN GlyphX;
+ INTN GlyphY;
+ EFI_UGA_DRAW_PROTOCOL *UgaDraw;
+ EFI_UGA_PIXEL_UNION Foreground;
+ EFI_UGA_PIXEL_UNION Background;
+ EFI_UGA_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);
+ 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;
+ UgaDraw->Blt (
+ UgaDraw,
+ (EFI_UGA_PIXEL *) 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;
+ }
+ }
+ }
+
+ UgaDraw->Blt (
+ UgaDraw,
+ (EFI_UGA_PIXEL *) BltChar,
+ EfiUgaBltBufferToVideo,
+ 0,
+ 0,
+ GlyphX,
+ GlyphY,
+ GLYPH_WIDTH,
+ GLYPH_HEIGHT,
+ GLYPH_WIDTH * sizeof (EFI_UGA_PIXEL)
+ );
+
+ return EFI_SUCCESS;
+}