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_OUTPUT_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_OUTPUT_PROTOCOL
*This
,
34 IN CHAR16
*UnicodeWeight
,
41 IN EFI_SIMPLE_TEXT_OUTPUT_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 if (Private
->LineBuffer
!= NULL
) {
511 FreePool (Private
->LineBuffer
);
522 GraphicsConsoleControllerDriverStop (
523 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
524 IN EFI_HANDLE Controller
,
525 IN UINTN NumberOfChildren
,
526 IN EFI_HANDLE
*ChildHandleBuffer
530 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*SimpleTextOutput
;
531 GRAPHICS_CONSOLE_DEV
*Private
;
533 Status
= gBS
->OpenProtocol (
535 &gEfiSimpleTextOutProtocolGuid
,
536 (VOID
**) &SimpleTextOutput
,
537 This
->DriverBindingHandle
,
539 EFI_OPEN_PROTOCOL_GET_PROTOCOL
541 if (EFI_ERROR (Status
)) {
542 return EFI_NOT_STARTED
;
545 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (SimpleTextOutput
);
547 Status
= gBS
->UninstallProtocolInterface (
549 &gEfiSimpleTextOutProtocolGuid
,
550 &Private
->SimpleTextOutput
553 if (!EFI_ERROR (Status
)) {
555 // Close the GOP or UGA IO Protocol
557 if (Private
->GraphicsOutput
!= NULL
) {
560 &gEfiGraphicsOutputProtocolGuid
,
561 This
->DriverBindingHandle
,
567 &gEfiUgaDrawProtocolGuid
,
568 This
->DriverBindingHandle
,
574 // Remove the font pack
576 mHii
->RemovePack (mHii
, Private
->HiiHandle
);
579 // Free our instance data
581 if (Private
!= NULL
) {
582 FreePool (Private
->LineBuffer
);
591 EfiLocateHiiProtocol (
597 Find if the HII protocol is available. If yes, locate the HII protocol
610 // There should only be one - so buffer size is this
612 Size
= sizeof (EFI_HANDLE
);
614 Status
= gBS
->LocateHandle (
616 &gEfiHiiProtocolGuid
,
622 if (EFI_ERROR (Status
)) {
626 Status
= gBS
->HandleProtocol (
628 &gEfiHiiProtocolGuid
,
635 // Body of the STO functions
639 GraphicsConsoleConOutReset (
640 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
641 IN BOOLEAN ExtendedVerification
646 Implements SIMPLE_TEXT_OUTPUT.Reset().
647 If ExtendeVerification is TRUE, then perform dependent Graphics Console
648 device reset, and set display mode to mode 0.
649 If ExtendedVerification is FALSE, only set display mode to mode 0.
653 This - Indicates the calling context.
655 ExtendedVerification - Indicates that the driver may perform a more exhaustive
656 verification operation of the device during reset.
661 The reset operation succeeds.
664 The Graphics Console is not functioning correctly
668 This
->SetAttribute (This
, EFI_TEXT_ATTR (This
->Mode
->Attribute
& 0x0F, EFI_BACKGROUND_BLACK
));
669 return This
->SetMode (This
, 0);
674 GraphicsConsoleConOutOutputString (
675 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
681 Implements SIMPLE_TEXT_OUTPUT.OutputString().
682 The Unicode string will be converted to Glyphs and will be
683 sent to the Graphics Console.
688 This - Indicates the calling context.
690 WString - The Null-terminated Unicode string to be displayed on
691 the Graphics Console.
696 The string is output successfully.
699 The Graphics Console failed to send the string out.
701 EFI_WARN_UNKNOWN_GLYPH
702 Indicates that some of the characters in the Unicode string could not
703 be rendered and are skipped.
707 GRAPHICS_CONSOLE_DEV
*Private
;
708 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
709 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
718 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground
;
719 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background
;
724 INT32 OriginAttribute
;
726 CHAR16 SpaceStr
[] = { NARROW_CHAR
, ' ', 0 };
728 Status
= EFI_SUCCESS
;
730 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
734 Mode
= This
->Mode
->Mode
;
735 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This
);
736 GraphicsOutput
= Private
->GraphicsOutput
;
737 UgaDraw
= Private
->UgaDraw
;
739 MaxColumn
= Private
->ModeData
[Mode
].Columns
;
740 MaxRow
= Private
->ModeData
[Mode
].Rows
;
741 DeltaX
= Private
->ModeData
[Mode
].DeltaX
;
742 DeltaY
= Private
->ModeData
[Mode
].DeltaY
;
743 Width
= MaxColumn
* GLYPH_WIDTH
;
744 Height
= (MaxRow
- 1) * GLYPH_HEIGHT
;
745 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
748 // The Attributes won't change when during the time OutputString is called
750 GetTextColors (This
, &Foreground
, &Background
);
759 OriginAttribute
= This
->Mode
->Attribute
;
763 if (*WString
== CHAR_BACKSPACE
) {
765 // If the cursor is at the left edge of the display, then move the cursor
768 if (This
->Mode
->CursorColumn
== 0 && This
->Mode
->CursorRow
> 0) {
769 This
->Mode
->CursorRow
--;
770 This
->Mode
->CursorColumn
= (INT32
) (MaxColumn
- 1);
771 This
->OutputString (This
, SpaceStr
);
773 This
->Mode
->CursorRow
--;
774 This
->Mode
->CursorColumn
= (INT32
) (MaxColumn
- 1);
775 } else if (This
->Mode
->CursorColumn
> 0) {
777 // If the cursor is not at the left edge of the display, then move the cursor
780 This
->Mode
->CursorColumn
--;
781 This
->OutputString (This
, SpaceStr
);
783 This
->Mode
->CursorColumn
--;
788 } else if (*WString
== CHAR_LINEFEED
) {
790 // If the cursor is at the bottom of the display, then scroll the display one
791 // row, and do not update the cursor position. Otherwise, move the cursor
794 if (This
->Mode
->CursorRow
== (INT32
) (MaxRow
- 1)) {
795 if (GraphicsOutput
!= NULL
) {
797 // Scroll Screen Up One Row
799 GraphicsOutput
->Blt (
804 DeltaY
+ GLYPH_HEIGHT
,
813 // Print Blank Line at last line
815 GraphicsOutput
->Blt (
829 // Scroll Screen Up One Row
836 DeltaY
+ GLYPH_HEIGHT
,
845 // Print Blank Line at last line
849 (EFI_UGA_PIXEL
*) (UINTN
) &Background
,
861 This
->Mode
->CursorRow
++;
866 } else if (*WString
== CHAR_CARRIAGE_RETURN
) {
868 // Move the cursor to the beginning of the current row.
870 This
->Mode
->CursorColumn
= 0;
873 } else if (*WString
== WIDE_CHAR
) {
875 This
->Mode
->Attribute
|= EFI_WIDE_ATTRIBUTE
;
878 } else if (*WString
== NARROW_CHAR
) {
880 This
->Mode
->Attribute
&= (~ (UINT32
) EFI_WIDE_ATTRIBUTE
);
885 // Print the character at the current cursor position and move the cursor
886 // right one column. If this moves the cursor past the right edge of the
887 // display, then the line should wrap to the beginning of the next line. This
888 // is equivalent to inserting a CR and an LF. Note that if the cursor is at the
889 // bottom of the display, and the line wraps, then the display will be scrolled
891 // If wide char is going to be displayed, need to display one character at a time
892 // Or, need to know the display length of a certain string.
894 // Index is used to determine how many character width units (wide = 2, narrow = 1)
895 // Count is used to determine how many characters are used regardless of their attributes
897 for (Count
= 0, Index
= 0; (This
->Mode
->CursorColumn
+ Index
) < MaxColumn
; Count
++, Index
++) {
898 if (WString
[Count
] == CHAR_NULL
) {
902 if (WString
[Count
] == CHAR_BACKSPACE
) {
906 if (WString
[Count
] == CHAR_LINEFEED
) {
910 if (WString
[Count
] == CHAR_CARRIAGE_RETURN
) {
914 if (WString
[Count
] == WIDE_CHAR
) {
918 if (WString
[Count
] == NARROW_CHAR
) {
922 // Is the wide attribute on?
924 if (This
->Mode
->Attribute
& EFI_WIDE_ATTRIBUTE
) {
926 // If wide, add one more width unit than normal since we are going to increment at the end of the for loop
930 // This is the end-case where if we are at column 79 and about to print a wide character
931 // We should prevent this from happening because we will wrap inappropriately. We should
932 // not print this character until the next line.
934 if ((This
->Mode
->CursorColumn
+ Index
+ 1) > MaxColumn
) {
941 Status
= DrawUnicodeWeightAtCursorN (This
, WString
, Count
);
942 if (EFI_ERROR (Status
)) {
946 // At the end of line, output carriage return and line feed
949 This
->Mode
->CursorColumn
+= (INT32
) Index
;
950 if (This
->Mode
->CursorColumn
> (INT32
) MaxColumn
) {
951 This
->Mode
->CursorColumn
-= 2;
952 This
->OutputString (This
, SpaceStr
);
955 if (This
->Mode
->CursorColumn
>= (INT32
) MaxColumn
) {
957 This
->OutputString (This
, mCrLfString
);
963 This
->Mode
->Attribute
= OriginAttribute
;
968 Status
= EFI_WARN_UNKNOWN_GLYPH
;
971 gBS
->RestoreTPL (OldTpl
);
978 GraphicsConsoleConOutTestString (
979 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
985 Implements SIMPLE_TEXT_OUTPUT.TestString().
986 If one of the characters in the *Wstring is
987 neither valid valid Unicode drawing characters,
988 not ASCII code, then this function will return
994 This - Indicates the calling context.
996 WString - The Null-terminated Unicode string to be tested.
1001 The Graphics Console is capable of rendering the output string.
1004 Some of the characters in the Unicode string cannot be rendered.
1017 while (WString
[Count
]) {
1018 Status
= mHii
->GetGlyph (
1027 if (EFI_ERROR (Status
)) {
1028 return EFI_UNSUPPORTED
;
1037 GraphicsConsoleConOutQueryMode (
1038 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
1039 IN UINTN ModeNumber
,
1044 Routine Description:
1046 Implements SIMPLE_TEXT_OUTPUT.QueryMode().
1047 It returnes information for an available text mode
1048 that the Graphics Console supports.
1049 In this driver,we only support text mode 80x25, which is
1055 This - Indicates the calling context.
1057 ModeNumber - The mode number to return information on.
1059 Columns - The returned columns of the requested mode.
1061 Rows - The returned rows of the requested mode.
1066 The requested mode information is returned.
1069 The mode number is not valid.
1073 GRAPHICS_CONSOLE_DEV
*Private
;
1077 if (ModeNumber
>= (UINTN
) This
->Mode
->MaxMode
) {
1078 return EFI_UNSUPPORTED
;
1081 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1082 Status
= EFI_SUCCESS
;
1084 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This
);
1086 *Columns
= Private
->ModeData
[ModeNumber
].Columns
;
1087 *Rows
= Private
->ModeData
[ModeNumber
].Rows
;
1089 if (*Columns
<= 0 && *Rows
<= 0) {
1090 Status
= EFI_UNSUPPORTED
;
1096 gBS
->RestoreTPL (OldTpl
);
1102 GraphicsConsoleConOutSetMode (
1103 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
1107 Routine Description:
1109 Implements SIMPLE_TEXT_OUTPUT.SetMode().
1110 Set the Graphics Console to a specified mode.
1111 In this driver, we only support mode 0.
1115 This - Indicates the calling context.
1117 ModeNumber - The text mode to set.
1122 The requested text mode is set.
1125 The requested text mode cannot be set because of Graphics Console device error.
1128 The text mode number is not valid.
1133 GRAPHICS_CONSOLE_DEV
*Private
;
1134 GRAPHICS_CONSOLE_MODE_DATA
*ModeData
;
1135 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*NewLineBuffer
;
1136 UINT32 HorizontalResolution
;
1137 UINT32 VerticalResolution
;
1138 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
1139 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
1144 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1146 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This
);
1147 GraphicsOutput
= Private
->GraphicsOutput
;
1148 UgaDraw
= Private
->UgaDraw
;
1149 ModeData
= &(Private
->ModeData
[ModeNumber
]);
1151 if (ModeData
->Columns
<= 0 && ModeData
->Rows
<= 0) {
1152 Status
= EFI_UNSUPPORTED
;
1157 // Make sure the requested mode number is supported
1159 if (ModeNumber
>= (UINTN
) This
->Mode
->MaxMode
) {
1160 Status
= EFI_UNSUPPORTED
;
1164 if (ModeData
->Columns
<= 0 && ModeData
->Rows
<= 0) {
1165 Status
= EFI_UNSUPPORTED
;
1169 // Attempt to allocate a line buffer for the requested mode number
1171 NewLineBuffer
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * ModeData
->Columns
* GLYPH_WIDTH
* GLYPH_HEIGHT
);
1173 if (NewLineBuffer
== NULL
) {
1175 // The new line buffer could not be allocated, so return an error.
1176 // No changes to the state of the current console have been made, so the current console is still valid
1178 Status
= EFI_OUT_OF_RESOURCES
;
1182 // If the mode has been set at least one other time, then LineBuffer will not be NULL
1184 if (Private
->LineBuffer
!= NULL
) {
1186 // Clear the current text window on the current graphics console
1188 This
->ClearScreen (This
);
1191 // If the new mode is the same as the old mode, then just return EFI_SUCCESS
1193 if ((INT32
) ModeNumber
== This
->Mode
->Mode
) {
1194 FreePool (NewLineBuffer
);
1195 Status
= EFI_SUCCESS
;
1199 // Otherwise, the size of the text console and/or the UGA mode will be changed,
1200 // so turn off the cursor, and free the LineBuffer for the current mode
1202 This
->EnableCursor (This
, FALSE
);
1204 FreePool (Private
->LineBuffer
);
1207 // Assign the current line buffer to the newly allocated line buffer
1209 Private
->LineBuffer
= NewLineBuffer
;
1211 if (GraphicsOutput
!= NULL
) {
1212 if (ModeData
->GopModeNumber
!= GraphicsOutput
->Mode
->Mode
) {
1214 // Either no graphics mode is currently set, or it is set to the wrong resolution, so set the new grapghics mode
1216 Status
= GraphicsOutput
->SetMode (GraphicsOutput
, ModeData
->GopModeNumber
);
1217 if (EFI_ERROR (Status
)) {
1219 // The mode set operation failed
1225 // The current graphics mode is correct, so simply clear the entire display
1227 Status
= GraphicsOutput
->Blt (
1236 ModeData
->GopHeight
,
1242 // Get the current UGA Draw mode information
1244 Status
= UgaDraw
->GetMode (
1246 &HorizontalResolution
,
1247 &VerticalResolution
,
1251 if (EFI_ERROR (Status
) || HorizontalResolution
!= ModeData
->GopWidth
|| VerticalResolution
!= ModeData
->GopHeight
) {
1253 // Either no graphics mode is currently set, or it is set to the wrong resolution, so set the new grapghics mode
1255 Status
= UgaDraw
->SetMode (
1258 ModeData
->GopHeight
,
1262 if (EFI_ERROR (Status
)) {
1264 // The mode set operation failed
1270 // The current graphics mode is correct, so simply clear the entire display
1272 Status
= UgaDraw
->Blt (
1274 (EFI_UGA_PIXEL
*) (UINTN
) &mEfiColors
[0],
1281 ModeData
->GopHeight
,
1288 // The new mode is valid, so commit the mode change
1290 This
->Mode
->Mode
= (INT32
) ModeNumber
;
1293 // Move the text cursor to the upper left hand corner of the displat and enable it
1295 This
->SetCursorPosition (This
, 0, 0);
1296 This
->EnableCursor (This
, TRUE
);
1298 Status
= EFI_SUCCESS
;
1301 gBS
->RestoreTPL (OldTpl
);
1307 GraphicsConsoleConOutSetAttribute (
1308 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
1312 Routine Description:
1314 Implements SIMPLE_TEXT_OUTPUT.SetAttribute().
1318 This - Indicates the calling context.
1320 Attrubute - The attribute to set. Only bit0..6 are valid, all other bits
1321 are undefined and must be zero.
1326 The requested attribute is set.
1329 The requested attribute cannot be set due to Graphics Console port error.
1332 The attribute requested is not defined by EFI spec.
1338 if ((Attribute
| 0xFF) != 0xFF) {
1339 return EFI_UNSUPPORTED
;
1342 if ((INT32
) Attribute
== This
->Mode
->Attribute
) {
1346 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1350 This
->Mode
->Attribute
= (INT32
) Attribute
;
1354 gBS
->RestoreTPL (OldTpl
);
1361 GraphicsConsoleConOutClearScreen (
1362 IN EFI_SIMPLE_TEXT_OUTPUT_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
;
1398 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1400 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This
);
1401 GraphicsOutput
= Private
->GraphicsOutput
;
1402 UgaDraw
= Private
->UgaDraw
;
1403 ModeData
= &(Private
->ModeData
[This
->Mode
->Mode
]);
1405 GetTextColors (This
, &Foreground
, &Background
);
1406 if (GraphicsOutput
!= NULL
) {
1407 Status
= GraphicsOutput
->Blt (
1416 ModeData
->GopHeight
,
1420 Status
= UgaDraw
->Blt (
1422 (EFI_UGA_PIXEL
*) (UINTN
) &Background
,
1429 ModeData
->GopHeight
,
1434 This
->Mode
->CursorColumn
= 0;
1435 This
->Mode
->CursorRow
= 0;
1439 gBS
->RestoreTPL (OldTpl
);
1446 GraphicsConsoleConOutSetCursorPosition (
1447 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
1452 Routine Description:
1454 Implements SIMPLE_TEXT_OUTPUT.SetCursorPosition().
1458 This - Indicates the calling context.
1460 Column - The row to set cursor to.
1462 Row - The column to set cursor to.
1467 The operation completed successfully.
1470 The request fails due to Graphics Console device error.
1473 The Graphics Console is not in a valid text mode, or the cursor position
1474 is invalid for current mode.
1478 GRAPHICS_CONSOLE_DEV
*Private
;
1479 GRAPHICS_CONSOLE_MODE_DATA
*ModeData
;
1483 Status
= EFI_SUCCESS
;
1485 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1487 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This
);
1488 ModeData
= &(Private
->ModeData
[This
->Mode
->Mode
]);
1490 if ((Column
>= ModeData
->Columns
) || (Row
>= ModeData
->Rows
)) {
1491 Status
= EFI_UNSUPPORTED
;
1495 if (((INT32
) Column
== This
->Mode
->CursorColumn
) && ((INT32
) Row
== This
->Mode
->CursorRow
)) {
1496 Status
= EFI_SUCCESS
;
1502 This
->Mode
->CursorColumn
= (INT32
) Column
;
1503 This
->Mode
->CursorRow
= (INT32
) Row
;
1508 gBS
->RestoreTPL (OldTpl
);
1515 GraphicsConsoleConOutEnableCursor (
1516 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
1520 Routine Description:
1522 Implements SIMPLE_TEXT_OUTPUT.EnableCursor().
1523 In this driver, the cursor cannot be hidden.
1527 This - Indicates the calling context.
1529 Visible - If TRUE, the cursor is set to be visible,
1530 If FALSE, the cursor is set to be invisible.
1535 The request is valid.
1538 The Graphics Console does not support a hidden cursor.
1544 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1548 This
->Mode
->CursorVisible
= Visible
;
1552 gBS
->RestoreTPL (OldTpl
);
1559 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
1560 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Foreground
,
1561 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Background
1566 Attribute
= This
->Mode
->Attribute
& 0x7F;
1568 *Foreground
= mEfiColors
[Attribute
& 0x0f];
1569 *Background
= mEfiColors
[Attribute
>> 4];
1576 DrawUnicodeWeightAtCursorN (
1577 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
1578 IN CHAR16
*UnicodeWeight
,
1582 GRAPHICS_CONSOLE_DEV
*Private
;
1584 EFI_STATUS ReturnStatus
;
1586 GLYPH_UNION GlyphData
;
1589 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
1590 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
1591 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground
;
1592 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background
;
1599 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This
);
1601 ReturnStatus
= EFI_SUCCESS
;
1605 GetTextColors (This
, &Foreground
, &Background
);
1609 while (Index
< Count
) {
1610 if (This
->Mode
->Attribute
& EFI_WIDE_ATTRIBUTE
) {
1611 GlyphStatus
= WIDE_CHAR
;
1613 GlyphStatus
= NARROW_CHAR
;
1616 Status
= mHii
->GetGlyph (
1624 if (EFI_ERROR (Status
)) {
1625 ReturnStatus
= Status
;
1630 CopyMem (&GlyphData
, Glyph
, sizeof (GLYPH_UNION
));
1634 // We are creating the second half of the wide character's BLT buffer
1636 if (GlyphWidth
== 0x10 && Counts
== 1) {
1637 CopyMem (&GlyphData
.NarrowGlyph
.GlyphCol1
, &Glyph
->WideGlyph
.GlyphCol2
, sizeof (Glyph
->WideGlyph
.GlyphCol2
));
1642 if (GlyphWidth
== 0x10) {
1645 (UINT8
*) &GlyphData
,
1651 &Private
->LineBuffer
[ArrayIndex
* GLYPH_WIDTH
]
1656 (UINT8
*) &GlyphData
,
1662 &Private
->LineBuffer
[ArrayIndex
* GLYPH_WIDTH
]
1668 } while (Counts
< 2 && GlyphWidth
== 0x10);
1672 // If we are printing Wide characters, treat the BLT as if it is twice as many characters
1674 if (GlyphWidth
== 0x10) {
1678 // Blt a character to the screen
1680 GlyphX
= This
->Mode
->CursorColumn
* GLYPH_WIDTH
;
1681 GlyphY
= This
->Mode
->CursorRow
* GLYPH_HEIGHT
;
1682 GraphicsOutput
= Private
->GraphicsOutput
;
1683 UgaDraw
= Private
->UgaDraw
;
1684 if (GraphicsOutput
!= NULL
) {
1685 GraphicsOutput
->Blt (
1687 Private
->LineBuffer
,
1688 EfiBltBufferToVideo
,
1691 GlyphX
+ Private
->ModeData
[This
->Mode
->Mode
].DeltaX
,
1692 GlyphY
+ Private
->ModeData
[This
->Mode
->Mode
].DeltaY
,
1693 GLYPH_WIDTH
* Count
,
1695 GLYPH_WIDTH
* Count
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
1700 (EFI_UGA_PIXEL
*) (UINTN
) Private
->LineBuffer
,
1701 EfiUgaBltBufferToVideo
,
1704 GlyphX
+ Private
->ModeData
[This
->Mode
->Mode
].DeltaX
,
1705 GlyphY
+ Private
->ModeData
[This
->Mode
->Mode
].DeltaY
,
1706 GLYPH_WIDTH
* Count
,
1708 GLYPH_WIDTH
* Count
* sizeof (EFI_UGA_PIXEL
)
1712 return ReturnStatus
;
1718 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
1721 GRAPHICS_CONSOLE_DEV
*Private
;
1722 EFI_SIMPLE_TEXT_OUTPUT_MODE
*CurrentMode
;
1725 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
1726 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
1727 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Foreground
;
1728 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Background
;
1729 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION BltChar
[GLYPH_HEIGHT
][GLYPH_WIDTH
];
1733 CurrentMode
= This
->Mode
;
1735 if (!CurrentMode
->CursorVisible
) {
1739 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This
);
1740 GraphicsOutput
= Private
->GraphicsOutput
;
1741 UgaDraw
= Private
->UgaDraw
;
1744 // BUGBUG - we need to think about what to do with wide and narrow character deletions.
1747 // Blt a character to the screen
1749 GlyphX
= (CurrentMode
->CursorColumn
* GLYPH_WIDTH
) + Private
->ModeData
[CurrentMode
->Mode
].DeltaX
;
1750 GlyphY
= (CurrentMode
->CursorRow
* GLYPH_HEIGHT
) + Private
->ModeData
[CurrentMode
->Mode
].DeltaY
;
1751 if (GraphicsOutput
!= NULL
) {
1752 GraphicsOutput
->Blt (
1754 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) BltChar
,
1755 EfiBltVideoToBltBuffer
,
1762 GLYPH_WIDTH
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
1767 (EFI_UGA_PIXEL
*) (UINTN
) BltChar
,
1768 EfiUgaVideoToBltBuffer
,
1775 GLYPH_WIDTH
* sizeof (EFI_UGA_PIXEL
)
1779 GetTextColors (This
, &Foreground
.Pixel
, &Background
.Pixel
);
1782 // Convert Monochrome bitmap of the Glyph to BltBuffer structure
1784 for (Y
= 0; Y
< GLYPH_HEIGHT
; Y
++) {
1785 for (X
= 0; X
< GLYPH_WIDTH
; X
++) {
1786 if ((mCursorGlyph
.GlyphCol1
[Y
] & (1 << X
)) != 0) {
1787 BltChar
[Y
][GLYPH_WIDTH
- X
- 1].Raw
^= Foreground
.Raw
;
1792 if (GraphicsOutput
!= NULL
) {
1793 GraphicsOutput
->Blt (
1795 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) BltChar
,
1796 EfiBltBufferToVideo
,
1803 GLYPH_WIDTH
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
1808 (EFI_UGA_PIXEL
*) (UINTN
) BltChar
,
1809 EfiUgaBltBufferToVideo
,
1816 GLYPH_WIDTH
* sizeof (EFI_UGA_PIXEL
)
1824 The user Entry Point for module GraphicsConsole. The user code starts with this function.
1826 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1827 @param[in] SystemTable A pointer to the EFI System Table.
1829 @retval EFI_SUCCESS The entry point is executed successfully.
1830 @retval other Some error occurs when executing this entry point.
1835 InitializeGraphicsConsole (
1836 IN EFI_HANDLE ImageHandle
,
1837 IN EFI_SYSTEM_TABLE
*SystemTable
1843 // Install driver model protocol(s).
1845 Status
= EfiLibInstallDriverBindingComponentName2 (
1848 &gGraphicsConsoleDriverBinding
,
1850 &gGraphicsConsoleComponentName
,
1851 &gGraphicsConsoleComponentName2
1853 ASSERT_EFI_ERROR (Status
);