2 This is the main routine for initializing the Graphics Console support routines.
4 Add all standard Glyphs from EFI 1.02 Specification
5 Implement optimal automatic Mode creation algorithm
6 Solve palette issues for mixed graphics and text
7 When does this protocol reset the palette?
9 Copyright (c) 2006 Intel Corporation. <BR>
10 All rights reserved. This program and the accompanying materials
11 are licensed and made available under the terms and conditions of the BSD License
12 which accompanies this distribution. The full text of the license may be found at
13 http://opensource.org/licenses/bsd-license.php
15 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
16 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 #include "GraphicsConsole.h"
23 // Function Prototypes
27 GraphicsConsoleControllerDriverSupported (
28 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
29 IN EFI_HANDLE Controller
,
30 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
35 GraphicsConsoleControllerDriverStart (
36 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
37 IN EFI_HANDLE Controller
,
38 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
43 GraphicsConsoleControllerDriverStop (
44 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
45 IN EFI_HANDLE Controller
,
46 IN UINTN NumberOfChildren
,
47 IN EFI_HANDLE
*ChildHandleBuffer
52 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
53 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Foreground
,
54 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Background
58 DrawUnicodeWeightAtCursor (
59 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
60 IN CHAR16 UnicodeWeight
64 DrawUnicodeWeightAtCursorN (
65 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
66 IN CHAR16
*UnicodeWeight
,
72 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
78 GRAPHICS_CONSOLE_DEV mGraphicsConsoleDevTemplate
= {
79 GRAPHICS_CONSOLE_DEV_SIGNATURE
,
80 (EFI_GRAPHICS_OUTPUT_PROTOCOL
*) NULL
,
81 (EFI_UGA_DRAW_PROTOCOL
*) NULL
,
83 GraphicsConsoleConOutReset
,
84 GraphicsConsoleConOutOutputString
,
85 GraphicsConsoleConOutTestString
,
86 GraphicsConsoleConOutQueryMode
,
87 GraphicsConsoleConOutSetMode
,
88 GraphicsConsoleConOutSetAttribute
,
89 GraphicsConsoleConOutClearScreen
,
90 GraphicsConsoleConOutSetCursorPosition
,
91 GraphicsConsoleConOutEnableCursor
,
92 (EFI_SIMPLE_TEXT_OUTPUT_MODE
*) NULL
97 EFI_TEXT_ATTR(EFI_LIGHTGRAY
, EFI_BLACK
),
103 { 80, 25, 0, 0, 0, 0 }, // Mode 0
104 { 80, 50, 0, 0, 0, 0 }, // Mode 1
105 { 0, 0, 0, 0, 0, 0 } // Mode 2
107 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) NULL
,
111 EFI_HII_PROTOCOL
*mHii
;
113 static CHAR16 mCrLfString
[3] = { CHAR_CARRIAGE_RETURN
, CHAR_LINEFEED
, CHAR_NULL
};
115 static EFI_GRAPHICS_OUTPUT_BLT_PIXEL mEfiColors
[16] = {
119 {0x00, 0x00, 0x00, 0x00}, // BLACK
120 {0x98, 0x00, 0x00, 0x00}, // BLUE
121 {0x00, 0x98, 0x00, 0x00}, // GREEN
122 {0x98, 0x98, 0x00, 0x00}, // CYAN
123 {0x00, 0x00, 0x98, 0x00}, // RED
124 {0x98, 0x00, 0x98, 0x00}, // MAGENTA
125 {0x00, 0x98, 0x98, 0x00}, // BROWN
126 {0x98, 0x98, 0x98, 0x00}, // LIGHTGRAY
127 {0x30, 0x30, 0x30, 0x00}, // DARKGRAY - BRIGHT BLACK
128 {0xff, 0x00, 0x00, 0x00}, // LIGHTBLUE - ?
129 {0x00, 0xff, 0x00, 0x00}, // LIGHTGREEN - ?
130 {0xff, 0xff, 0x00, 0x00}, // LIGHTCYAN
131 {0x00, 0x00, 0xff, 0x00}, // LIGHTRED
132 {0xff, 0x00, 0xff, 0x00}, // LIGHTMAGENTA
133 {0x00, 0xff, 0xff, 0x00}, // LIGHTBROWN
134 {0xff, 0xff, 0xff, 0x00} // WHITE
137 static EFI_NARROW_GLYPH mCursorGlyph
= {
140 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF }
143 EFI_DRIVER_BINDING_PROTOCOL gGraphicsConsoleDriverBinding
= {
144 GraphicsConsoleControllerDriverSupported
,
145 GraphicsConsoleControllerDriverStart
,
146 GraphicsConsoleControllerDriverStop
,
154 GraphicsConsoleControllerDriverSupported (
155 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
156 IN EFI_HANDLE Controller
,
157 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
161 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
162 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
163 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
167 // Open the IO Abstraction(s) needed to perform the supported test
169 Status
= gBS
->OpenProtocol (
171 &gEfiGraphicsOutputProtocolGuid
,
172 (VOID
**) &GraphicsOutput
,
173 This
->DriverBindingHandle
,
175 EFI_OPEN_PROTOCOL_BY_DRIVER
178 if (EFI_ERROR (Status
)) {
179 GraphicsOutput
= NULL
;
181 // Open Graphics Output Protocol failed, try to open UGA Draw Protocol
183 Status
= gBS
->OpenProtocol (
185 &gEfiUgaDrawProtocolGuid
,
187 This
->DriverBindingHandle
,
189 EFI_OPEN_PROTOCOL_BY_DRIVER
191 if (EFI_ERROR (Status
)) {
197 // We need to ensure that we do not layer on top of a virtual handle.
198 // We need to ensure that the handles produced by the conspliter do not
201 Status
= gBS
->OpenProtocol (
203 &gEfiDevicePathProtocolGuid
,
204 (VOID
**) &DevicePath
,
205 This
->DriverBindingHandle
,
207 EFI_OPEN_PROTOCOL_BY_DRIVER
209 if (!EFI_ERROR (Status
)) {
212 &gEfiDevicePathProtocolGuid
,
213 This
->DriverBindingHandle
,
220 // Does Hii Exist? If not, we aren't ready to run
222 Status
= EfiLocateHiiProtocol ();
225 // Close the I/O Abstraction(s) used to perform the supported test
228 if (GraphicsOutput
!= NULL
) {
231 &gEfiGraphicsOutputProtocolGuid
,
232 This
->DriverBindingHandle
,
238 &gEfiUgaDrawProtocolGuid
,
239 This
->DriverBindingHandle
,
248 GraphicsConsoleControllerDriverStart (
249 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
250 IN EFI_HANDLE Controller
,
251 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
257 Start the controller.
261 This - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
262 Controller - The handle of the controller to start.
263 RemainingDevicePath - A pointer to the remaining portion of a devcie path.
267 EFI_SUCCESS - Return successfully.
268 EFI_OUT_OF_RESOURCES - Out of resources.
273 GRAPHICS_CONSOLE_DEV
*Private
;
274 EFI_HII_PACKAGES
*Package
;
275 EFI_HII_FONT_PACK
*FontPack
;
276 UINTN NarrowFontSize
;
277 UINT32 HorizontalResolution
;
278 UINT32 VerticalResolution
;
287 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
292 // Initialize the Graphics Console device instance
294 Private
= AllocateCopyPool (
295 sizeof (GRAPHICS_CONSOLE_DEV
),
296 &mGraphicsConsoleDevTemplate
298 if (Private
== NULL
) {
299 return EFI_OUT_OF_RESOURCES
;
302 Private
->SimpleTextOutput
.Mode
= &(Private
->SimpleTextOutputMode
);
304 Status
= gBS
->OpenProtocol (
306 &gEfiGraphicsOutputProtocolGuid
,
307 (VOID
**) &Private
->GraphicsOutput
,
308 This
->DriverBindingHandle
,
310 EFI_OPEN_PROTOCOL_BY_DRIVER
312 if (EFI_ERROR(Status
)) {
313 Private
->GraphicsOutput
= NULL
;
315 Status
= gBS
->OpenProtocol (
317 &gEfiUgaDrawProtocolGuid
,
318 (VOID
**) &Private
->UgaDraw
,
319 This
->DriverBindingHandle
,
321 EFI_OPEN_PROTOCOL_BY_DRIVER
323 if (EFI_ERROR (Status
)) {
329 // Get the HII protocol. If Supported() succeeds, do we really
330 // need to get HII protocol again?
332 Status
= EfiLocateHiiProtocol ();
333 if (EFI_ERROR (Status
)) {
337 NarrowFontSize
= ReturnNarrowFontSize ();
339 FontPack
= AllocateZeroPool (sizeof (EFI_HII_FONT_PACK
) + NarrowFontSize
);
342 FontPack
->Header
.Length
= (UINT32
) (sizeof (EFI_HII_FONT_PACK
) + NarrowFontSize
);
343 FontPack
->Header
.Type
= EFI_HII_FONT
;
344 FontPack
->NumberOfNarrowGlyphs
= (UINT16
) (NarrowFontSize
/ sizeof (EFI_NARROW_GLYPH
));
346 Location
= (UINT8
*) (&FontPack
->NumberOfWideGlyphs
+ sizeof (UINT8
));
347 CopyMem (Location
, UsStdNarrowGlyphData
, NarrowFontSize
);
350 // Register our Fonts into the global database
352 Package
= PreparePackages (1, NULL
, FontPack
);
353 mHii
->NewPack (mHii
, Package
, &(Private
->HiiHandle
));
354 gBS
->FreePool (Package
);
357 // Free the font database
359 gBS
->FreePool (FontPack
);
362 // If the current mode information can not be retrieved, then attemp to set the default mode
363 // of 800x600, 32 bit colot, 60 Hz refresh.
365 HorizontalResolution
= 800;
366 VerticalResolution
= 600;
368 if (Private
->GraphicsOutput
!= NULL
) {
370 // The console is build on top of Graphics Output Protocol, find the mode number for 800x600
372 for (ModeNumber
= 0; ModeNumber
< Private
->GraphicsOutput
->Mode
->MaxMode
; ModeNumber
++) {
373 Status
= Private
->GraphicsOutput
->QueryMode (
374 Private
->GraphicsOutput
,
379 if (!EFI_ERROR (Status
)) {
380 if ((Info
->HorizontalResolution
== 800) &&
381 (Info
->VerticalResolution
== 600) &&
382 ((Info
->PixelFormat
== PixelRedGreenBlueReserved8BitPerColor
) ||
383 (Info
->PixelFormat
== PixelBlueGreenRedReserved8BitPerColor
))) {
384 Status
= Private
->GraphicsOutput
->SetMode (Private
->GraphicsOutput
, ModeNumber
);
385 if (!EFI_ERROR (Status
)) {
386 gBS
->FreePool (Info
);
390 gBS
->FreePool (Info
);
394 if (EFI_ERROR (Status
) || (ModeNumber
== Private
->GraphicsOutput
->Mode
->MaxMode
)) {
396 // Set default mode failed or device don't support default mode, then get the current mode information
398 HorizontalResolution
= Private
->GraphicsOutput
->Mode
->Info
->HorizontalResolution
;
399 VerticalResolution
= Private
->GraphicsOutput
->Mode
->Info
->VerticalResolution
;
400 ModeNumber
= Private
->GraphicsOutput
->Mode
->Mode
;
404 // The console is build on top of UGA Draw Protocol
408 Status
= Private
->UgaDraw
->SetMode (
410 HorizontalResolution
,
415 if (EFI_ERROR (Status
)) {
417 // Get the current mode information from the UGA Draw Protocol
419 Status
= Private
->UgaDraw
->GetMode (
421 &HorizontalResolution
,
426 if (EFI_ERROR (Status
)) {
433 // Compute the maximum number of text Rows and Columns that this current graphics mode can support
435 Columns
= HorizontalResolution
/ GLYPH_WIDTH
;
436 Rows
= VerticalResolution
/ GLYPH_HEIGHT
;
439 // See if the mode is too small to support the required 80x25 text mode
441 if (Columns
< 80 || Rows
< 25) {
445 // Add Mode #0 that must be 80x25
448 Private
->ModeData
[MaxMode
].GopWidth
= HorizontalResolution
;
449 Private
->ModeData
[MaxMode
].GopHeight
= VerticalResolution
;
450 Private
->ModeData
[MaxMode
].GopModeNumber
= ModeNumber
;
451 Private
->ModeData
[MaxMode
].DeltaX
= (HorizontalResolution
- (80 * GLYPH_WIDTH
)) >> 1;
452 Private
->ModeData
[MaxMode
].DeltaY
= (VerticalResolution
- (25 * GLYPH_HEIGHT
)) >> 1;
456 // If it is possible to support Mode #1 - 80x50, than add it as an active mode
459 Private
->ModeData
[MaxMode
].GopWidth
= HorizontalResolution
;
460 Private
->ModeData
[MaxMode
].GopHeight
= VerticalResolution
;
461 Private
->ModeData
[MaxMode
].GopModeNumber
= ModeNumber
;
462 Private
->ModeData
[MaxMode
].DeltaX
= (HorizontalResolution
- (80 * GLYPH_WIDTH
)) >> 1;
463 Private
->ModeData
[MaxMode
].DeltaY
= (VerticalResolution
- (50 * GLYPH_HEIGHT
)) >> 1;
467 // If the graphics mode is 800x600, than add a text mode that uses the entire display
469 if (HorizontalResolution
== 800 && VerticalResolution
== 600) {
472 Private
->ModeData
[MaxMode
].Columns
= 0;
473 Private
->ModeData
[MaxMode
].Rows
= 0;
474 Private
->ModeData
[MaxMode
].GopWidth
= 800;
475 Private
->ModeData
[MaxMode
].GopHeight
= 600;
476 Private
->ModeData
[MaxMode
].GopModeNumber
= ModeNumber
;
477 Private
->ModeData
[MaxMode
].DeltaX
= 0;
478 Private
->ModeData
[MaxMode
].DeltaY
= 0;
482 Private
->ModeData
[MaxMode
].Columns
= 800 / GLYPH_WIDTH
;
483 Private
->ModeData
[MaxMode
].Rows
= 600 / GLYPH_HEIGHT
;
484 Private
->ModeData
[MaxMode
].GopWidth
= 800;
485 Private
->ModeData
[MaxMode
].GopHeight
= 600;
486 Private
->ModeData
[MaxMode
].GopModeNumber
= ModeNumber
;
487 Private
->ModeData
[MaxMode
].DeltaX
= (800 % GLYPH_WIDTH
) >> 1;
488 Private
->ModeData
[MaxMode
].DeltaY
= (600 % GLYPH_HEIGHT
) >> 1;
492 // Update the maximum number of modes
494 Private
->SimpleTextOutputMode
.MaxMode
= (INT32
) MaxMode
;
497 // Determine the number of text modes that this protocol can support
499 Status
= GraphicsConsoleConOutSetMode (&Private
->SimpleTextOutput
, 0);
500 if (EFI_ERROR (Status
)) {
505 GraphicsConsoleConOutOutputString (&Private
->SimpleTextOutput
, (CHAR16
*)L
"Graphics Console Started\n\r");
509 // Install protocol interfaces for the Graphics Console device.
511 Status
= gBS
->InstallMultipleProtocolInterfaces (
513 &gEfiSimpleTextOutProtocolGuid
,
514 &Private
->SimpleTextOutput
,
519 if (EFI_ERROR (Status
)) {
521 // Close the GOP or UGA IO Protocol
523 if (Private
->GraphicsOutput
!= NULL
) {
526 &gEfiGraphicsOutputProtocolGuid
,
527 This
->DriverBindingHandle
,
533 &gEfiUgaDrawProtocolGuid
,
534 This
->DriverBindingHandle
,
542 if (Private
!= NULL
) {
543 gBS
->FreePool (Private
->LineBuffer
);
544 gBS
->FreePool (Private
);
553 GraphicsConsoleControllerDriverStop (
554 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
555 IN EFI_HANDLE Controller
,
556 IN UINTN NumberOfChildren
,
557 IN EFI_HANDLE
*ChildHandleBuffer
561 EFI_SIMPLE_TEXT_OUT_PROTOCOL
*SimpleTextOutput
;
562 GRAPHICS_CONSOLE_DEV
*Private
;
564 Status
= gBS
->OpenProtocol (
566 &gEfiSimpleTextOutProtocolGuid
,
567 (VOID
**) &SimpleTextOutput
,
568 This
->DriverBindingHandle
,
570 EFI_OPEN_PROTOCOL_GET_PROTOCOL
572 if (EFI_ERROR (Status
)) {
573 return EFI_NOT_STARTED
;
576 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (SimpleTextOutput
);
578 Status
= gBS
->UninstallProtocolInterface (
580 &gEfiSimpleTextOutProtocolGuid
,
581 &Private
->SimpleTextOutput
584 if (!EFI_ERROR (Status
)) {
586 // Close the GOP or UGA IO Protocol
588 if (Private
->GraphicsOutput
!= NULL
) {
591 &gEfiGraphicsOutputProtocolGuid
,
592 This
->DriverBindingHandle
,
598 &gEfiUgaDrawProtocolGuid
,
599 This
->DriverBindingHandle
,
605 // Remove the font pack
607 mHii
->RemovePack (mHii
, Private
->HiiHandle
);
610 // Free our instance data
612 if (Private
!= NULL
) {
613 gBS
->FreePool (Private
->LineBuffer
);
614 gBS
->FreePool (Private
);
622 EfiLocateHiiProtocol (
628 Find if the HII protocol is available. If yes, locate the HII protocol
641 // There should only be one - so buffer size is this
643 Size
= sizeof (EFI_HANDLE
);
645 Status
= gBS
->LocateHandle (
647 &gEfiHiiProtocolGuid
,
653 if (EFI_ERROR (Status
)) {
657 Status
= gBS
->HandleProtocol (
659 &gEfiHiiProtocolGuid
,
666 // Body of the STO functions
670 GraphicsConsoleConOutReset (
671 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
672 IN BOOLEAN ExtendedVerification
677 Implements SIMPLE_TEXT_OUTPUT.Reset().
678 If ExtendeVerification is TRUE, then perform dependent Graphics Console
679 device reset, and set display mode to mode 0.
680 If ExtendedVerification is FALSE, only set display mode to mode 0.
684 This - Indicates the calling context.
686 ExtendedVerification - Indicates that the driver may perform a more exhaustive
687 verification operation of the device during reset.
692 The reset operation succeeds.
695 The Graphics Console is not functioning correctly
699 This
->SetAttribute (This
, EFI_TEXT_ATTR (This
->Mode
->Attribute
& 0x0F, EFI_BACKGROUND_BLACK
));
700 return This
->SetMode (This
, 0);
705 GraphicsConsoleConOutOutputString (
706 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
712 Implements SIMPLE_TEXT_OUTPUT.OutputString().
713 The Unicode string will be converted to Glyphs and will be
714 sent to the Graphics Console.
719 This - Indicates the calling context.
721 WString - The Null-terminated Unicode string to be displayed on
722 the Graphics Console.
727 The string is output successfully.
730 The Graphics Console failed to send the string out.
732 EFI_WARN_UNKNOWN_GLYPH
733 Indicates that some of the characters in the Unicode string could not
734 be rendered and are skipped.
738 GRAPHICS_CONSOLE_DEV
*Private
;
739 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
740 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
749 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground
;
750 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background
;
755 INT32 OriginAttribute
;
756 CHAR16 SpaceStr
[] = { NARROW_CHAR
, ' ', 0 };
761 Mode
= This
->Mode
->Mode
;
762 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This
);
763 GraphicsOutput
= Private
->GraphicsOutput
;
764 UgaDraw
= Private
->UgaDraw
;
766 MaxColumn
= Private
->ModeData
[Mode
].Columns
;
767 MaxRow
= Private
->ModeData
[Mode
].Rows
;
768 DeltaX
= Private
->ModeData
[Mode
].DeltaX
;
769 DeltaY
= Private
->ModeData
[Mode
].DeltaY
;
770 Width
= MaxColumn
* GLYPH_WIDTH
;
771 Height
= (MaxRow
- 1) * GLYPH_HEIGHT
;
772 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
775 // The Attributes won't change when during the time OutputString is called
777 GetTextColors (This
, &Foreground
, &Background
);
786 OriginAttribute
= This
->Mode
->Attribute
;
790 if (*WString
== CHAR_BACKSPACE
) {
792 // If the cursor is at the left edge of the display, then move the cursor
795 if (This
->Mode
->CursorColumn
== 0 && This
->Mode
->CursorRow
> 0) {
796 This
->Mode
->CursorRow
--;
797 This
->Mode
->CursorColumn
= (INT32
) (MaxColumn
- 1);
798 This
->OutputString (This
, SpaceStr
);
800 This
->Mode
->CursorRow
--;
801 This
->Mode
->CursorColumn
= (INT32
) (MaxColumn
- 1);
802 } else if (This
->Mode
->CursorColumn
> 0) {
804 // If the cursor is not at the left edge of the display, then move the cursor
807 This
->Mode
->CursorColumn
--;
808 This
->OutputString (This
, SpaceStr
);
810 This
->Mode
->CursorColumn
--;
815 } else if (*WString
== CHAR_LINEFEED
) {
817 // If the cursor is at the bottom of the display, then scroll the display one
818 // row, and do not update the cursor position. Otherwise, move the cursor
821 if (This
->Mode
->CursorRow
== (INT32
) (MaxRow
- 1)) {
822 if (GraphicsOutput
!= NULL
) {
824 // Scroll Screen Up One Row
826 GraphicsOutput
->Blt (
831 DeltaY
+ GLYPH_HEIGHT
,
840 // Print Blank Line at last line
842 GraphicsOutput
->Blt (
856 // Scroll Screen Up One Row
863 DeltaY
+ GLYPH_HEIGHT
,
872 // Print Blank Line at last line
876 (EFI_UGA_PIXEL
*) (UINTN
) &Background
,
888 This
->Mode
->CursorRow
++;
893 } else if (*WString
== CHAR_CARRIAGE_RETURN
) {
895 // Move the cursor to the beginning of the current row.
897 This
->Mode
->CursorColumn
= 0;
900 } else if (*WString
== WIDE_CHAR
) {
902 This
->Mode
->Attribute
|= EFI_WIDE_ATTRIBUTE
;
905 } else if (*WString
== NARROW_CHAR
) {
907 This
->Mode
->Attribute
&= (~ (UINT32
) EFI_WIDE_ATTRIBUTE
);
912 // Print the character at the current cursor position and move the cursor
913 // right one column. If this moves the cursor past the right edge of the
914 // display, then the line should wrap to the beginning of the next line. This
915 // is equivalent to inserting a CR and an LF. Note that if the cursor is at the
916 // bottom of the display, and the line wraps, then the display will be scrolled
918 // If wide char is going to be displayed, need to display one character at a time
919 // Or, need to know the display length of a certain string.
921 // Index is used to determine how many character width units (wide = 2, narrow = 1)
922 // Count is used to determine how many characters are used regardless of their attributes
924 for (Count
= 0, Index
= 0; (This
->Mode
->CursorColumn
+ Index
) < MaxColumn
; Count
++, Index
++) {
925 if (WString
[Count
] == CHAR_NULL
) {
929 if (WString
[Count
] == CHAR_BACKSPACE
) {
933 if (WString
[Count
] == CHAR_LINEFEED
) {
937 if (WString
[Count
] == CHAR_CARRIAGE_RETURN
) {
941 if (WString
[Count
] == WIDE_CHAR
) {
945 if (WString
[Count
] == NARROW_CHAR
) {
949 // Is the wide attribute on?
951 if (This
->Mode
->Attribute
& EFI_WIDE_ATTRIBUTE
) {
953 // If wide, add one more width unit than normal since we are going to increment at the end of the for loop
957 // This is the end-case where if we are at column 79 and about to print a wide character
958 // We should prevent this from happening because we will wrap inappropriately. We should
959 // not print this character until the next line.
961 if ((This
->Mode
->CursorColumn
+ Index
+ 1) > MaxColumn
) {
968 Status
= DrawUnicodeWeightAtCursorN (This
, WString
, Count
);
969 if (EFI_ERROR (Status
)) {
973 // At the end of line, output carriage return and line feed
976 This
->Mode
->CursorColumn
+= (INT32
) Index
;
977 if (This
->Mode
->CursorColumn
> (INT32
) MaxColumn
) {
978 This
->Mode
->CursorColumn
-= 2;
979 This
->OutputString (This
, SpaceStr
);
982 if (This
->Mode
->CursorColumn
>= (INT32
) MaxColumn
) {
984 This
->OutputString (This
, mCrLfString
);
990 This
->Mode
->Attribute
= OriginAttribute
;
995 return EFI_WARN_UNKNOWN_GLYPH
;
1003 GraphicsConsoleConOutTestString (
1004 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
1008 Routine Description:
1010 Implements SIMPLE_TEXT_OUTPUT.TestString().
1011 If one of the characters in the *Wstring is
1012 neither valid valid Unicode drawing characters,
1013 not ASCII code, then this function will return
1019 This - Indicates the calling context.
1021 WString - The Null-terminated Unicode string to be tested.
1026 The Graphics Console is capable of rendering the output string.
1029 Some of the characters in the Unicode string cannot be rendered.
1037 GRAPHICS_CONSOLE_DEV
*Private
;
1040 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This
);
1044 while (WString
[Count
]) {
1045 Status
= mHii
->GetGlyph (
1054 if (EFI_ERROR (Status
)) {
1055 return EFI_UNSUPPORTED
;
1064 GraphicsConsoleConOutQueryMode (
1065 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
1066 IN UINTN ModeNumber
,
1071 Routine Description:
1073 Implements SIMPLE_TEXT_OUTPUT.QueryMode().
1074 It returnes information for an available text mode
1075 that the Graphics Console supports.
1076 In this driver,we only support text mode 80x25, which is
1082 This - Indicates the calling context.
1084 ModeNumber - The mode number to return information on.
1086 Columns - The returned columns of the requested mode.
1088 Rows - The returned rows of the requested mode.
1093 The requested mode information is returned.
1096 The mode number is not valid.
1100 GRAPHICS_CONSOLE_DEV
*Private
;
1102 if (ModeNumber
>= (UINTN
) This
->Mode
->MaxMode
) {
1103 return EFI_UNSUPPORTED
;
1106 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This
);
1108 *Columns
= Private
->ModeData
[ModeNumber
].Columns
;
1109 *Rows
= Private
->ModeData
[ModeNumber
].Rows
;
1111 if (*Columns
<= 0 && *Rows
<= 0) {
1112 return EFI_UNSUPPORTED
;
1121 GraphicsConsoleConOutSetMode (
1122 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
1126 Routine Description:
1128 Implements SIMPLE_TEXT_OUTPUT.SetMode().
1129 Set the Graphics Console to a specified mode.
1130 In this driver, we only support mode 0.
1134 This - Indicates the calling context.
1136 ModeNumber - The text mode to set.
1141 The requested text mode is set.
1144 The requested text mode cannot be set because of Graphics Console device error.
1147 The text mode number is not valid.
1152 GRAPHICS_CONSOLE_DEV
*Private
;
1153 GRAPHICS_CONSOLE_MODE_DATA
*ModeData
;
1154 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*NewLineBuffer
;
1155 UINT32 HorizontalResolution
;
1156 UINT32 VerticalResolution
;
1157 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
1158 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
1162 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This
);
1163 GraphicsOutput
= Private
->GraphicsOutput
;
1164 UgaDraw
= Private
->UgaDraw
;
1165 ModeData
= &(Private
->ModeData
[ModeNumber
]);
1168 // Make sure the requested mode number is supported
1170 if (ModeNumber
>= (UINTN
) This
->Mode
->MaxMode
) {
1171 return EFI_UNSUPPORTED
;
1174 if (ModeData
->Columns
<= 0 && ModeData
->Rows
<= 0) {
1175 return EFI_UNSUPPORTED
;
1178 // Attempt to allocate a line buffer for the requested mode number
1180 Status
= gBS
->AllocatePool (
1181 EfiBootServicesData
,
1182 sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * ModeData
->Columns
* GLYPH_WIDTH
* GLYPH_HEIGHT
,
1183 (VOID
**) &NewLineBuffer
1185 if (EFI_ERROR (Status
)) {
1187 // The new line buffer could not be allocated, so return an error.
1188 // No changes to the state of the current console have been made, so the current console is still valid
1193 // If the mode has been set at least one other time, then LineBuffer will not be NULL
1195 if (Private
->LineBuffer
!= NULL
) {
1197 // Clear the current text window on the current graphics console
1199 This
->ClearScreen (This
);
1202 // If the new mode is the same as the old mode, then just return EFI_SUCCESS
1204 if ((INT32
) ModeNumber
== This
->Mode
->Mode
) {
1205 gBS
->FreePool (NewLineBuffer
);
1209 // Otherwise, the size of the text console and/or the UGA mode will be changed,
1210 // so turn off the cursor, and free the LineBuffer for the current mode
1212 This
->EnableCursor (This
, FALSE
);
1214 gBS
->FreePool (Private
->LineBuffer
);
1217 // Assign the current line buffer to the newly allocated line buffer
1219 Private
->LineBuffer
= NewLineBuffer
;
1221 if (GraphicsOutput
!= NULL
) {
1222 if (ModeData
->GopModeNumber
!= GraphicsOutput
->Mode
->Mode
) {
1224 // Either no graphics mode is currently set, or it is set to the wrong resolution, so set the new grapghics mode
1226 Status
= GraphicsOutput
->SetMode (GraphicsOutput
, ModeData
->GopModeNumber
);
1227 if (EFI_ERROR (Status
)) {
1229 // The mode set operation failed
1235 // The current graphics mode is correct, so simply clear the entire display
1237 Status
= GraphicsOutput
->Blt (
1246 ModeData
->GopHeight
,
1252 // Get the current UGA Draw mode information
1254 Status
= UgaDraw
->GetMode (
1256 &HorizontalResolution
,
1257 &VerticalResolution
,
1261 if (EFI_ERROR (Status
) || HorizontalResolution
!= ModeData
->GopWidth
|| VerticalResolution
!= ModeData
->GopHeight
) {
1263 // Either no graphics mode is currently set, or it is set to the wrong resolution, so set the new grapghics mode
1265 Status
= UgaDraw
->SetMode (
1268 ModeData
->GopHeight
,
1272 if (EFI_ERROR (Status
)) {
1274 // The mode set operation failed
1280 // The current graphics mode is correct, so simply clear the entire display
1282 Status
= UgaDraw
->Blt (
1284 (EFI_UGA_PIXEL
*) (UINTN
) &mEfiColors
[0],
1291 ModeData
->GopHeight
,
1298 // The new mode is valid, so commit the mode change
1300 This
->Mode
->Mode
= (INT32
) ModeNumber
;
1303 // Move the text cursor to the upper left hand corner of the displat and enable it
1305 This
->SetCursorPosition (This
, 0, 0);
1306 This
->EnableCursor (This
, TRUE
);
1313 GraphicsConsoleConOutSetAttribute (
1314 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
1318 Routine Description:
1320 Implements SIMPLE_TEXT_OUTPUT.SetAttribute().
1324 This - Indicates the calling context.
1326 Attrubute - The attribute to set. Only bit0..6 are valid, all other bits
1327 are undefined and must be zero.
1332 The requested attribute is set.
1335 The requested attribute cannot be set due to Graphics Console port error.
1338 The attribute requested is not defined by EFI spec.
1342 if ((Attribute
| 0xFF) != 0xFF) {
1343 return EFI_UNSUPPORTED
;
1346 if ((INT32
) Attribute
== This
->Mode
->Attribute
) {
1352 This
->Mode
->Attribute
= (INT32
) Attribute
;
1361 GraphicsConsoleConOutClearScreen (
1362 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
1365 Routine Description:
1367 Implements SIMPLE_TEXT_OUTPUT.ClearScreen().
1368 It clears the Graphics Console's display to the
1369 currently selected background color.
1374 This - Indicates the calling context.
1379 The operation completed successfully.
1382 The Graphics Console cannot be cleared due to Graphics Console device error.
1385 The Graphics Console is not in a valid text mode.
1390 GRAPHICS_CONSOLE_DEV
*Private
;
1391 GRAPHICS_CONSOLE_MODE_DATA
*ModeData
;
1392 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
1393 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
1394 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground
;
1395 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background
;
1397 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This
);
1398 GraphicsOutput
= Private
->GraphicsOutput
;
1399 UgaDraw
= Private
->UgaDraw
;
1400 ModeData
= &(Private
->ModeData
[This
->Mode
->Mode
]);
1402 GetTextColors (This
, &Foreground
, &Background
);
1403 if (GraphicsOutput
!= NULL
) {
1404 Status
= GraphicsOutput
->Blt (
1413 ModeData
->GopHeight
,
1417 Status
= UgaDraw
->Blt (
1419 (EFI_UGA_PIXEL
*) (UINTN
) &Background
,
1426 ModeData
->GopHeight
,
1431 This
->Mode
->CursorColumn
= 0;
1432 This
->Mode
->CursorRow
= 0;
1441 GraphicsConsoleConOutSetCursorPosition (
1442 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
1447 Routine Description:
1449 Implements SIMPLE_TEXT_OUTPUT.SetCursorPosition().
1453 This - Indicates the calling context.
1455 Column - The row to set cursor to.
1457 Row - The column to set cursor to.
1462 The operation completed successfully.
1465 The request fails due to Graphics Console device error.
1468 The Graphics Console is not in a valid text mode, or the cursor position
1469 is invalid for current mode.
1473 GRAPHICS_CONSOLE_DEV
*Private
;
1474 GRAPHICS_CONSOLE_MODE_DATA
*ModeData
;
1476 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This
);
1477 ModeData
= &(Private
->ModeData
[This
->Mode
->Mode
]);
1479 if ((Column
>= ModeData
->Columns
) || (Row
>= ModeData
->Rows
)) {
1480 return EFI_UNSUPPORTED
;
1483 if (((INT32
) Column
== This
->Mode
->CursorColumn
) && ((INT32
) Row
== This
->Mode
->CursorRow
)) {
1489 This
->Mode
->CursorColumn
= (INT32
) Column
;
1490 This
->Mode
->CursorRow
= (INT32
) Row
;
1499 GraphicsConsoleConOutEnableCursor (
1500 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
1504 Routine Description:
1506 Implements SIMPLE_TEXT_OUTPUT.EnableCursor().
1507 In this driver, the cursor cannot be hidden.
1511 This - Indicates the calling context.
1513 Visible - If TRUE, the cursor is set to be visible,
1514 If FALSE, the cursor is set to be invisible.
1519 The request is valid.
1522 The Graphics Console does not support a hidden cursor.
1528 This
->Mode
->CursorVisible
= Visible
;
1537 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
1538 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Foreground
,
1539 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Background
1544 Attribute
= This
->Mode
->Attribute
& 0x7F;
1546 *Foreground
= mEfiColors
[Attribute
& 0x0f];
1547 *Background
= mEfiColors
[Attribute
>> 4];
1553 DrawUnicodeWeightAtCursorN (
1554 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
1555 IN CHAR16
*UnicodeWeight
,
1559 GRAPHICS_CONSOLE_DEV
*Private
;
1561 EFI_STATUS ReturnStatus
;
1563 GLYPH_UNION GlyphData
;
1566 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
1567 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
1568 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground
;
1569 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background
;
1576 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This
);
1578 ReturnStatus
= EFI_SUCCESS
;
1582 GetTextColors (This
, &Foreground
, &Background
);
1586 while (Index
< Count
) {
1587 if (This
->Mode
->Attribute
& EFI_WIDE_ATTRIBUTE
) {
1588 GlyphStatus
= WIDE_CHAR
;
1590 GlyphStatus
= NARROW_CHAR
;
1593 Status
= mHii
->GetGlyph (
1601 if (EFI_ERROR (Status
)) {
1602 ReturnStatus
= Status
;
1607 CopyMem (&GlyphData
, Glyph
, sizeof (GLYPH_UNION
));
1611 // We are creating the second half of the wide character's BLT buffer
1613 if (GlyphWidth
== 0x10 && Counts
== 1) {
1614 CopyMem (&GlyphData
.NarrowGlyph
.GlyphCol1
, &Glyph
->WideGlyph
.GlyphCol2
, sizeof (Glyph
->WideGlyph
.GlyphCol2
));
1619 if (GlyphWidth
== 0x10) {
1622 (UINT8
*) &GlyphData
,
1628 &Private
->LineBuffer
[ArrayIndex
* GLYPH_WIDTH
]
1633 (UINT8
*) &GlyphData
,
1639 &Private
->LineBuffer
[ArrayIndex
* GLYPH_WIDTH
]
1645 } while (Counts
< 2 && GlyphWidth
== 0x10);
1649 // If we are printing Wide characters, treat the BLT as if it is twice as many characters
1651 if (GlyphWidth
== 0x10) {
1655 // Blt a character to the screen
1657 GlyphX
= This
->Mode
->CursorColumn
* GLYPH_WIDTH
;
1658 GlyphY
= This
->Mode
->CursorRow
* GLYPH_HEIGHT
;
1659 GraphicsOutput
= Private
->GraphicsOutput
;
1660 UgaDraw
= Private
->UgaDraw
;
1661 if (GraphicsOutput
!= NULL
) {
1662 GraphicsOutput
->Blt (
1664 Private
->LineBuffer
,
1665 EfiBltBufferToVideo
,
1668 GlyphX
+ Private
->ModeData
[This
->Mode
->Mode
].DeltaX
,
1669 GlyphY
+ Private
->ModeData
[This
->Mode
->Mode
].DeltaY
,
1670 GLYPH_WIDTH
* Count
,
1672 GLYPH_WIDTH
* Count
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
1677 (EFI_UGA_PIXEL
*) (UINTN
) Private
->LineBuffer
,
1678 EfiUgaBltBufferToVideo
,
1681 GlyphX
+ Private
->ModeData
[This
->Mode
->Mode
].DeltaX
,
1682 GlyphY
+ Private
->ModeData
[This
->Mode
->Mode
].DeltaY
,
1683 GLYPH_WIDTH
* Count
,
1685 GLYPH_WIDTH
* Count
* sizeof (EFI_UGA_PIXEL
)
1689 return ReturnStatus
;
1694 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
1697 GRAPHICS_CONSOLE_DEV
*Private
;
1698 EFI_SIMPLE_TEXT_OUTPUT_MODE
*CurrentMode
;
1701 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
1702 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
1703 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Foreground
;
1704 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Background
;
1705 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION BltChar
[GLYPH_HEIGHT
][GLYPH_WIDTH
];
1709 CurrentMode
= This
->Mode
;
1711 if (!CurrentMode
->CursorVisible
) {
1715 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This
);
1716 GraphicsOutput
= Private
->GraphicsOutput
;
1717 UgaDraw
= Private
->UgaDraw
;
1720 // BUGBUG - we need to think about what to do with wide and narrow character deletions.
1723 // Blt a character to the screen
1725 GlyphX
= (CurrentMode
->CursorColumn
* GLYPH_WIDTH
) + Private
->ModeData
[CurrentMode
->Mode
].DeltaX
;
1726 GlyphY
= (CurrentMode
->CursorRow
* GLYPH_HEIGHT
) + Private
->ModeData
[CurrentMode
->Mode
].DeltaY
;
1727 if (GraphicsOutput
!= NULL
) {
1728 GraphicsOutput
->Blt (
1730 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) BltChar
,
1731 EfiBltVideoToBltBuffer
,
1738 GLYPH_WIDTH
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
1743 (EFI_UGA_PIXEL
*) (UINTN
) BltChar
,
1744 EfiUgaVideoToBltBuffer
,
1751 GLYPH_WIDTH
* sizeof (EFI_UGA_PIXEL
)
1755 GetTextColors (This
, &Foreground
.Pixel
, &Background
.Pixel
);
1758 // Convert Monochrome bitmap of the Glyph to BltBuffer structure
1760 for (Y
= 0; Y
< GLYPH_HEIGHT
; Y
++) {
1761 for (X
= 0; X
< GLYPH_WIDTH
; X
++) {
1762 if ((mCursorGlyph
.GlyphCol1
[Y
] & (1 << X
)) != 0) {
1763 BltChar
[Y
][GLYPH_WIDTH
- X
- 1].Raw
^= Foreground
.Raw
;
1768 if (GraphicsOutput
!= NULL
) {
1769 GraphicsOutput
->Blt (
1771 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) BltChar
,
1772 EfiBltBufferToVideo
,
1779 GLYPH_WIDTH
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
1784 (EFI_UGA_PIXEL
*) (UINTN
) BltChar
,
1785 EfiUgaBltBufferToVideo
,
1792 GLYPH_WIDTH
* sizeof (EFI_UGA_PIXEL
)