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 - 2007 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"
25 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
26 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Foreground
,
27 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Background
32 DrawUnicodeWeightAtCursorN (
33 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
34 IN CHAR16
*UnicodeWeight
,
41 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
47 GRAPHICS_CONSOLE_DEV mGraphicsConsoleDevTemplate
= {
48 GRAPHICS_CONSOLE_DEV_SIGNATURE
,
49 (EFI_GRAPHICS_OUTPUT_PROTOCOL
*) NULL
,
50 (EFI_UGA_DRAW_PROTOCOL
*) NULL
,
52 GraphicsConsoleConOutReset
,
53 GraphicsConsoleConOutOutputString
,
54 GraphicsConsoleConOutTestString
,
55 GraphicsConsoleConOutQueryMode
,
56 GraphicsConsoleConOutSetMode
,
57 GraphicsConsoleConOutSetAttribute
,
58 GraphicsConsoleConOutClearScreen
,
59 GraphicsConsoleConOutSetCursorPosition
,
60 GraphicsConsoleConOutEnableCursor
,
61 (EFI_SIMPLE_TEXT_OUTPUT_MODE
*) NULL
66 EFI_TEXT_ATTR(EFI_LIGHTGRAY
, EFI_BLACK
),
72 { 80, 25, 0, 0, 0, 0 }, // Mode 0
73 { 80, 50, 0, 0, 0, 0 }, // Mode 1
74 { 0, 0, 0, 0, 0, 0 } // Mode 2
76 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) NULL
,
80 EFI_HII_PROTOCOL
*mHii
;
82 static CHAR16 mCrLfString
[3] = { CHAR_CARRIAGE_RETURN
, CHAR_LINEFEED
, CHAR_NULL
};
84 static EFI_GRAPHICS_OUTPUT_BLT_PIXEL mEfiColors
[16] = {
88 {0x00, 0x00, 0x00, 0x00}, // BLACK
89 {0x98, 0x00, 0x00, 0x00}, // BLUE
90 {0x00, 0x98, 0x00, 0x00}, // GREEN
91 {0x98, 0x98, 0x00, 0x00}, // CYAN
92 {0x00, 0x00, 0x98, 0x00}, // RED
93 {0x98, 0x00, 0x98, 0x00}, // MAGENTA
94 {0x00, 0x98, 0x98, 0x00}, // BROWN
95 {0x98, 0x98, 0x98, 0x00}, // LIGHTGRAY
96 {0x30, 0x30, 0x30, 0x00}, // DARKGRAY - BRIGHT BLACK
97 {0xff, 0x00, 0x00, 0x00}, // LIGHTBLUE - ?
98 {0x00, 0xff, 0x00, 0x00}, // LIGHTGREEN - ?
99 {0xff, 0xff, 0x00, 0x00}, // LIGHTCYAN
100 {0x00, 0x00, 0xff, 0x00}, // LIGHTRED
101 {0xff, 0x00, 0xff, 0x00}, // LIGHTMAGENTA
102 {0x00, 0xff, 0xff, 0x00}, // LIGHTBROWN
103 {0xff, 0xff, 0xff, 0x00} // WHITE
106 static EFI_NARROW_GLYPH mCursorGlyph
= {
109 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF }
112 EFI_DRIVER_BINDING_PROTOCOL gGraphicsConsoleDriverBinding
= {
113 GraphicsConsoleControllerDriverSupported
,
114 GraphicsConsoleControllerDriverStart
,
115 GraphicsConsoleControllerDriverStop
,
123 GraphicsConsoleControllerDriverSupported (
124 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
125 IN EFI_HANDLE Controller
,
126 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
130 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
131 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
132 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
136 // Open the IO Abstraction(s) needed to perform the supported test
138 Status
= gBS
->OpenProtocol (
140 &gEfiGraphicsOutputProtocolGuid
,
141 (VOID
**) &GraphicsOutput
,
142 This
->DriverBindingHandle
,
144 EFI_OPEN_PROTOCOL_BY_DRIVER
147 if (EFI_ERROR (Status
)) {
148 GraphicsOutput
= NULL
;
150 // Open Graphics Output Protocol failed, try to open UGA Draw Protocol
152 Status
= gBS
->OpenProtocol (
154 &gEfiUgaDrawProtocolGuid
,
156 This
->DriverBindingHandle
,
158 EFI_OPEN_PROTOCOL_BY_DRIVER
160 if (EFI_ERROR (Status
)) {
166 // We need to ensure that we do not layer on top of a virtual handle.
167 // We need to ensure that the handles produced by the conspliter do not
170 Status
= gBS
->OpenProtocol (
172 &gEfiDevicePathProtocolGuid
,
173 (VOID
**) &DevicePath
,
174 This
->DriverBindingHandle
,
176 EFI_OPEN_PROTOCOL_BY_DRIVER
178 if (!EFI_ERROR (Status
)) {
181 &gEfiDevicePathProtocolGuid
,
182 This
->DriverBindingHandle
,
189 // Does Hii Exist? If not, we aren't ready to run
191 Status
= EfiLocateHiiProtocol ();
194 // Close the I/O Abstraction(s) used to perform the supported test
197 if (GraphicsOutput
!= NULL
) {
200 &gEfiGraphicsOutputProtocolGuid
,
201 This
->DriverBindingHandle
,
207 &gEfiUgaDrawProtocolGuid
,
208 This
->DriverBindingHandle
,
217 GraphicsConsoleControllerDriverStart (
218 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
219 IN EFI_HANDLE Controller
,
220 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
226 Start the controller.
230 This - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
231 Controller - The handle of the controller to start.
232 RemainingDevicePath - A pointer to the remaining portion of a devcie path.
236 EFI_SUCCESS - Return successfully.
237 EFI_OUT_OF_RESOURCES - Out of resources.
242 GRAPHICS_CONSOLE_DEV
*Private
;
243 EFI_HII_PACKAGES
*Package
;
244 EFI_HII_FONT_PACK
*FontPack
;
245 UINTN NarrowFontSize
;
246 UINT32 HorizontalResolution
;
247 UINT32 VerticalResolution
;
256 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
261 // Initialize the Graphics Console device instance
263 Private
= AllocateCopyPool (
264 sizeof (GRAPHICS_CONSOLE_DEV
),
265 &mGraphicsConsoleDevTemplate
267 if (Private
== NULL
) {
268 return EFI_OUT_OF_RESOURCES
;
271 Private
->SimpleTextOutput
.Mode
= &(Private
->SimpleTextOutputMode
);
273 Status
= gBS
->OpenProtocol (
275 &gEfiGraphicsOutputProtocolGuid
,
276 (VOID
**) &Private
->GraphicsOutput
,
277 This
->DriverBindingHandle
,
279 EFI_OPEN_PROTOCOL_BY_DRIVER
281 if (EFI_ERROR(Status
)) {
282 Private
->GraphicsOutput
= NULL
;
284 Status
= gBS
->OpenProtocol (
286 &gEfiUgaDrawProtocolGuid
,
287 (VOID
**) &Private
->UgaDraw
,
288 This
->DriverBindingHandle
,
290 EFI_OPEN_PROTOCOL_BY_DRIVER
292 if (EFI_ERROR (Status
)) {
298 // Get the HII protocol. If Supported() succeeds, do we really
299 // need to get HII protocol again?
301 Status
= EfiLocateHiiProtocol ();
302 if (EFI_ERROR (Status
)) {
306 NarrowFontSize
= ReturnNarrowFontSize ();
308 FontPack
= AllocateZeroPool (sizeof (EFI_HII_FONT_PACK
) + NarrowFontSize
);
311 FontPack
->Header
.Length
= (UINT32
) (sizeof (EFI_HII_FONT_PACK
) + NarrowFontSize
);
312 FontPack
->Header
.Type
= EFI_HII_FONT
;
313 FontPack
->NumberOfNarrowGlyphs
= (UINT16
) (NarrowFontSize
/ sizeof (EFI_NARROW_GLYPH
));
315 Location
= (UINT8
*) (&FontPack
->NumberOfWideGlyphs
+ sizeof (UINT8
));
316 CopyMem (Location
, UsStdNarrowGlyphData
, NarrowFontSize
);
319 // Register our Fonts into the global database
321 Package
= PreparePackages (1, NULL
, FontPack
);
322 mHii
->NewPack (mHii
, Package
, &(Private
->HiiHandle
));
326 // Free the font database
331 // If the current mode information can not be retrieved, then attemp to set the default mode
332 // of 800x600, 32 bit colot, 60 Hz refresh.
334 HorizontalResolution
= 800;
335 VerticalResolution
= 600;
337 if (Private
->GraphicsOutput
!= NULL
) {
339 // The console is build on top of Graphics Output Protocol, find the mode number for 800x600
341 for (ModeNumber
= 0; ModeNumber
< Private
->GraphicsOutput
->Mode
->MaxMode
; ModeNumber
++) {
342 Status
= Private
->GraphicsOutput
->QueryMode (
343 Private
->GraphicsOutput
,
348 if (!EFI_ERROR (Status
)) {
349 if ((Info
->HorizontalResolution
== 800) &&
350 (Info
->VerticalResolution
== 600)) {
351 Status
= Private
->GraphicsOutput
->SetMode (Private
->GraphicsOutput
, ModeNumber
);
352 if (!EFI_ERROR (Status
)) {
361 if (EFI_ERROR (Status
) || (ModeNumber
== Private
->GraphicsOutput
->Mode
->MaxMode
)) {
363 // Set default mode failed or device don't support default mode, then get the current mode information
365 HorizontalResolution
= Private
->GraphicsOutput
->Mode
->Info
->HorizontalResolution
;
366 VerticalResolution
= Private
->GraphicsOutput
->Mode
->Info
->VerticalResolution
;
367 ModeNumber
= Private
->GraphicsOutput
->Mode
->Mode
;
371 // The console is build on top of UGA Draw Protocol
375 Status
= Private
->UgaDraw
->SetMode (
377 HorizontalResolution
,
382 if (EFI_ERROR (Status
)) {
384 // Get the current mode information from the UGA Draw Protocol
386 Status
= Private
->UgaDraw
->GetMode (
388 &HorizontalResolution
,
393 if (EFI_ERROR (Status
)) {
400 // Compute the maximum number of text Rows and Columns that this current graphics mode can support
402 Columns
= HorizontalResolution
/ GLYPH_WIDTH
;
403 Rows
= VerticalResolution
/ GLYPH_HEIGHT
;
406 // See if the mode is too small to support the required 80x25 text mode
408 if (Columns
< 80 || Rows
< 25) {
412 // Add Mode #0 that must be 80x25
415 Private
->ModeData
[MaxMode
].GopWidth
= HorizontalResolution
;
416 Private
->ModeData
[MaxMode
].GopHeight
= VerticalResolution
;
417 Private
->ModeData
[MaxMode
].GopModeNumber
= ModeNumber
;
418 Private
->ModeData
[MaxMode
].DeltaX
= (HorizontalResolution
- (80 * GLYPH_WIDTH
)) >> 1;
419 Private
->ModeData
[MaxMode
].DeltaY
= (VerticalResolution
- (25 * GLYPH_HEIGHT
)) >> 1;
423 // If it is possible to support Mode #1 - 80x50, than add it as an active mode
426 Private
->ModeData
[MaxMode
].GopWidth
= HorizontalResolution
;
427 Private
->ModeData
[MaxMode
].GopHeight
= VerticalResolution
;
428 Private
->ModeData
[MaxMode
].GopModeNumber
= ModeNumber
;
429 Private
->ModeData
[MaxMode
].DeltaX
= (HorizontalResolution
- (80 * GLYPH_WIDTH
)) >> 1;
430 Private
->ModeData
[MaxMode
].DeltaY
= (VerticalResolution
- (50 * GLYPH_HEIGHT
)) >> 1;
434 // If the graphics mode is 800x600, than add a text mode that uses the entire display
436 if (HorizontalResolution
== 800 && VerticalResolution
== 600) {
439 Private
->ModeData
[MaxMode
].Columns
= 0;
440 Private
->ModeData
[MaxMode
].Rows
= 0;
441 Private
->ModeData
[MaxMode
].GopWidth
= 800;
442 Private
->ModeData
[MaxMode
].GopHeight
= 600;
443 Private
->ModeData
[MaxMode
].GopModeNumber
= ModeNumber
;
444 Private
->ModeData
[MaxMode
].DeltaX
= 0;
445 Private
->ModeData
[MaxMode
].DeltaY
= 0;
449 Private
->ModeData
[MaxMode
].Columns
= 800 / GLYPH_WIDTH
;
450 Private
->ModeData
[MaxMode
].Rows
= 600 / GLYPH_HEIGHT
;
451 Private
->ModeData
[MaxMode
].GopWidth
= 800;
452 Private
->ModeData
[MaxMode
].GopHeight
= 600;
453 Private
->ModeData
[MaxMode
].GopModeNumber
= ModeNumber
;
454 Private
->ModeData
[MaxMode
].DeltaX
= (800 % GLYPH_WIDTH
) >> 1;
455 Private
->ModeData
[MaxMode
].DeltaY
= (600 % GLYPH_HEIGHT
) >> 1;
459 // Update the maximum number of modes
461 Private
->SimpleTextOutputMode
.MaxMode
= (INT32
) MaxMode
;
464 // Determine the number of text modes that this protocol can support
466 Status
= GraphicsConsoleConOutSetMode (&Private
->SimpleTextOutput
, 0);
467 if (EFI_ERROR (Status
)) {
472 GraphicsConsoleConOutOutputString (&Private
->SimpleTextOutput
, (CHAR16
*)L
"Graphics Console Started\n\r");
476 // Install protocol interfaces for the Graphics Console device.
478 Status
= gBS
->InstallMultipleProtocolInterfaces (
480 &gEfiSimpleTextOutProtocolGuid
,
481 &Private
->SimpleTextOutput
,
486 if (EFI_ERROR (Status
)) {
488 // Close the GOP or UGA IO Protocol
490 if (Private
->GraphicsOutput
!= NULL
) {
493 &gEfiGraphicsOutputProtocolGuid
,
494 This
->DriverBindingHandle
,
500 &gEfiUgaDrawProtocolGuid
,
501 This
->DriverBindingHandle
,
509 if (Private
!= NULL
) {
510 FreePool (Private
->LineBuffer
);
520 GraphicsConsoleControllerDriverStop (
521 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
522 IN EFI_HANDLE Controller
,
523 IN UINTN NumberOfChildren
,
524 IN EFI_HANDLE
*ChildHandleBuffer
528 EFI_SIMPLE_TEXT_OUT_PROTOCOL
*SimpleTextOutput
;
529 GRAPHICS_CONSOLE_DEV
*Private
;
531 Status
= gBS
->OpenProtocol (
533 &gEfiSimpleTextOutProtocolGuid
,
534 (VOID
**) &SimpleTextOutput
,
535 This
->DriverBindingHandle
,
537 EFI_OPEN_PROTOCOL_GET_PROTOCOL
539 if (EFI_ERROR (Status
)) {
540 return EFI_NOT_STARTED
;
543 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (SimpleTextOutput
);
545 Status
= gBS
->UninstallProtocolInterface (
547 &gEfiSimpleTextOutProtocolGuid
,
548 &Private
->SimpleTextOutput
551 if (!EFI_ERROR (Status
)) {
553 // Close the GOP or UGA IO Protocol
555 if (Private
->GraphicsOutput
!= NULL
) {
558 &gEfiGraphicsOutputProtocolGuid
,
559 This
->DriverBindingHandle
,
565 &gEfiUgaDrawProtocolGuid
,
566 This
->DriverBindingHandle
,
572 // Remove the font pack
574 mHii
->RemovePack (mHii
, Private
->HiiHandle
);
577 // Free our instance data
579 if (Private
!= NULL
) {
580 FreePool (Private
->LineBuffer
);
589 EfiLocateHiiProtocol (
595 Find if the HII protocol is available. If yes, locate the HII protocol
608 // There should only be one - so buffer size is this
610 Size
= sizeof (EFI_HANDLE
);
612 Status
= gBS
->LocateHandle (
614 &gEfiHiiProtocolGuid
,
620 if (EFI_ERROR (Status
)) {
624 Status
= gBS
->HandleProtocol (
626 &gEfiHiiProtocolGuid
,
633 // Body of the STO functions
637 GraphicsConsoleConOutReset (
638 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
639 IN BOOLEAN ExtendedVerification
644 Implements SIMPLE_TEXT_OUTPUT.Reset().
645 If ExtendeVerification is TRUE, then perform dependent Graphics Console
646 device reset, and set display mode to mode 0.
647 If ExtendedVerification is FALSE, only set display mode to mode 0.
651 This - Indicates the calling context.
653 ExtendedVerification - Indicates that the driver may perform a more exhaustive
654 verification operation of the device during reset.
659 The reset operation succeeds.
662 The Graphics Console is not functioning correctly
666 This
->SetAttribute (This
, EFI_TEXT_ATTR (This
->Mode
->Attribute
& 0x0F, EFI_BACKGROUND_BLACK
));
667 return This
->SetMode (This
, 0);
672 GraphicsConsoleConOutOutputString (
673 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
679 Implements SIMPLE_TEXT_OUTPUT.OutputString().
680 The Unicode string will be converted to Glyphs and will be
681 sent to the Graphics Console.
686 This - Indicates the calling context.
688 WString - The Null-terminated Unicode string to be displayed on
689 the Graphics Console.
694 The string is output successfully.
697 The Graphics Console failed to send the string out.
699 EFI_WARN_UNKNOWN_GLYPH
700 Indicates that some of the characters in the Unicode string could not
701 be rendered and are skipped.
705 GRAPHICS_CONSOLE_DEV
*Private
;
706 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
707 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
716 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground
;
717 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background
;
722 INT32 OriginAttribute
;
724 CHAR16 SpaceStr
[] = { NARROW_CHAR
, ' ', 0 };
726 Status
= EFI_SUCCESS
;
728 OldTpl
= gBS
->RaiseTPL (EFI_TPL_NOTIFY
);
732 Mode
= This
->Mode
->Mode
;
733 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This
);
734 GraphicsOutput
= Private
->GraphicsOutput
;
735 UgaDraw
= Private
->UgaDraw
;
737 MaxColumn
= Private
->ModeData
[Mode
].Columns
;
738 MaxRow
= Private
->ModeData
[Mode
].Rows
;
739 DeltaX
= Private
->ModeData
[Mode
].DeltaX
;
740 DeltaY
= Private
->ModeData
[Mode
].DeltaY
;
741 Width
= MaxColumn
* GLYPH_WIDTH
;
742 Height
= (MaxRow
- 1) * GLYPH_HEIGHT
;
743 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
746 // The Attributes won't change when during the time OutputString is called
748 GetTextColors (This
, &Foreground
, &Background
);
757 OriginAttribute
= This
->Mode
->Attribute
;
761 if (*WString
== CHAR_BACKSPACE
) {
763 // If the cursor is at the left edge of the display, then move the cursor
766 if (This
->Mode
->CursorColumn
== 0 && This
->Mode
->CursorRow
> 0) {
767 This
->Mode
->CursorRow
--;
768 This
->Mode
->CursorColumn
= (INT32
) (MaxColumn
- 1);
769 This
->OutputString (This
, SpaceStr
);
771 This
->Mode
->CursorRow
--;
772 This
->Mode
->CursorColumn
= (INT32
) (MaxColumn
- 1);
773 } else if (This
->Mode
->CursorColumn
> 0) {
775 // If the cursor is not at the left edge of the display, then move the cursor
778 This
->Mode
->CursorColumn
--;
779 This
->OutputString (This
, SpaceStr
);
781 This
->Mode
->CursorColumn
--;
786 } else if (*WString
== CHAR_LINEFEED
) {
788 // If the cursor is at the bottom of the display, then scroll the display one
789 // row, and do not update the cursor position. Otherwise, move the cursor
792 if (This
->Mode
->CursorRow
== (INT32
) (MaxRow
- 1)) {
793 if (GraphicsOutput
!= NULL
) {
795 // Scroll Screen Up One Row
797 GraphicsOutput
->Blt (
802 DeltaY
+ GLYPH_HEIGHT
,
811 // Print Blank Line at last line
813 GraphicsOutput
->Blt (
827 // Scroll Screen Up One Row
834 DeltaY
+ GLYPH_HEIGHT
,
843 // Print Blank Line at last line
847 (EFI_UGA_PIXEL
*) (UINTN
) &Background
,
859 This
->Mode
->CursorRow
++;
864 } else if (*WString
== CHAR_CARRIAGE_RETURN
) {
866 // Move the cursor to the beginning of the current row.
868 This
->Mode
->CursorColumn
= 0;
871 } else if (*WString
== WIDE_CHAR
) {
873 This
->Mode
->Attribute
|= EFI_WIDE_ATTRIBUTE
;
876 } else if (*WString
== NARROW_CHAR
) {
878 This
->Mode
->Attribute
&= (~ (UINT32
) EFI_WIDE_ATTRIBUTE
);
883 // Print the character at the current cursor position and move the cursor
884 // right one column. If this moves the cursor past the right edge of the
885 // display, then the line should wrap to the beginning of the next line. This
886 // is equivalent to inserting a CR and an LF. Note that if the cursor is at the
887 // bottom of the display, and the line wraps, then the display will be scrolled
889 // If wide char is going to be displayed, need to display one character at a time
890 // Or, need to know the display length of a certain string.
892 // Index is used to determine how many character width units (wide = 2, narrow = 1)
893 // Count is used to determine how many characters are used regardless of their attributes
895 for (Count
= 0, Index
= 0; (This
->Mode
->CursorColumn
+ Index
) < MaxColumn
; Count
++, Index
++) {
896 if (WString
[Count
] == CHAR_NULL
) {
900 if (WString
[Count
] == CHAR_BACKSPACE
) {
904 if (WString
[Count
] == CHAR_LINEFEED
) {
908 if (WString
[Count
] == CHAR_CARRIAGE_RETURN
) {
912 if (WString
[Count
] == WIDE_CHAR
) {
916 if (WString
[Count
] == NARROW_CHAR
) {
920 // Is the wide attribute on?
922 if (This
->Mode
->Attribute
& EFI_WIDE_ATTRIBUTE
) {
924 // If wide, add one more width unit than normal since we are going to increment at the end of the for loop
928 // This is the end-case where if we are at column 79 and about to print a wide character
929 // We should prevent this from happening because we will wrap inappropriately. We should
930 // not print this character until the next line.
932 if ((This
->Mode
->CursorColumn
+ Index
+ 1) > MaxColumn
) {
939 Status
= DrawUnicodeWeightAtCursorN (This
, WString
, Count
);
940 if (EFI_ERROR (Status
)) {
944 // At the end of line, output carriage return and line feed
947 This
->Mode
->CursorColumn
+= (INT32
) Index
;
948 if (This
->Mode
->CursorColumn
> (INT32
) MaxColumn
) {
949 This
->Mode
->CursorColumn
-= 2;
950 This
->OutputString (This
, SpaceStr
);
953 if (This
->Mode
->CursorColumn
>= (INT32
) MaxColumn
) {
955 This
->OutputString (This
, mCrLfString
);
961 This
->Mode
->Attribute
= OriginAttribute
;
966 Status
= EFI_WARN_UNKNOWN_GLYPH
;
969 gBS
->RestoreTPL (OldTpl
);
976 GraphicsConsoleConOutTestString (
977 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
983 Implements SIMPLE_TEXT_OUTPUT.TestString().
984 If one of the characters in the *Wstring is
985 neither valid valid Unicode drawing characters,
986 not ASCII code, then this function will return
992 This - Indicates the calling context.
994 WString - The Null-terminated Unicode string to be tested.
999 The Graphics Console is capable of rendering the output string.
1002 Some of the characters in the Unicode string cannot be rendered.
1015 while (WString
[Count
]) {
1016 Status
= mHii
->GetGlyph (
1025 if (EFI_ERROR (Status
)) {
1026 return EFI_UNSUPPORTED
;
1035 GraphicsConsoleConOutQueryMode (
1036 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
1037 IN UINTN ModeNumber
,
1042 Routine Description:
1044 Implements SIMPLE_TEXT_OUTPUT.QueryMode().
1045 It returnes information for an available text mode
1046 that the Graphics Console supports.
1047 In this driver,we only support text mode 80x25, which is
1053 This - Indicates the calling context.
1055 ModeNumber - The mode number to return information on.
1057 Columns - The returned columns of the requested mode.
1059 Rows - The returned rows of the requested mode.
1064 The requested mode information is returned.
1067 The mode number is not valid.
1071 GRAPHICS_CONSOLE_DEV
*Private
;
1075 if (ModeNumber
>= (UINTN
) This
->Mode
->MaxMode
) {
1076 return EFI_UNSUPPORTED
;
1079 OldTpl
= gBS
->RaiseTPL (EFI_TPL_NOTIFY
);
1080 Status
= EFI_SUCCESS
;
1082 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This
);
1084 *Columns
= Private
->ModeData
[ModeNumber
].Columns
;
1085 *Rows
= Private
->ModeData
[ModeNumber
].Rows
;
1087 if (*Columns
<= 0 && *Rows
<= 0) {
1088 Status
= EFI_UNSUPPORTED
;
1094 gBS
->RestoreTPL (OldTpl
);
1100 GraphicsConsoleConOutSetMode (
1101 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
1105 Routine Description:
1107 Implements SIMPLE_TEXT_OUTPUT.SetMode().
1108 Set the Graphics Console to a specified mode.
1109 In this driver, we only support mode 0.
1113 This - Indicates the calling context.
1115 ModeNumber - The text mode to set.
1120 The requested text mode is set.
1123 The requested text mode cannot be set because of Graphics Console device error.
1126 The text mode number is not valid.
1131 GRAPHICS_CONSOLE_DEV
*Private
;
1132 GRAPHICS_CONSOLE_MODE_DATA
*ModeData
;
1133 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*NewLineBuffer
;
1134 UINT32 HorizontalResolution
;
1135 UINT32 VerticalResolution
;
1136 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
1137 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
1142 OldTpl
= gBS
->RaiseTPL (EFI_TPL_NOTIFY
);
1144 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This
);
1145 GraphicsOutput
= Private
->GraphicsOutput
;
1146 UgaDraw
= Private
->UgaDraw
;
1147 ModeData
= &(Private
->ModeData
[ModeNumber
]);
1149 if (ModeData
->Columns
<= 0 && ModeData
->Rows
<= 0) {
1150 Status
= EFI_UNSUPPORTED
;
1155 // Make sure the requested mode number is supported
1157 if (ModeNumber
>= (UINTN
) This
->Mode
->MaxMode
) {
1158 Status
= EFI_UNSUPPORTED
;
1162 if (ModeData
->Columns
<= 0 && ModeData
->Rows
<= 0) {
1163 Status
= EFI_UNSUPPORTED
;
1167 // Attempt to allocate a line buffer for the requested mode number
1169 NewLineBuffer
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * ModeData
->Columns
* GLYPH_WIDTH
* GLYPH_HEIGHT
);
1171 if (NewLineBuffer
== NULL
) {
1173 // The new line buffer could not be allocated, so return an error.
1174 // No changes to the state of the current console have been made, so the current console is still valid
1176 Status
= EFI_OUT_OF_RESOURCES
;
1180 // If the mode has been set at least one other time, then LineBuffer will not be NULL
1182 if (Private
->LineBuffer
!= NULL
) {
1184 // Clear the current text window on the current graphics console
1186 This
->ClearScreen (This
);
1189 // If the new mode is the same as the old mode, then just return EFI_SUCCESS
1191 if ((INT32
) ModeNumber
== This
->Mode
->Mode
) {
1192 FreePool (NewLineBuffer
);
1193 Status
= EFI_SUCCESS
;
1197 // Otherwise, the size of the text console and/or the UGA mode will be changed,
1198 // so turn off the cursor, and free the LineBuffer for the current mode
1200 This
->EnableCursor (This
, FALSE
);
1202 FreePool (Private
->LineBuffer
);
1205 // Assign the current line buffer to the newly allocated line buffer
1207 Private
->LineBuffer
= NewLineBuffer
;
1209 if (GraphicsOutput
!= NULL
) {
1210 if (ModeData
->GopModeNumber
!= GraphicsOutput
->Mode
->Mode
) {
1212 // Either no graphics mode is currently set, or it is set to the wrong resolution, so set the new grapghics mode
1214 Status
= GraphicsOutput
->SetMode (GraphicsOutput
, ModeData
->GopModeNumber
);
1215 if (EFI_ERROR (Status
)) {
1217 // The mode set operation failed
1223 // The current graphics mode is correct, so simply clear the entire display
1225 Status
= GraphicsOutput
->Blt (
1234 ModeData
->GopHeight
,
1240 // Get the current UGA Draw mode information
1242 Status
= UgaDraw
->GetMode (
1244 &HorizontalResolution
,
1245 &VerticalResolution
,
1249 if (EFI_ERROR (Status
) || HorizontalResolution
!= ModeData
->GopWidth
|| VerticalResolution
!= ModeData
->GopHeight
) {
1251 // Either no graphics mode is currently set, or it is set to the wrong resolution, so set the new grapghics mode
1253 Status
= UgaDraw
->SetMode (
1256 ModeData
->GopHeight
,
1260 if (EFI_ERROR (Status
)) {
1262 // The mode set operation failed
1268 // The current graphics mode is correct, so simply clear the entire display
1270 Status
= UgaDraw
->Blt (
1272 (EFI_UGA_PIXEL
*) (UINTN
) &mEfiColors
[0],
1279 ModeData
->GopHeight
,
1286 // The new mode is valid, so commit the mode change
1288 This
->Mode
->Mode
= (INT32
) ModeNumber
;
1291 // Move the text cursor to the upper left hand corner of the displat and enable it
1293 This
->SetCursorPosition (This
, 0, 0);
1294 This
->EnableCursor (This
, TRUE
);
1296 Status
= EFI_SUCCESS
;
1299 gBS
->RestoreTPL (OldTpl
);
1305 GraphicsConsoleConOutSetAttribute (
1306 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
1310 Routine Description:
1312 Implements SIMPLE_TEXT_OUTPUT.SetAttribute().
1316 This - Indicates the calling context.
1318 Attrubute - The attribute to set. Only bit0..6 are valid, all other bits
1319 are undefined and must be zero.
1324 The requested attribute is set.
1327 The requested attribute cannot be set due to Graphics Console port error.
1330 The attribute requested is not defined by EFI spec.
1336 if ((Attribute
| 0xFF) != 0xFF) {
1337 return EFI_UNSUPPORTED
;
1340 if ((INT32
) Attribute
== This
->Mode
->Attribute
) {
1344 OldTpl
= gBS
->RaiseTPL (EFI_TPL_NOTIFY
);
1348 This
->Mode
->Attribute
= (INT32
) Attribute
;
1352 gBS
->RestoreTPL (OldTpl
);
1359 GraphicsConsoleConOutClearScreen (
1360 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
1363 Routine Description:
1365 Implements SIMPLE_TEXT_OUTPUT.ClearScreen().
1366 It clears the Graphics Console's display to the
1367 currently selected background color.
1372 This - Indicates the calling context.
1377 The operation completed successfully.
1380 The Graphics Console cannot be cleared due to Graphics Console device error.
1383 The Graphics Console is not in a valid text mode.
1388 GRAPHICS_CONSOLE_DEV
*Private
;
1389 GRAPHICS_CONSOLE_MODE_DATA
*ModeData
;
1390 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
1391 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
1392 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground
;
1393 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background
;
1396 OldTpl
= gBS
->RaiseTPL (EFI_TPL_NOTIFY
);
1398 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This
);
1399 GraphicsOutput
= Private
->GraphicsOutput
;
1400 UgaDraw
= Private
->UgaDraw
;
1401 ModeData
= &(Private
->ModeData
[This
->Mode
->Mode
]);
1403 GetTextColors (This
, &Foreground
, &Background
);
1404 if (GraphicsOutput
!= NULL
) {
1405 Status
= GraphicsOutput
->Blt (
1414 ModeData
->GopHeight
,
1418 Status
= UgaDraw
->Blt (
1420 (EFI_UGA_PIXEL
*) (UINTN
) &Background
,
1427 ModeData
->GopHeight
,
1432 This
->Mode
->CursorColumn
= 0;
1433 This
->Mode
->CursorRow
= 0;
1437 gBS
->RestoreTPL (OldTpl
);
1444 GraphicsConsoleConOutSetCursorPosition (
1445 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
1450 Routine Description:
1452 Implements SIMPLE_TEXT_OUTPUT.SetCursorPosition().
1456 This - Indicates the calling context.
1458 Column - The row to set cursor to.
1460 Row - The column to set cursor to.
1465 The operation completed successfully.
1468 The request fails due to Graphics Console device error.
1471 The Graphics Console is not in a valid text mode, or the cursor position
1472 is invalid for current mode.
1476 GRAPHICS_CONSOLE_DEV
*Private
;
1477 GRAPHICS_CONSOLE_MODE_DATA
*ModeData
;
1481 Status
= EFI_SUCCESS
;
1483 OldTpl
= gBS
->RaiseTPL (EFI_TPL_NOTIFY
);
1485 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This
);
1486 ModeData
= &(Private
->ModeData
[This
->Mode
->Mode
]);
1488 if ((Column
>= ModeData
->Columns
) || (Row
>= ModeData
->Rows
)) {
1489 Status
= EFI_UNSUPPORTED
;
1493 if (((INT32
) Column
== This
->Mode
->CursorColumn
) && ((INT32
) Row
== This
->Mode
->CursorRow
)) {
1494 Status
= EFI_SUCCESS
;
1500 This
->Mode
->CursorColumn
= (INT32
) Column
;
1501 This
->Mode
->CursorRow
= (INT32
) Row
;
1506 gBS
->RestoreTPL (OldTpl
);
1513 GraphicsConsoleConOutEnableCursor (
1514 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
1518 Routine Description:
1520 Implements SIMPLE_TEXT_OUTPUT.EnableCursor().
1521 In this driver, the cursor cannot be hidden.
1525 This - Indicates the calling context.
1527 Visible - If TRUE, the cursor is set to be visible,
1528 If FALSE, the cursor is set to be invisible.
1533 The request is valid.
1536 The Graphics Console does not support a hidden cursor.
1542 OldTpl
= gBS
->RaiseTPL (EFI_TPL_NOTIFY
);
1546 This
->Mode
->CursorVisible
= Visible
;
1550 gBS
->RestoreTPL (OldTpl
);
1557 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
1558 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Foreground
,
1559 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Background
1564 Attribute
= This
->Mode
->Attribute
& 0x7F;
1566 *Foreground
= mEfiColors
[Attribute
& 0x0f];
1567 *Background
= mEfiColors
[Attribute
>> 4];
1574 DrawUnicodeWeightAtCursorN (
1575 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
1576 IN CHAR16
*UnicodeWeight
,
1580 GRAPHICS_CONSOLE_DEV
*Private
;
1582 EFI_STATUS ReturnStatus
;
1584 GLYPH_UNION GlyphData
;
1587 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
1588 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
1589 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground
;
1590 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background
;
1597 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This
);
1599 ReturnStatus
= EFI_SUCCESS
;
1603 GetTextColors (This
, &Foreground
, &Background
);
1607 while (Index
< Count
) {
1608 if (This
->Mode
->Attribute
& EFI_WIDE_ATTRIBUTE
) {
1609 GlyphStatus
= WIDE_CHAR
;
1611 GlyphStatus
= NARROW_CHAR
;
1614 Status
= mHii
->GetGlyph (
1622 if (EFI_ERROR (Status
)) {
1623 ReturnStatus
= Status
;
1628 CopyMem (&GlyphData
, Glyph
, sizeof (GLYPH_UNION
));
1632 // We are creating the second half of the wide character's BLT buffer
1634 if (GlyphWidth
== 0x10 && Counts
== 1) {
1635 CopyMem (&GlyphData
.NarrowGlyph
.GlyphCol1
, &Glyph
->WideGlyph
.GlyphCol2
, sizeof (Glyph
->WideGlyph
.GlyphCol2
));
1640 if (GlyphWidth
== 0x10) {
1643 (UINT8
*) &GlyphData
,
1649 &Private
->LineBuffer
[ArrayIndex
* GLYPH_WIDTH
]
1654 (UINT8
*) &GlyphData
,
1660 &Private
->LineBuffer
[ArrayIndex
* GLYPH_WIDTH
]
1666 } while (Counts
< 2 && GlyphWidth
== 0x10);
1670 // If we are printing Wide characters, treat the BLT as if it is twice as many characters
1672 if (GlyphWidth
== 0x10) {
1676 // Blt a character to the screen
1678 GlyphX
= This
->Mode
->CursorColumn
* GLYPH_WIDTH
;
1679 GlyphY
= This
->Mode
->CursorRow
* GLYPH_HEIGHT
;
1680 GraphicsOutput
= Private
->GraphicsOutput
;
1681 UgaDraw
= Private
->UgaDraw
;
1682 if (GraphicsOutput
!= NULL
) {
1683 GraphicsOutput
->Blt (
1685 Private
->LineBuffer
,
1686 EfiBltBufferToVideo
,
1689 GlyphX
+ Private
->ModeData
[This
->Mode
->Mode
].DeltaX
,
1690 GlyphY
+ Private
->ModeData
[This
->Mode
->Mode
].DeltaY
,
1691 GLYPH_WIDTH
* Count
,
1693 GLYPH_WIDTH
* Count
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
1698 (EFI_UGA_PIXEL
*) (UINTN
) Private
->LineBuffer
,
1699 EfiUgaBltBufferToVideo
,
1702 GlyphX
+ Private
->ModeData
[This
->Mode
->Mode
].DeltaX
,
1703 GlyphY
+ Private
->ModeData
[This
->Mode
->Mode
].DeltaY
,
1704 GLYPH_WIDTH
* Count
,
1706 GLYPH_WIDTH
* Count
* sizeof (EFI_UGA_PIXEL
)
1710 return ReturnStatus
;
1716 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
1719 GRAPHICS_CONSOLE_DEV
*Private
;
1720 EFI_SIMPLE_TEXT_OUTPUT_MODE
*CurrentMode
;
1723 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
1724 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
1725 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Foreground
;
1726 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Background
;
1727 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION BltChar
[GLYPH_HEIGHT
][GLYPH_WIDTH
];
1731 CurrentMode
= This
->Mode
;
1733 if (!CurrentMode
->CursorVisible
) {
1737 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This
);
1738 GraphicsOutput
= Private
->GraphicsOutput
;
1739 UgaDraw
= Private
->UgaDraw
;
1742 // BUGBUG - we need to think about what to do with wide and narrow character deletions.
1745 // Blt a character to the screen
1747 GlyphX
= (CurrentMode
->CursorColumn
* GLYPH_WIDTH
) + Private
->ModeData
[CurrentMode
->Mode
].DeltaX
;
1748 GlyphY
= (CurrentMode
->CursorRow
* GLYPH_HEIGHT
) + Private
->ModeData
[CurrentMode
->Mode
].DeltaY
;
1749 if (GraphicsOutput
!= NULL
) {
1750 GraphicsOutput
->Blt (
1752 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) BltChar
,
1753 EfiBltVideoToBltBuffer
,
1760 GLYPH_WIDTH
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
1765 (EFI_UGA_PIXEL
*) (UINTN
) BltChar
,
1766 EfiUgaVideoToBltBuffer
,
1773 GLYPH_WIDTH
* sizeof (EFI_UGA_PIXEL
)
1777 GetTextColors (This
, &Foreground
.Pixel
, &Background
.Pixel
);
1780 // Convert Monochrome bitmap of the Glyph to BltBuffer structure
1782 for (Y
= 0; Y
< GLYPH_HEIGHT
; Y
++) {
1783 for (X
= 0; X
< GLYPH_WIDTH
; X
++) {
1784 if ((mCursorGlyph
.GlyphCol1
[Y
] & (1 << X
)) != 0) {
1785 BltChar
[Y
][GLYPH_WIDTH
- X
- 1].Raw
^= Foreground
.Raw
;
1790 if (GraphicsOutput
!= NULL
) {
1791 GraphicsOutput
->Blt (
1793 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) BltChar
,
1794 EfiBltBufferToVideo
,
1801 GLYPH_WIDTH
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
1806 (EFI_UGA_PIXEL
*) (UINTN
) BltChar
,
1807 EfiUgaBltBufferToVideo
,
1814 GLYPH_WIDTH
* sizeof (EFI_UGA_PIXEL
)