audk/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.c

1932 lines
56 KiB
C

/**@file
This is the main routine for initializing the Graphics Console support routines.
Remaining Tasks
Add all standard Glyphs from UEFI 2.0 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
);
EFI_STATUS
CheckModeSupported (
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,
IN UINT32 HorizontalResolution,
IN UINT32 VerticalResolution,
OUT UINT32 *CurrentModeNumber
);
//
// 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
{ 100,31, 0, 0, 0, 0 }, // Mode 2
{ 0, 0, 0, 0, 0, 0 } // Mode 3
},
(EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) NULL,
(EFI_HII_HANDLE ) 0
};
EFI_HII_DATABASE_PROTOCOL *mHiiDatabase;
EFI_HII_FONT_PROTOCOL *mHiiFont;
BOOLEAN mFirstAccessFlag = TRUE;
STATIC EFI_GUID mFontPackageListGuid = {0xf5f219d3, 0x7006, 0x4648, 0xac, 0x8d, 0xd6, 0x1d, 0xfb, 0x7b, 0xc6, 0xad};
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;
UINTN NarrowFontSize;
UINT32 HorizontalResolution;
UINT32 VerticalResolution;
UINT32 ColorDepth;
UINT32 RefreshRate;
UINTN MaxMode;
UINTN Columns;
UINTN Rows;
UINT32 ModeNumber;
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;
}
}
NarrowFontSize = ReturnNarrowFontSize ();
#if 1
if (mFirstAccessFlag) {
HiiLibAddFontPackageToHiiDatabase (NarrowFontSize, (UINT8 *) UsStdNarrowGlyphData, &mFontPackageListGuid, &(Private->HiiHandle));
mFirstAccessFlag = FALSE;
}
#else
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);
#endif
//
// 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 the user-defined mode; if there are multiple video devices,
// graphic console driver will set all the video devices to the same mode.
//
Status = CheckModeSupported (
Private->GraphicsOutput,
CURRENT_HORIZONTAL_RESOLUTION,
CURRENT_VERTICAL_RESOLUTION,
&ModeNumber
);
if (!EFI_ERROR(Status)) {
//
// Update default mode to current mode
//
HorizontalResolution = CURRENT_HORIZONTAL_RESOLUTION;
VerticalResolution = CURRENT_VERTICAL_RESOLUTION;
} else {
//
// if not supporting current mode, try 800x600 which is required by UEFI/EFI spec
//
Status = CheckModeSupported (
Private->GraphicsOutput,
800,
600,
&ModeNumber
);
}
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 {
//
// At first try to set user-defined resolution
//
ColorDepth = 32;
RefreshRate = 60;
Status = Private->UgaDraw->SetMode (
Private->UgaDraw,
CURRENT_HORIZONTAL_RESOLUTION,
CURRENT_VERTICAL_RESOLUTION,
ColorDepth,
RefreshRate
);
if (!EFI_ERROR (Status)) {
HorizontalResolution = CURRENT_HORIZONTAL_RESOLUTION;
VerticalResolution = CURRENT_VERTICAL_RESOLUTION;
} else {
//
// Try to set 800*600 which is required by UEFI/EFI spec
//
Status = Private->UgaDraw->SetMode (
Private->UgaDraw,
HorizontalResolution,
VerticalResolution,
ColorDepth,
RefreshRate
);
if (EFI_ERROR (Status)) {
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 it is not to support Mode #1 - 80x50, then skip it
//
if (MaxMode < 2) {
Private->ModeData[MaxMode].Columns = 0;
Private->ModeData[MaxMode].Rows = 0;
Private->ModeData[MaxMode].GopWidth = HorizontalResolution;
Private->ModeData[MaxMode].GopHeight = VerticalResolution;
Private->ModeData[MaxMode].GopModeNumber = ModeNumber;
Private->ModeData[MaxMode].DeltaX = 0;
Private->ModeData[MaxMode].DeltaY = 0;
MaxMode++;
}
//
// Add Mode #2 that must be 100x31 (graphic mode >= 800x600)
//
if (Columns >= 100 && Rows >= 31) {
Private->ModeData[MaxMode].GopWidth = HorizontalResolution;
Private->ModeData[MaxMode].GopHeight = VerticalResolution;
Private->ModeData[MaxMode].GopModeNumber = ModeNumber;
Private->ModeData[MaxMode].DeltaX = (HorizontalResolution - (100 * GLYPH_WIDTH)) >> 1;
Private->ModeData[MaxMode].DeltaY = (VerticalResolution - (31 * GLYPH_HEIGHT)) >> 1;
MaxMode++;
}
//
// Add Mode #3 that uses the entire display for user-defined mode
//
if (HorizontalResolution > 800 && VerticalResolution > 600) {
Private->ModeData[MaxMode].Columns = HorizontalResolution/GLYPH_WIDTH;
Private->ModeData[MaxMode].Rows = VerticalResolution/GLYPH_HEIGHT;
Private->ModeData[MaxMode].GopWidth = HorizontalResolution;
Private->ModeData[MaxMode].GopHeight = VerticalResolution;
Private->ModeData[MaxMode].GopModeNumber = ModeNumber;
Private->ModeData[MaxMode].DeltaX = (HorizontalResolution % GLYPH_WIDTH) >> 1;
Private->ModeData[MaxMode].DeltaY = (VerticalResolution % 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
//
if (Private->HiiHandle != NULL) {
HiiLibRemovePackages (Private->HiiHandle);
mFirstAccessFlag = TRUE;
}
//
// Free our instance data
//
if (Private != NULL) {
FreePool (Private->LineBuffer);
FreePool (Private);
}
}
return Status;
}
EFI_STATUS
CheckModeSupported (
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,
IN UINT32 HorizontalResolution,
IN UINT32 VerticalResolution,
OUT UINT32 *CurrentModeNumber
)
{
UINT32 ModeNumber;
EFI_STATUS Status;
UINTN SizeOfInfo;
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
Status = EFI_SUCCESS;
for (ModeNumber = 0; ModeNumber < GraphicsOutput->Mode->MaxMode; ModeNumber++) {
Status = GraphicsOutput->QueryMode (
GraphicsOutput,
ModeNumber,
&SizeOfInfo,
&Info
);
if (!EFI_ERROR (Status)) {
if ((Info->HorizontalResolution == HorizontalResolution) &&
(Info->VerticalResolution == VerticalResolution)) {
Status = GraphicsOutput->SetMode (GraphicsOutput, ModeNumber);
if (!EFI_ERROR (Status)) {
gBS->FreePool (Info);
break;
}
}
gBS->FreePool (Info);
}
}
if (ModeNumber == GraphicsOutput->Mode->MaxMode) {
Status = EFI_UNSUPPORTED;
}
*CurrentModeNumber = ModeNumber;
return Status;
}
EFI_STATUS
EfiLocateHiiProtocol (
VOID
)
/*++
Routine Description:
Locate HII protocols for future usage.
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,
&gEfiHiiDatabaseProtocolGuid,
NULL,
&Size,
(VOID **) &Handle
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = gBS->HandleProtocol (
Handle,
&gEfiHiiDatabaseProtocolGuid,
(VOID **) &mHiiDatabase
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = gBS->HandleProtocol (
Handle,
&gEfiHiiFontProtocolGuid,
(VOID **) &mHiiFont
);
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 Count;
EFI_IMAGE_OUTPUT *Blt = NULL;
Count = 0;
while (WString[Count] != 0) {
Status = mHiiFont->GetGlyph (
mHiiFont,
WString[Count],
NULL,
&Blt,
NULL
);
SafeFreePool (Blt);
Blt = NULL;
Count++;
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 GOP/UGA mode will be changed,
// so erase the cursor, and free the LineBuffer for the current mode
//
EraseCursor (This);
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);
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;
}
EFI_STATUS
DrawUnicodeWeightAtCursorN (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
IN CHAR16 *UnicodeWeight,
IN UINTN Count
)
{
EFI_STATUS Status;
GRAPHICS_CONSOLE_DEV *Private;
EFI_IMAGE_OUTPUT *Blt;
EFI_STRING String;
EFI_FONT_DISPLAY_INFO *FontInfo;
EFI_UGA_DRAW_PROTOCOL *UgaDraw;
EFI_HII_ROW_INFO *RowInfoArray;
UINTN RowInfoArraySize;
Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
Blt = (EFI_IMAGE_OUTPUT *) AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));
if (Blt == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Blt->Width = (UINT16) (Private->ModeData[This->Mode->Mode].GopWidth);
Blt->Height = (UINT16) (Private->ModeData[This->Mode->Mode].GopHeight);
String = AllocateCopyPool ((Count + 1) * sizeof (CHAR16), UnicodeWeight);
if (String == NULL) {
SafeFreePool (Blt);
return EFI_OUT_OF_RESOURCES;
}
*(String + Count) = 0;
FontInfo = (EFI_FONT_DISPLAY_INFO *) AllocateZeroPool (sizeof (EFI_FONT_DISPLAY_INFO));
if (FontInfo == NULL) {
SafeFreePool (Blt);
SafeFreePool (String);
return EFI_OUT_OF_RESOURCES;
}
GetTextColors (This, &FontInfo->ForegroundColor, &FontInfo->BackgroundColor);
if (Private->GraphicsOutput != NULL) {
Blt->Image.Screen = Private->GraphicsOutput;
Status = mHiiFont->StringToImage (
mHiiFont,
EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_DIRECT_TO_SCREEN,
String,
FontInfo,
&Blt,
This->Mode->CursorColumn * GLYPH_WIDTH + Private->ModeData[This->Mode->Mode].DeltaX,
This->Mode->CursorRow * GLYPH_HEIGHT + Private->ModeData[This->Mode->Mode].DeltaY,
NULL,
NULL,
NULL
);
} else {
ASSERT (Private->UgaDraw!= NULL);
UgaDraw = Private->UgaDraw;
Blt->Image.Bitmap = AllocateZeroPool (Blt->Width * Blt->Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
if (Blt->Image.Bitmap == NULL) {
SafeFreePool (Blt);
SafeFreePool (String);
return EFI_OUT_OF_RESOURCES;
}
RowInfoArray = NULL;
//
// StringToImage only support blt'ing image to device using GOP protocol. If GOP is not supported in this platform,
// we ask StringToImage to print the string to blt buffer, then blt to device using UgaDraw.
//
Status = mHiiFont->StringToImage (
mHiiFont,
EFI_HII_IGNORE_IF_NO_GLYPH,
String,
FontInfo,
&Blt,
This->Mode->CursorColumn * GLYPH_WIDTH + Private->ModeData[This->Mode->Mode].DeltaX,
This->Mode->CursorRow * GLYPH_HEIGHT + Private->ModeData[This->Mode->Mode].DeltaY,
&RowInfoArray,
&RowInfoArraySize,
NULL
);
if (!EFI_ERROR (Status)) {
//
// Line breaks are handled by caller of DrawUnicodeWeightAtCursorN, so the updated parameter RowInfoArraySize by StringToImage will
// always be 1. ASSERT here to make sure.
//
ASSERT (RowInfoArraySize == 1);
Status = UgaDraw->Blt (
UgaDraw,
(EFI_UGA_PIXEL *) Blt->Image.Bitmap,
EfiUgaBltBufferToVideo,
This->Mode->CursorColumn * GLYPH_WIDTH + Private->ModeData[This->Mode->Mode].DeltaX,
(This->Mode->CursorRow) * GLYPH_HEIGHT + Private->ModeData[This->Mode->Mode].DeltaY,
This->Mode->CursorColumn * GLYPH_WIDTH + Private->ModeData[This->Mode->Mode].DeltaX,
(This->Mode->CursorRow) * GLYPH_HEIGHT + Private->ModeData[This->Mode->Mode].DeltaY,
RowInfoArray[0].LineWidth,
RowInfoArray[0].LineHeight,
Blt->Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
);
}
SafeFreePool (RowInfoArray);
SafeFreePool (Blt->Image.Bitmap);
}
SafeFreePool (Blt);
SafeFreePool (String);
SafeFreePool (FontInfo);
return Status;
}
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 = EfiLibInstallDriverBindingComponentName2 (
ImageHandle,
SystemTable,
&gGraphicsConsoleDriverBinding,
ImageHandle,
&gGraphicsConsoleComponentName,
&gGraphicsConsoleComponentName2
);
ASSERT_EFI_ERROR (Status);
return Status;
}