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.
21 // Include common header file for this module.
23 #include "CommonHeader.h"
25 #include "GraphicsConsole.h"
30 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
31 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Foreground
,
32 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Background
37 DrawUnicodeWeightAtCursorN (
38 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
39 IN CHAR16
*UnicodeWeight
,
46 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
52 GRAPHICS_CONSOLE_DEV mGraphicsConsoleDevTemplate
= {
53 GRAPHICS_CONSOLE_DEV_SIGNATURE
,
54 (EFI_GRAPHICS_OUTPUT_PROTOCOL
*) NULL
,
55 (EFI_UGA_DRAW_PROTOCOL
*) NULL
,
57 GraphicsConsoleConOutReset
,
58 GraphicsConsoleConOutOutputString
,
59 GraphicsConsoleConOutTestString
,
60 GraphicsConsoleConOutQueryMode
,
61 GraphicsConsoleConOutSetMode
,
62 GraphicsConsoleConOutSetAttribute
,
63 GraphicsConsoleConOutClearScreen
,
64 GraphicsConsoleConOutSetCursorPosition
,
65 GraphicsConsoleConOutEnableCursor
,
66 (EFI_SIMPLE_TEXT_OUTPUT_MODE
*) NULL
71 EFI_TEXT_ATTR(EFI_LIGHTGRAY
, EFI_BLACK
),
77 { 80, 25, 0, 0, 0, 0 }, // Mode 0
78 { 80, 50, 0, 0, 0, 0 }, // Mode 1
79 { 0, 0, 0, 0, 0, 0 } // Mode 2
81 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) NULL
,
85 EFI_HII_PROTOCOL
*mHii
;
87 static CHAR16 mCrLfString
[3] = { CHAR_CARRIAGE_RETURN
, CHAR_LINEFEED
, CHAR_NULL
};
89 static EFI_GRAPHICS_OUTPUT_BLT_PIXEL mEfiColors
[16] = {
93 {0x00, 0x00, 0x00, 0x00}, // BLACK
94 {0x98, 0x00, 0x00, 0x00}, // BLUE
95 {0x00, 0x98, 0x00, 0x00}, // GREEN
96 {0x98, 0x98, 0x00, 0x00}, // CYAN
97 {0x00, 0x00, 0x98, 0x00}, // RED
98 {0x98, 0x00, 0x98, 0x00}, // MAGENTA
99 {0x00, 0x98, 0x98, 0x00}, // BROWN
100 {0x98, 0x98, 0x98, 0x00}, // LIGHTGRAY
101 {0x30, 0x30, 0x30, 0x00}, // DARKGRAY - BRIGHT BLACK
102 {0xff, 0x00, 0x00, 0x00}, // LIGHTBLUE - ?
103 {0x00, 0xff, 0x00, 0x00}, // LIGHTGREEN - ?
104 {0xff, 0xff, 0x00, 0x00}, // LIGHTCYAN
105 {0x00, 0x00, 0xff, 0x00}, // LIGHTRED
106 {0xff, 0x00, 0xff, 0x00}, // LIGHTMAGENTA
107 {0x00, 0xff, 0xff, 0x00}, // LIGHTBROWN
108 {0xff, 0xff, 0xff, 0x00} // WHITE
111 static EFI_NARROW_GLYPH mCursorGlyph
= {
114 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF }
117 EFI_DRIVER_BINDING_PROTOCOL gGraphicsConsoleDriverBinding
= {
118 GraphicsConsoleControllerDriverSupported
,
119 GraphicsConsoleControllerDriverStart
,
120 GraphicsConsoleControllerDriverStop
,
128 GraphicsConsoleControllerDriverSupported (
129 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
130 IN EFI_HANDLE Controller
,
131 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
135 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
136 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
137 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
141 // Open the IO Abstraction(s) needed to perform the supported test
143 Status
= gBS
->OpenProtocol (
145 &gEfiGraphicsOutputProtocolGuid
,
146 (VOID
**) &GraphicsOutput
,
147 This
->DriverBindingHandle
,
149 EFI_OPEN_PROTOCOL_BY_DRIVER
152 if (EFI_ERROR (Status
)) {
153 GraphicsOutput
= NULL
;
155 // Open Graphics Output Protocol failed, try to open UGA Draw Protocol
157 Status
= gBS
->OpenProtocol (
159 &gEfiUgaDrawProtocolGuid
,
161 This
->DriverBindingHandle
,
163 EFI_OPEN_PROTOCOL_BY_DRIVER
165 if (EFI_ERROR (Status
)) {
171 // We need to ensure that we do not layer on top of a virtual handle.
172 // We need to ensure that the handles produced by the conspliter do not
175 Status
= gBS
->OpenProtocol (
177 &gEfiDevicePathProtocolGuid
,
178 (VOID
**) &DevicePath
,
179 This
->DriverBindingHandle
,
181 EFI_OPEN_PROTOCOL_BY_DRIVER
183 if (!EFI_ERROR (Status
)) {
186 &gEfiDevicePathProtocolGuid
,
187 This
->DriverBindingHandle
,
194 // Does Hii Exist? If not, we aren't ready to run
196 Status
= EfiLocateHiiProtocol ();
199 // Close the I/O Abstraction(s) used to perform the supported test
202 if (GraphicsOutput
!= NULL
) {
205 &gEfiGraphicsOutputProtocolGuid
,
206 This
->DriverBindingHandle
,
212 &gEfiUgaDrawProtocolGuid
,
213 This
->DriverBindingHandle
,
222 GraphicsConsoleControllerDriverStart (
223 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
224 IN EFI_HANDLE Controller
,
225 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
231 Start the controller.
235 This - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
236 Controller - The handle of the controller to start.
237 RemainingDevicePath - A pointer to the remaining portion of a devcie path.
241 EFI_SUCCESS - Return successfully.
242 EFI_OUT_OF_RESOURCES - Out of resources.
247 GRAPHICS_CONSOLE_DEV
*Private
;
248 EFI_HII_PACKAGES
*Package
;
249 EFI_HII_FONT_PACK
*FontPack
;
250 UINTN NarrowFontSize
;
251 UINT32 HorizontalResolution
;
252 UINT32 VerticalResolution
;
261 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
266 // Initialize the Graphics Console device instance
268 Private
= AllocateCopyPool (
269 sizeof (GRAPHICS_CONSOLE_DEV
),
270 &mGraphicsConsoleDevTemplate
272 if (Private
== NULL
) {
273 return EFI_OUT_OF_RESOURCES
;
276 Private
->SimpleTextOutput
.Mode
= &(Private
->SimpleTextOutputMode
);
278 Status
= gBS
->OpenProtocol (
280 &gEfiGraphicsOutputProtocolGuid
,
281 (VOID
**) &Private
->GraphicsOutput
,
282 This
->DriverBindingHandle
,
284 EFI_OPEN_PROTOCOL_BY_DRIVER
286 if (EFI_ERROR(Status
)) {
287 Private
->GraphicsOutput
= NULL
;
289 Status
= gBS
->OpenProtocol (
291 &gEfiUgaDrawProtocolGuid
,
292 (VOID
**) &Private
->UgaDraw
,
293 This
->DriverBindingHandle
,
295 EFI_OPEN_PROTOCOL_BY_DRIVER
297 if (EFI_ERROR (Status
)) {
303 // Get the HII protocol. If Supported() succeeds, do we really
304 // need to get HII protocol again?
306 Status
= EfiLocateHiiProtocol ();
307 if (EFI_ERROR (Status
)) {
311 NarrowFontSize
= ReturnNarrowFontSize ();
313 FontPack
= AllocateZeroPool (sizeof (EFI_HII_FONT_PACK
) + NarrowFontSize
);
316 FontPack
->Header
.Length
= (UINT32
) (sizeof (EFI_HII_FONT_PACK
) + NarrowFontSize
);
317 FontPack
->Header
.Type
= EFI_HII_FONT
;
318 FontPack
->NumberOfNarrowGlyphs
= (UINT16
) (NarrowFontSize
/ sizeof (EFI_NARROW_GLYPH
));
320 Location
= (UINT8
*) (&FontPack
->NumberOfWideGlyphs
+ sizeof (UINT8
));
321 CopyMem (Location
, UsStdNarrowGlyphData
, NarrowFontSize
);
324 // Register our Fonts into the global database
326 Package
= PreparePackages (1, NULL
, FontPack
);
327 mHii
->NewPack (mHii
, Package
, &(Private
->HiiHandle
));
331 // Free the font database
336 // If the current mode information can not be retrieved, then attemp to set the default mode
337 // of 800x600, 32 bit colot, 60 Hz refresh.
339 HorizontalResolution
= 800;
340 VerticalResolution
= 600;
342 if (Private
->GraphicsOutput
!= NULL
) {
344 // The console is build on top of Graphics Output Protocol, find the mode number for 800x600
346 for (ModeNumber
= 0; ModeNumber
< Private
->GraphicsOutput
->Mode
->MaxMode
; ModeNumber
++) {
347 Status
= Private
->GraphicsOutput
->QueryMode (
348 Private
->GraphicsOutput
,
353 if (!EFI_ERROR (Status
)) {
354 if ((Info
->HorizontalResolution
== 800) &&
355 (Info
->VerticalResolution
== 600)) {
356 Status
= Private
->GraphicsOutput
->SetMode (Private
->GraphicsOutput
, ModeNumber
);
357 if (!EFI_ERROR (Status
)) {
366 if (EFI_ERROR (Status
) || (ModeNumber
== Private
->GraphicsOutput
->Mode
->MaxMode
)) {
368 // Set default mode failed or device don't support default mode, then get the current mode information
370 HorizontalResolution
= Private
->GraphicsOutput
->Mode
->Info
->HorizontalResolution
;
371 VerticalResolution
= Private
->GraphicsOutput
->Mode
->Info
->VerticalResolution
;
372 ModeNumber
= Private
->GraphicsOutput
->Mode
->Mode
;
376 // The console is build on top of UGA Draw Protocol
380 Status
= Private
->UgaDraw
->SetMode (
382 HorizontalResolution
,
387 if (EFI_ERROR (Status
)) {
389 // Get the current mode information from the UGA Draw Protocol
391 Status
= Private
->UgaDraw
->GetMode (
393 &HorizontalResolution
,
398 if (EFI_ERROR (Status
)) {
405 // Compute the maximum number of text Rows and Columns that this current graphics mode can support
407 Columns
= HorizontalResolution
/ GLYPH_WIDTH
;
408 Rows
= VerticalResolution
/ GLYPH_HEIGHT
;
411 // See if the mode is too small to support the required 80x25 text mode
413 if (Columns
< 80 || Rows
< 25) {
417 // Add Mode #0 that must be 80x25
420 Private
->ModeData
[MaxMode
].GopWidth
= HorizontalResolution
;
421 Private
->ModeData
[MaxMode
].GopHeight
= VerticalResolution
;
422 Private
->ModeData
[MaxMode
].GopModeNumber
= ModeNumber
;
423 Private
->ModeData
[MaxMode
].DeltaX
= (HorizontalResolution
- (80 * GLYPH_WIDTH
)) >> 1;
424 Private
->ModeData
[MaxMode
].DeltaY
= (VerticalResolution
- (25 * GLYPH_HEIGHT
)) >> 1;
428 // If it is possible to support Mode #1 - 80x50, than add it as an active mode
431 Private
->ModeData
[MaxMode
].GopWidth
= HorizontalResolution
;
432 Private
->ModeData
[MaxMode
].GopHeight
= VerticalResolution
;
433 Private
->ModeData
[MaxMode
].GopModeNumber
= ModeNumber
;
434 Private
->ModeData
[MaxMode
].DeltaX
= (HorizontalResolution
- (80 * GLYPH_WIDTH
)) >> 1;
435 Private
->ModeData
[MaxMode
].DeltaY
= (VerticalResolution
- (50 * GLYPH_HEIGHT
)) >> 1;
439 // If the graphics mode is 800x600, than add a text mode that uses the entire display
441 if (HorizontalResolution
== 800 && VerticalResolution
== 600) {
444 Private
->ModeData
[MaxMode
].Columns
= 0;
445 Private
->ModeData
[MaxMode
].Rows
= 0;
446 Private
->ModeData
[MaxMode
].GopWidth
= 800;
447 Private
->ModeData
[MaxMode
].GopHeight
= 600;
448 Private
->ModeData
[MaxMode
].GopModeNumber
= ModeNumber
;
449 Private
->ModeData
[MaxMode
].DeltaX
= 0;
450 Private
->ModeData
[MaxMode
].DeltaY
= 0;
454 Private
->ModeData
[MaxMode
].Columns
= 800 / GLYPH_WIDTH
;
455 Private
->ModeData
[MaxMode
].Rows
= 600 / GLYPH_HEIGHT
;
456 Private
->ModeData
[MaxMode
].GopWidth
= 800;
457 Private
->ModeData
[MaxMode
].GopHeight
= 600;
458 Private
->ModeData
[MaxMode
].GopModeNumber
= ModeNumber
;
459 Private
->ModeData
[MaxMode
].DeltaX
= (800 % GLYPH_WIDTH
) >> 1;
460 Private
->ModeData
[MaxMode
].DeltaY
= (600 % GLYPH_HEIGHT
) >> 1;
464 // Update the maximum number of modes
466 Private
->SimpleTextOutputMode
.MaxMode
= (INT32
) MaxMode
;
469 // Determine the number of text modes that this protocol can support
471 Status
= GraphicsConsoleConOutSetMode (&Private
->SimpleTextOutput
, 0);
472 if (EFI_ERROR (Status
)) {
477 GraphicsConsoleConOutOutputString (&Private
->SimpleTextOutput
, (CHAR16
*)L
"Graphics Console Started\n\r");
481 // Install protocol interfaces for the Graphics Console device.
483 Status
= gBS
->InstallMultipleProtocolInterfaces (
485 &gEfiSimpleTextOutProtocolGuid
,
486 &Private
->SimpleTextOutput
,
491 if (EFI_ERROR (Status
)) {
493 // Close the GOP or UGA IO Protocol
495 if (Private
->GraphicsOutput
!= NULL
) {
498 &gEfiGraphicsOutputProtocolGuid
,
499 This
->DriverBindingHandle
,
505 &gEfiUgaDrawProtocolGuid
,
506 This
->DriverBindingHandle
,
514 if (Private
!= NULL
) {
515 if (Private
->LineBuffer
!= NULL
) {
516 FreePool (Private
->LineBuffer
);
527 GraphicsConsoleControllerDriverStop (
528 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
529 IN EFI_HANDLE Controller
,
530 IN UINTN NumberOfChildren
,
531 IN EFI_HANDLE
*ChildHandleBuffer
535 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*SimpleTextOutput
;
536 GRAPHICS_CONSOLE_DEV
*Private
;
538 Status
= gBS
->OpenProtocol (
540 &gEfiSimpleTextOutProtocolGuid
,
541 (VOID
**) &SimpleTextOutput
,
542 This
->DriverBindingHandle
,
544 EFI_OPEN_PROTOCOL_GET_PROTOCOL
546 if (EFI_ERROR (Status
)) {
547 return EFI_NOT_STARTED
;
550 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (SimpleTextOutput
);
552 Status
= gBS
->UninstallProtocolInterface (
554 &gEfiSimpleTextOutProtocolGuid
,
555 &Private
->SimpleTextOutput
558 if (!EFI_ERROR (Status
)) {
560 // Close the GOP or UGA IO Protocol
562 if (Private
->GraphicsOutput
!= NULL
) {
565 &gEfiGraphicsOutputProtocolGuid
,
566 This
->DriverBindingHandle
,
572 &gEfiUgaDrawProtocolGuid
,
573 This
->DriverBindingHandle
,
579 // Remove the font pack
581 mHii
->RemovePack (mHii
, Private
->HiiHandle
);
584 // Free our instance data
586 if (Private
!= NULL
) {
587 FreePool (Private
->LineBuffer
);
596 EfiLocateHiiProtocol (
602 Find if the HII protocol is available. If yes, locate the HII protocol
615 // There should only be one - so buffer size is this
617 Size
= sizeof (EFI_HANDLE
);
619 Status
= gBS
->LocateHandle (
621 &gEfiHiiProtocolGuid
,
627 if (EFI_ERROR (Status
)) {
631 Status
= gBS
->HandleProtocol (
633 &gEfiHiiProtocolGuid
,
640 // Body of the STO functions
644 GraphicsConsoleConOutReset (
645 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
646 IN BOOLEAN ExtendedVerification
651 Implements SIMPLE_TEXT_OUTPUT.Reset().
652 If ExtendeVerification is TRUE, then perform dependent Graphics Console
653 device reset, and set display mode to mode 0.
654 If ExtendedVerification is FALSE, only set display mode to mode 0.
658 This - Indicates the calling context.
660 ExtendedVerification - Indicates that the driver may perform a more exhaustive
661 verification operation of the device during reset.
666 The reset operation succeeds.
669 The Graphics Console is not functioning correctly
673 This
->SetAttribute (This
, EFI_TEXT_ATTR (This
->Mode
->Attribute
& 0x0F, EFI_BACKGROUND_BLACK
));
674 return This
->SetMode (This
, 0);
679 GraphicsConsoleConOutOutputString (
680 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
686 Implements SIMPLE_TEXT_OUTPUT.OutputString().
687 The Unicode string will be converted to Glyphs and will be
688 sent to the Graphics Console.
693 This - Indicates the calling context.
695 WString - The Null-terminated Unicode string to be displayed on
696 the Graphics Console.
701 The string is output successfully.
704 The Graphics Console failed to send the string out.
706 EFI_WARN_UNKNOWN_GLYPH
707 Indicates that some of the characters in the Unicode string could not
708 be rendered and are skipped.
712 GRAPHICS_CONSOLE_DEV
*Private
;
713 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
714 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
723 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground
;
724 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background
;
729 INT32 OriginAttribute
;
731 CHAR16 SpaceStr
[] = { NARROW_CHAR
, ' ', 0 };
733 Status
= EFI_SUCCESS
;
735 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
739 Mode
= This
->Mode
->Mode
;
740 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This
);
741 GraphicsOutput
= Private
->GraphicsOutput
;
742 UgaDraw
= Private
->UgaDraw
;
744 MaxColumn
= Private
->ModeData
[Mode
].Columns
;
745 MaxRow
= Private
->ModeData
[Mode
].Rows
;
746 DeltaX
= Private
->ModeData
[Mode
].DeltaX
;
747 DeltaY
= Private
->ModeData
[Mode
].DeltaY
;
748 Width
= MaxColumn
* GLYPH_WIDTH
;
749 Height
= (MaxRow
- 1) * GLYPH_HEIGHT
;
750 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
753 // The Attributes won't change when during the time OutputString is called
755 GetTextColors (This
, &Foreground
, &Background
);
764 OriginAttribute
= This
->Mode
->Attribute
;
768 if (*WString
== CHAR_BACKSPACE
) {
770 // If the cursor is at the left edge of the display, then move the cursor
773 if (This
->Mode
->CursorColumn
== 0 && This
->Mode
->CursorRow
> 0) {
774 This
->Mode
->CursorRow
--;
775 This
->Mode
->CursorColumn
= (INT32
) (MaxColumn
- 1);
776 This
->OutputString (This
, SpaceStr
);
778 This
->Mode
->CursorRow
--;
779 This
->Mode
->CursorColumn
= (INT32
) (MaxColumn
- 1);
780 } else if (This
->Mode
->CursorColumn
> 0) {
782 // If the cursor is not at the left edge of the display, then move the cursor
785 This
->Mode
->CursorColumn
--;
786 This
->OutputString (This
, SpaceStr
);
788 This
->Mode
->CursorColumn
--;
793 } else if (*WString
== CHAR_LINEFEED
) {
795 // If the cursor is at the bottom of the display, then scroll the display one
796 // row, and do not update the cursor position. Otherwise, move the cursor
799 if (This
->Mode
->CursorRow
== (INT32
) (MaxRow
- 1)) {
800 if (GraphicsOutput
!= NULL
) {
802 // Scroll Screen Up One Row
804 GraphicsOutput
->Blt (
809 DeltaY
+ GLYPH_HEIGHT
,
818 // Print Blank Line at last line
820 GraphicsOutput
->Blt (
834 // Scroll Screen Up One Row
841 DeltaY
+ GLYPH_HEIGHT
,
850 // Print Blank Line at last line
854 (EFI_UGA_PIXEL
*) (UINTN
) &Background
,
866 This
->Mode
->CursorRow
++;
871 } else if (*WString
== CHAR_CARRIAGE_RETURN
) {
873 // Move the cursor to the beginning of the current row.
875 This
->Mode
->CursorColumn
= 0;
878 } else if (*WString
== WIDE_CHAR
) {
880 This
->Mode
->Attribute
|= EFI_WIDE_ATTRIBUTE
;
883 } else if (*WString
== NARROW_CHAR
) {
885 This
->Mode
->Attribute
&= (~ (UINT32
) EFI_WIDE_ATTRIBUTE
);
890 // Print the character at the current cursor position and move the cursor
891 // right one column. If this moves the cursor past the right edge of the
892 // display, then the line should wrap to the beginning of the next line. This
893 // is equivalent to inserting a CR and an LF. Note that if the cursor is at the
894 // bottom of the display, and the line wraps, then the display will be scrolled
896 // If wide char is going to be displayed, need to display one character at a time
897 // Or, need to know the display length of a certain string.
899 // Index is used to determine how many character width units (wide = 2, narrow = 1)
900 // Count is used to determine how many characters are used regardless of their attributes
902 for (Count
= 0, Index
= 0; (This
->Mode
->CursorColumn
+ Index
) < MaxColumn
; Count
++, Index
++) {
903 if (WString
[Count
] == CHAR_NULL
) {
907 if (WString
[Count
] == CHAR_BACKSPACE
) {
911 if (WString
[Count
] == CHAR_LINEFEED
) {
915 if (WString
[Count
] == CHAR_CARRIAGE_RETURN
) {
919 if (WString
[Count
] == WIDE_CHAR
) {
923 if (WString
[Count
] == NARROW_CHAR
) {
927 // Is the wide attribute on?
929 if (This
->Mode
->Attribute
& EFI_WIDE_ATTRIBUTE
) {
931 // If wide, add one more width unit than normal since we are going to increment at the end of the for loop
935 // This is the end-case where if we are at column 79 and about to print a wide character
936 // We should prevent this from happening because we will wrap inappropriately. We should
937 // not print this character until the next line.
939 if ((This
->Mode
->CursorColumn
+ Index
+ 1) > MaxColumn
) {
946 Status
= DrawUnicodeWeightAtCursorN (This
, WString
, Count
);
947 if (EFI_ERROR (Status
)) {
951 // At the end of line, output carriage return and line feed
954 This
->Mode
->CursorColumn
+= (INT32
) Index
;
955 if (This
->Mode
->CursorColumn
> (INT32
) MaxColumn
) {
956 This
->Mode
->CursorColumn
-= 2;
957 This
->OutputString (This
, SpaceStr
);
960 if (This
->Mode
->CursorColumn
>= (INT32
) MaxColumn
) {
962 This
->OutputString (This
, mCrLfString
);
968 This
->Mode
->Attribute
= OriginAttribute
;
973 Status
= EFI_WARN_UNKNOWN_GLYPH
;
976 gBS
->RestoreTPL (OldTpl
);
983 GraphicsConsoleConOutTestString (
984 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
990 Implements SIMPLE_TEXT_OUTPUT.TestString().
991 If one of the characters in the *Wstring is
992 neither valid valid Unicode drawing characters,
993 not ASCII code, then this function will return
999 This - Indicates the calling context.
1001 WString - The Null-terminated Unicode string to be tested.
1006 The Graphics Console is capable of rendering the output string.
1009 Some of the characters in the Unicode string cannot be rendered.
1022 while (WString
[Count
]) {
1023 Status
= mHii
->GetGlyph (
1032 if (EFI_ERROR (Status
)) {
1033 return EFI_UNSUPPORTED
;
1042 GraphicsConsoleConOutQueryMode (
1043 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
1044 IN UINTN ModeNumber
,
1049 Routine Description:
1051 Implements SIMPLE_TEXT_OUTPUT.QueryMode().
1052 It returnes information for an available text mode
1053 that the Graphics Console supports.
1054 In this driver,we only support text mode 80x25, which is
1060 This - Indicates the calling context.
1062 ModeNumber - The mode number to return information on.
1064 Columns - The returned columns of the requested mode.
1066 Rows - The returned rows of the requested mode.
1071 The requested mode information is returned.
1074 The mode number is not valid.
1078 GRAPHICS_CONSOLE_DEV
*Private
;
1082 if (ModeNumber
>= (UINTN
) This
->Mode
->MaxMode
) {
1083 return EFI_UNSUPPORTED
;
1086 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1087 Status
= EFI_SUCCESS
;
1089 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This
);
1091 *Columns
= Private
->ModeData
[ModeNumber
].Columns
;
1092 *Rows
= Private
->ModeData
[ModeNumber
].Rows
;
1094 if (*Columns
<= 0 && *Rows
<= 0) {
1095 Status
= EFI_UNSUPPORTED
;
1101 gBS
->RestoreTPL (OldTpl
);
1107 GraphicsConsoleConOutSetMode (
1108 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
1112 Routine Description:
1114 Implements SIMPLE_TEXT_OUTPUT.SetMode().
1115 Set the Graphics Console to a specified mode.
1116 In this driver, we only support mode 0.
1120 This - Indicates the calling context.
1122 ModeNumber - The text mode to set.
1127 The requested text mode is set.
1130 The requested text mode cannot be set because of Graphics Console device error.
1133 The text mode number is not valid.
1138 GRAPHICS_CONSOLE_DEV
*Private
;
1139 GRAPHICS_CONSOLE_MODE_DATA
*ModeData
;
1140 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*NewLineBuffer
;
1141 UINT32 HorizontalResolution
;
1142 UINT32 VerticalResolution
;
1143 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
1144 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
1149 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1151 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This
);
1152 GraphicsOutput
= Private
->GraphicsOutput
;
1153 UgaDraw
= Private
->UgaDraw
;
1154 ModeData
= &(Private
->ModeData
[ModeNumber
]);
1156 if (ModeData
->Columns
<= 0 && ModeData
->Rows
<= 0) {
1157 Status
= EFI_UNSUPPORTED
;
1162 // Make sure the requested mode number is supported
1164 if (ModeNumber
>= (UINTN
) This
->Mode
->MaxMode
) {
1165 Status
= EFI_UNSUPPORTED
;
1169 if (ModeData
->Columns
<= 0 && ModeData
->Rows
<= 0) {
1170 Status
= EFI_UNSUPPORTED
;
1174 // Attempt to allocate a line buffer for the requested mode number
1176 NewLineBuffer
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * ModeData
->Columns
* GLYPH_WIDTH
* GLYPH_HEIGHT
);
1178 if (NewLineBuffer
== NULL
) {
1180 // The new line buffer could not be allocated, so return an error.
1181 // No changes to the state of the current console have been made, so the current console is still valid
1183 Status
= EFI_OUT_OF_RESOURCES
;
1187 // If the mode has been set at least one other time, then LineBuffer will not be NULL
1189 if (Private
->LineBuffer
!= NULL
) {
1191 // Clear the current text window on the current graphics console
1193 This
->ClearScreen (This
);
1196 // If the new mode is the same as the old mode, then just return EFI_SUCCESS
1198 if ((INT32
) ModeNumber
== This
->Mode
->Mode
) {
1199 FreePool (NewLineBuffer
);
1200 Status
= EFI_SUCCESS
;
1204 // Otherwise, the size of the text console and/or the UGA mode will be changed,
1205 // so turn off the cursor, and free the LineBuffer for the current mode
1207 This
->EnableCursor (This
, FALSE
);
1209 FreePool (Private
->LineBuffer
);
1212 // Assign the current line buffer to the newly allocated line buffer
1214 Private
->LineBuffer
= NewLineBuffer
;
1216 if (GraphicsOutput
!= NULL
) {
1217 if (ModeData
->GopModeNumber
!= GraphicsOutput
->Mode
->Mode
) {
1219 // Either no graphics mode is currently set, or it is set to the wrong resolution, so set the new grapghics mode
1221 Status
= GraphicsOutput
->SetMode (GraphicsOutput
, ModeData
->GopModeNumber
);
1222 if (EFI_ERROR (Status
)) {
1224 // The mode set operation failed
1230 // The current graphics mode is correct, so simply clear the entire display
1232 Status
= GraphicsOutput
->Blt (
1241 ModeData
->GopHeight
,
1247 // Get the current UGA Draw mode information
1249 Status
= UgaDraw
->GetMode (
1251 &HorizontalResolution
,
1252 &VerticalResolution
,
1256 if (EFI_ERROR (Status
) || HorizontalResolution
!= ModeData
->GopWidth
|| VerticalResolution
!= ModeData
->GopHeight
) {
1258 // Either no graphics mode is currently set, or it is set to the wrong resolution, so set the new grapghics mode
1260 Status
= UgaDraw
->SetMode (
1263 ModeData
->GopHeight
,
1267 if (EFI_ERROR (Status
)) {
1269 // The mode set operation failed
1275 // The current graphics mode is correct, so simply clear the entire display
1277 Status
= UgaDraw
->Blt (
1279 (EFI_UGA_PIXEL
*) (UINTN
) &mEfiColors
[0],
1286 ModeData
->GopHeight
,
1293 // The new mode is valid, so commit the mode change
1295 This
->Mode
->Mode
= (INT32
) ModeNumber
;
1298 // Move the text cursor to the upper left hand corner of the displat and enable it
1300 This
->SetCursorPosition (This
, 0, 0);
1301 This
->EnableCursor (This
, TRUE
);
1303 Status
= EFI_SUCCESS
;
1306 gBS
->RestoreTPL (OldTpl
);
1312 GraphicsConsoleConOutSetAttribute (
1313 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
1317 Routine Description:
1319 Implements SIMPLE_TEXT_OUTPUT.SetAttribute().
1323 This - Indicates the calling context.
1325 Attrubute - The attribute to set. Only bit0..6 are valid, all other bits
1326 are undefined and must be zero.
1331 The requested attribute is set.
1334 The requested attribute cannot be set due to Graphics Console port error.
1337 The attribute requested is not defined by EFI spec.
1343 if ((Attribute
| 0xFF) != 0xFF) {
1344 return EFI_UNSUPPORTED
;
1347 if ((INT32
) Attribute
== This
->Mode
->Attribute
) {
1351 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1355 This
->Mode
->Attribute
= (INT32
) Attribute
;
1359 gBS
->RestoreTPL (OldTpl
);
1366 GraphicsConsoleConOutClearScreen (
1367 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
1370 Routine Description:
1372 Implements SIMPLE_TEXT_OUTPUT.ClearScreen().
1373 It clears the Graphics Console's display to the
1374 currently selected background color.
1379 This - Indicates the calling context.
1384 The operation completed successfully.
1387 The Graphics Console cannot be cleared due to Graphics Console device error.
1390 The Graphics Console is not in a valid text mode.
1395 GRAPHICS_CONSOLE_DEV
*Private
;
1396 GRAPHICS_CONSOLE_MODE_DATA
*ModeData
;
1397 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
1398 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
1399 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground
;
1400 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background
;
1403 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1405 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This
);
1406 GraphicsOutput
= Private
->GraphicsOutput
;
1407 UgaDraw
= Private
->UgaDraw
;
1408 ModeData
= &(Private
->ModeData
[This
->Mode
->Mode
]);
1410 GetTextColors (This
, &Foreground
, &Background
);
1411 if (GraphicsOutput
!= NULL
) {
1412 Status
= GraphicsOutput
->Blt (
1421 ModeData
->GopHeight
,
1425 Status
= UgaDraw
->Blt (
1427 (EFI_UGA_PIXEL
*) (UINTN
) &Background
,
1434 ModeData
->GopHeight
,
1439 This
->Mode
->CursorColumn
= 0;
1440 This
->Mode
->CursorRow
= 0;
1444 gBS
->RestoreTPL (OldTpl
);
1451 GraphicsConsoleConOutSetCursorPosition (
1452 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
1457 Routine Description:
1459 Implements SIMPLE_TEXT_OUTPUT.SetCursorPosition().
1463 This - Indicates the calling context.
1465 Column - The row to set cursor to.
1467 Row - The column to set cursor to.
1472 The operation completed successfully.
1475 The request fails due to Graphics Console device error.
1478 The Graphics Console is not in a valid text mode, or the cursor position
1479 is invalid for current mode.
1483 GRAPHICS_CONSOLE_DEV
*Private
;
1484 GRAPHICS_CONSOLE_MODE_DATA
*ModeData
;
1488 Status
= EFI_SUCCESS
;
1490 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1492 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This
);
1493 ModeData
= &(Private
->ModeData
[This
->Mode
->Mode
]);
1495 if ((Column
>= ModeData
->Columns
) || (Row
>= ModeData
->Rows
)) {
1496 Status
= EFI_UNSUPPORTED
;
1500 if (((INT32
) Column
== This
->Mode
->CursorColumn
) && ((INT32
) Row
== This
->Mode
->CursorRow
)) {
1501 Status
= EFI_SUCCESS
;
1507 This
->Mode
->CursorColumn
= (INT32
) Column
;
1508 This
->Mode
->CursorRow
= (INT32
) Row
;
1513 gBS
->RestoreTPL (OldTpl
);
1520 GraphicsConsoleConOutEnableCursor (
1521 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
1525 Routine Description:
1527 Implements SIMPLE_TEXT_OUTPUT.EnableCursor().
1528 In this driver, the cursor cannot be hidden.
1532 This - Indicates the calling context.
1534 Visible - If TRUE, the cursor is set to be visible,
1535 If FALSE, the cursor is set to be invisible.
1540 The request is valid.
1543 The Graphics Console does not support a hidden cursor.
1549 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1553 This
->Mode
->CursorVisible
= Visible
;
1557 gBS
->RestoreTPL (OldTpl
);
1564 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
1565 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Foreground
,
1566 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Background
1571 Attribute
= This
->Mode
->Attribute
& 0x7F;
1573 *Foreground
= mEfiColors
[Attribute
& 0x0f];
1574 *Background
= mEfiColors
[Attribute
>> 4];
1581 DrawUnicodeWeightAtCursorN (
1582 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
1583 IN CHAR16
*UnicodeWeight
,
1587 GRAPHICS_CONSOLE_DEV
*Private
;
1589 EFI_STATUS ReturnStatus
;
1591 GLYPH_UNION GlyphData
;
1594 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
1595 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
1596 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground
;
1597 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background
;
1604 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This
);
1606 ReturnStatus
= EFI_SUCCESS
;
1610 GetTextColors (This
, &Foreground
, &Background
);
1614 while (Index
< Count
) {
1615 if (This
->Mode
->Attribute
& EFI_WIDE_ATTRIBUTE
) {
1616 GlyphStatus
= WIDE_CHAR
;
1618 GlyphStatus
= NARROW_CHAR
;
1621 Status
= mHii
->GetGlyph (
1629 if (EFI_ERROR (Status
)) {
1630 ReturnStatus
= Status
;
1635 CopyMem (&GlyphData
, Glyph
, sizeof (GLYPH_UNION
));
1639 // We are creating the second half of the wide character's BLT buffer
1641 if (GlyphWidth
== 0x10 && Counts
== 1) {
1642 CopyMem (&GlyphData
.NarrowGlyph
.GlyphCol1
, &Glyph
->WideGlyph
.GlyphCol2
, sizeof (Glyph
->WideGlyph
.GlyphCol2
));
1647 if (GlyphWidth
== 0x10) {
1650 (UINT8
*) &GlyphData
,
1656 &Private
->LineBuffer
[ArrayIndex
* GLYPH_WIDTH
]
1661 (UINT8
*) &GlyphData
,
1667 &Private
->LineBuffer
[ArrayIndex
* GLYPH_WIDTH
]
1673 } while (Counts
< 2 && GlyphWidth
== 0x10);
1677 // If we are printing Wide characters, treat the BLT as if it is twice as many characters
1679 if (GlyphWidth
== 0x10) {
1683 // Blt a character to the screen
1685 GlyphX
= This
->Mode
->CursorColumn
* GLYPH_WIDTH
;
1686 GlyphY
= This
->Mode
->CursorRow
* GLYPH_HEIGHT
;
1687 GraphicsOutput
= Private
->GraphicsOutput
;
1688 UgaDraw
= Private
->UgaDraw
;
1689 if (GraphicsOutput
!= NULL
) {
1690 GraphicsOutput
->Blt (
1692 Private
->LineBuffer
,
1693 EfiBltBufferToVideo
,
1696 GlyphX
+ Private
->ModeData
[This
->Mode
->Mode
].DeltaX
,
1697 GlyphY
+ Private
->ModeData
[This
->Mode
->Mode
].DeltaY
,
1698 GLYPH_WIDTH
* Count
,
1700 GLYPH_WIDTH
* Count
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
1705 (EFI_UGA_PIXEL
*) (UINTN
) Private
->LineBuffer
,
1706 EfiUgaBltBufferToVideo
,
1709 GlyphX
+ Private
->ModeData
[This
->Mode
->Mode
].DeltaX
,
1710 GlyphY
+ Private
->ModeData
[This
->Mode
->Mode
].DeltaY
,
1711 GLYPH_WIDTH
* Count
,
1713 GLYPH_WIDTH
* Count
* sizeof (EFI_UGA_PIXEL
)
1717 return ReturnStatus
;
1723 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
1726 GRAPHICS_CONSOLE_DEV
*Private
;
1727 EFI_SIMPLE_TEXT_OUTPUT_MODE
*CurrentMode
;
1730 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
1731 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
1732 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Foreground
;
1733 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Background
;
1734 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION BltChar
[GLYPH_HEIGHT
][GLYPH_WIDTH
];
1738 CurrentMode
= This
->Mode
;
1740 if (!CurrentMode
->CursorVisible
) {
1744 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This
);
1745 GraphicsOutput
= Private
->GraphicsOutput
;
1746 UgaDraw
= Private
->UgaDraw
;
1749 // BUGBUG - we need to think about what to do with wide and narrow character deletions.
1752 // Blt a character to the screen
1754 GlyphX
= (CurrentMode
->CursorColumn
* GLYPH_WIDTH
) + Private
->ModeData
[CurrentMode
->Mode
].DeltaX
;
1755 GlyphY
= (CurrentMode
->CursorRow
* GLYPH_HEIGHT
) + Private
->ModeData
[CurrentMode
->Mode
].DeltaY
;
1756 if (GraphicsOutput
!= NULL
) {
1757 GraphicsOutput
->Blt (
1759 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) BltChar
,
1760 EfiBltVideoToBltBuffer
,
1767 GLYPH_WIDTH
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
1772 (EFI_UGA_PIXEL
*) (UINTN
) BltChar
,
1773 EfiUgaVideoToBltBuffer
,
1780 GLYPH_WIDTH
* sizeof (EFI_UGA_PIXEL
)
1784 GetTextColors (This
, &Foreground
.Pixel
, &Background
.Pixel
);
1787 // Convert Monochrome bitmap of the Glyph to BltBuffer structure
1789 for (Y
= 0; Y
< GLYPH_HEIGHT
; Y
++) {
1790 for (X
= 0; X
< GLYPH_WIDTH
; X
++) {
1791 if ((mCursorGlyph
.GlyphCol1
[Y
] & (1 << X
)) != 0) {
1792 BltChar
[Y
][GLYPH_WIDTH
- X
- 1].Raw
^= Foreground
.Raw
;
1797 if (GraphicsOutput
!= NULL
) {
1798 GraphicsOutput
->Blt (
1800 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) BltChar
,
1801 EfiBltBufferToVideo
,
1808 GLYPH_WIDTH
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
1813 (EFI_UGA_PIXEL
*) (UINTN
) BltChar
,
1814 EfiUgaBltBufferToVideo
,
1821 GLYPH_WIDTH
* sizeof (EFI_UGA_PIXEL
)