/**@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.
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 }; #if (EFI_SPECIFICATION_VERSION >= 0x0002000A) 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}; #else EFI_HII_PROTOCOL *mHii; #endif 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 1 Status = HiiLibRemovePackagesFromHiiDatabase (Private->HiiHandle); if (!EFI_ERROR (Status)) { mFirstAccessFlag = TRUE; } #else mHii->RemovePack (mHii, Private->HiiHandle); #endif // // 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; #if (EFI_SPECIFICATION_VERSION >= 0x0002000A) // // 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; #else // // 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, &mHii ); return Status; #endif } // // 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; #if (EFI_SPECIFICATION_VERSION >= 0x0002000A) EFI_IMAGE_OUTPUT *Blt = NULL; #else UINT16 GlyphWidth; UINT32 GlyphStatus = 0; GLYPH_UNION *Glyph; #endif Count = 0; while (WString[Count] != 0) { #if (EFI_SPECIFICATION_VERSION >= 0x0002000A) Status = mHiiFont->GetGlyph ( mHiiFont, WString[Count], NULL, &Blt, NULL ); SafeFreePool (Blt); Blt = NULL; Count++; #else Status = mHii->GetGlyph ( mHii, WString, &Count, (UINT8 **) &Glyph, &GlyphWidth, &GlyphStatus ); #endif 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; } #if (EFI_SPECIFICATION_VERSION >= 0x0002000A) 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; Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This); // // GOP protocol is required in UEFI mode. // ASSERT (Private->GraphicsOutput != NULL); 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); Blt->Image.Screen = Private->GraphicsOutput; 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); 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 ); SafeFreePool (Blt); SafeFreePool (String); SafeFreePool (FontInfo); return Status; } #else 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; } #endif 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; }