2 This is the main routine for initializing the Graphics Console support routines.
4 Add all standard Glyphs from EFI 1.02 Specification
5 Implement optimal automatic Mode creation algorithm
6 Solve palette issues for mixed graphics and text
7 When does this protocol reset the palette?
9 Copyright (c) 2006 Intel Corporation. <BR>
10 All rights reserved. This program and the accompanying materials
11 are licensed and made available under the terms and conditions of the BSD License
12 which accompanies this distribution. The full text of the license may be found at
13 http://opensource.org/licenses/bsd-license.php
15 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
16 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 #include "GraphicsConsole.h"
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
));
323 gBS
->FreePool (Package
);
326 // Free the font database
328 gBS
->FreePool (FontPack
);
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
)) {
353 gBS
->FreePool (Info
);
357 gBS
->FreePool (Info
);
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 gBS
->FreePool (Private
->LineBuffer
);
511 gBS
->FreePool (Private
);
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 gBS
->FreePool (Private
->LineBuffer
);
581 gBS
->FreePool (Private
);
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
;
723 CHAR16 SpaceStr
[] = { NARROW_CHAR
, ' ', 0 };
728 Mode
= This
->Mode
->Mode
;
729 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This
);
730 GraphicsOutput
= Private
->GraphicsOutput
;
731 UgaDraw
= Private
->UgaDraw
;
733 MaxColumn
= Private
->ModeData
[Mode
].Columns
;
734 MaxRow
= Private
->ModeData
[Mode
].Rows
;
735 DeltaX
= Private
->ModeData
[Mode
].DeltaX
;
736 DeltaY
= Private
->ModeData
[Mode
].DeltaY
;
737 Width
= MaxColumn
* GLYPH_WIDTH
;
738 Height
= (MaxRow
- 1) * GLYPH_HEIGHT
;
739 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
742 // The Attributes won't change when during the time OutputString is called
744 GetTextColors (This
, &Foreground
, &Background
);
753 OriginAttribute
= This
->Mode
->Attribute
;
757 if (*WString
== CHAR_BACKSPACE
) {
759 // If the cursor is at the left edge of the display, then move the cursor
762 if (This
->Mode
->CursorColumn
== 0 && This
->Mode
->CursorRow
> 0) {
763 This
->Mode
->CursorRow
--;
764 This
->Mode
->CursorColumn
= (INT32
) (MaxColumn
- 1);
765 This
->OutputString (This
, SpaceStr
);
767 This
->Mode
->CursorRow
--;
768 This
->Mode
->CursorColumn
= (INT32
) (MaxColumn
- 1);
769 } else if (This
->Mode
->CursorColumn
> 0) {
771 // If the cursor is not at the left edge of the display, then move the cursor
774 This
->Mode
->CursorColumn
--;
775 This
->OutputString (This
, SpaceStr
);
777 This
->Mode
->CursorColumn
--;
782 } else if (*WString
== CHAR_LINEFEED
) {
784 // If the cursor is at the bottom of the display, then scroll the display one
785 // row, and do not update the cursor position. Otherwise, move the cursor
788 if (This
->Mode
->CursorRow
== (INT32
) (MaxRow
- 1)) {
789 if (GraphicsOutput
!= NULL
) {
791 // Scroll Screen Up One Row
793 GraphicsOutput
->Blt (
798 DeltaY
+ GLYPH_HEIGHT
,
807 // Print Blank Line at last line
809 GraphicsOutput
->Blt (
823 // Scroll Screen Up One Row
830 DeltaY
+ GLYPH_HEIGHT
,
839 // Print Blank Line at last line
843 (EFI_UGA_PIXEL
*) (UINTN
) &Background
,
855 This
->Mode
->CursorRow
++;
860 } else if (*WString
== CHAR_CARRIAGE_RETURN
) {
862 // Move the cursor to the beginning of the current row.
864 This
->Mode
->CursorColumn
= 0;
867 } else if (*WString
== WIDE_CHAR
) {
869 This
->Mode
->Attribute
|= EFI_WIDE_ATTRIBUTE
;
872 } else if (*WString
== NARROW_CHAR
) {
874 This
->Mode
->Attribute
&= (~ (UINT32
) EFI_WIDE_ATTRIBUTE
);
879 // Print the character at the current cursor position and move the cursor
880 // right one column. If this moves the cursor past the right edge of the
881 // display, then the line should wrap to the beginning of the next line. This
882 // is equivalent to inserting a CR and an LF. Note that if the cursor is at the
883 // bottom of the display, and the line wraps, then the display will be scrolled
885 // If wide char is going to be displayed, need to display one character at a time
886 // Or, need to know the display length of a certain string.
888 // Index is used to determine how many character width units (wide = 2, narrow = 1)
889 // Count is used to determine how many characters are used regardless of their attributes
891 for (Count
= 0, Index
= 0; (This
->Mode
->CursorColumn
+ Index
) < MaxColumn
; Count
++, Index
++) {
892 if (WString
[Count
] == CHAR_NULL
) {
896 if (WString
[Count
] == CHAR_BACKSPACE
) {
900 if (WString
[Count
] == CHAR_LINEFEED
) {
904 if (WString
[Count
] == CHAR_CARRIAGE_RETURN
) {
908 if (WString
[Count
] == WIDE_CHAR
) {
912 if (WString
[Count
] == NARROW_CHAR
) {
916 // Is the wide attribute on?
918 if (This
->Mode
->Attribute
& EFI_WIDE_ATTRIBUTE
) {
920 // If wide, add one more width unit than normal since we are going to increment at the end of the for loop
924 // This is the end-case where if we are at column 79 and about to print a wide character
925 // We should prevent this from happening because we will wrap inappropriately. We should
926 // not print this character until the next line.
928 if ((This
->Mode
->CursorColumn
+ Index
+ 1) > MaxColumn
) {
935 Status
= DrawUnicodeWeightAtCursorN (This
, WString
, Count
);
936 if (EFI_ERROR (Status
)) {
940 // At the end of line, output carriage return and line feed
943 This
->Mode
->CursorColumn
+= (INT32
) Index
;
944 if (This
->Mode
->CursorColumn
> (INT32
) MaxColumn
) {
945 This
->Mode
->CursorColumn
-= 2;
946 This
->OutputString (This
, SpaceStr
);
949 if (This
->Mode
->CursorColumn
>= (INT32
) MaxColumn
) {
951 This
->OutputString (This
, mCrLfString
);
957 This
->Mode
->Attribute
= OriginAttribute
;
962 return EFI_WARN_UNKNOWN_GLYPH
;
970 GraphicsConsoleConOutTestString (
971 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
977 Implements SIMPLE_TEXT_OUTPUT.TestString().
978 If one of the characters in the *Wstring is
979 neither valid valid Unicode drawing characters,
980 not ASCII code, then this function will return
986 This - Indicates the calling context.
988 WString - The Null-terminated Unicode string to be tested.
993 The Graphics Console is capable of rendering the output string.
996 Some of the characters in the Unicode string cannot be rendered.
1009 while (WString
[Count
]) {
1010 Status
= mHii
->GetGlyph (
1019 if (EFI_ERROR (Status
)) {
1020 return EFI_UNSUPPORTED
;
1029 GraphicsConsoleConOutQueryMode (
1030 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
1031 IN UINTN ModeNumber
,
1036 Routine Description:
1038 Implements SIMPLE_TEXT_OUTPUT.QueryMode().
1039 It returnes information for an available text mode
1040 that the Graphics Console supports.
1041 In this driver,we only support text mode 80x25, which is
1047 This - Indicates the calling context.
1049 ModeNumber - The mode number to return information on.
1051 Columns - The returned columns of the requested mode.
1053 Rows - The returned rows of the requested mode.
1058 The requested mode information is returned.
1061 The mode number is not valid.
1065 GRAPHICS_CONSOLE_DEV
*Private
;
1067 if (ModeNumber
>= (UINTN
) This
->Mode
->MaxMode
) {
1068 return EFI_UNSUPPORTED
;
1071 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This
);
1073 *Columns
= Private
->ModeData
[ModeNumber
].Columns
;
1074 *Rows
= Private
->ModeData
[ModeNumber
].Rows
;
1076 if (*Columns
<= 0 && *Rows
<= 0) {
1077 return EFI_UNSUPPORTED
;
1086 GraphicsConsoleConOutSetMode (
1087 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
1091 Routine Description:
1093 Implements SIMPLE_TEXT_OUTPUT.SetMode().
1094 Set the Graphics Console to a specified mode.
1095 In this driver, we only support mode 0.
1099 This - Indicates the calling context.
1101 ModeNumber - The text mode to set.
1106 The requested text mode is set.
1109 The requested text mode cannot be set because of Graphics Console device error.
1112 The text mode number is not valid.
1117 GRAPHICS_CONSOLE_DEV
*Private
;
1118 GRAPHICS_CONSOLE_MODE_DATA
*ModeData
;
1119 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*NewLineBuffer
;
1120 UINT32 HorizontalResolution
;
1121 UINT32 VerticalResolution
;
1122 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
1123 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
1127 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This
);
1128 GraphicsOutput
= Private
->GraphicsOutput
;
1129 UgaDraw
= Private
->UgaDraw
;
1130 ModeData
= &(Private
->ModeData
[ModeNumber
]);
1132 if (ModeData
->Columns
<= 0 && ModeData
->Rows
<= 0) {
1133 return EFI_UNSUPPORTED
;
1137 // Make sure the requested mode number is supported
1139 if (ModeNumber
>= (UINTN
) This
->Mode
->MaxMode
) {
1140 return EFI_UNSUPPORTED
;
1143 if (ModeData
->Columns
<= 0 && ModeData
->Rows
<= 0) {
1144 return EFI_UNSUPPORTED
;
1147 // Attempt to allocate a line buffer for the requested mode number
1149 Status
= gBS
->AllocatePool (
1150 EfiBootServicesData
,
1151 sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
) * ModeData
->Columns
* GLYPH_WIDTH
* GLYPH_HEIGHT
,
1152 (VOID
**) &NewLineBuffer
1154 if (EFI_ERROR (Status
)) {
1156 // The new line buffer could not be allocated, so return an error.
1157 // No changes to the state of the current console have been made, so the current console is still valid
1162 // If the mode has been set at least one other time, then LineBuffer will not be NULL
1164 if (Private
->LineBuffer
!= NULL
) {
1166 // Clear the current text window on the current graphics console
1168 This
->ClearScreen (This
);
1171 // If the new mode is the same as the old mode, then just return EFI_SUCCESS
1173 if ((INT32
) ModeNumber
== This
->Mode
->Mode
) {
1174 gBS
->FreePool (NewLineBuffer
);
1178 // Otherwise, the size of the text console and/or the UGA mode will be changed,
1179 // so turn off the cursor, and free the LineBuffer for the current mode
1181 This
->EnableCursor (This
, FALSE
);
1183 gBS
->FreePool (Private
->LineBuffer
);
1186 // Assign the current line buffer to the newly allocated line buffer
1188 Private
->LineBuffer
= NewLineBuffer
;
1190 if (GraphicsOutput
!= NULL
) {
1191 if (ModeData
->GopModeNumber
!= GraphicsOutput
->Mode
->Mode
) {
1193 // Either no graphics mode is currently set, or it is set to the wrong resolution, so set the new grapghics mode
1195 Status
= GraphicsOutput
->SetMode (GraphicsOutput
, ModeData
->GopModeNumber
);
1196 if (EFI_ERROR (Status
)) {
1198 // The mode set operation failed
1204 // The current graphics mode is correct, so simply clear the entire display
1206 Status
= GraphicsOutput
->Blt (
1215 ModeData
->GopHeight
,
1221 // Get the current UGA Draw mode information
1223 Status
= UgaDraw
->GetMode (
1225 &HorizontalResolution
,
1226 &VerticalResolution
,
1230 if (EFI_ERROR (Status
) || HorizontalResolution
!= ModeData
->GopWidth
|| VerticalResolution
!= ModeData
->GopHeight
) {
1232 // Either no graphics mode is currently set, or it is set to the wrong resolution, so set the new grapghics mode
1234 Status
= UgaDraw
->SetMode (
1237 ModeData
->GopHeight
,
1241 if (EFI_ERROR (Status
)) {
1243 // The mode set operation failed
1249 // The current graphics mode is correct, so simply clear the entire display
1251 Status
= UgaDraw
->Blt (
1253 (EFI_UGA_PIXEL
*) (UINTN
) &mEfiColors
[0],
1260 ModeData
->GopHeight
,
1267 // The new mode is valid, so commit the mode change
1269 This
->Mode
->Mode
= (INT32
) ModeNumber
;
1272 // Move the text cursor to the upper left hand corner of the displat and enable it
1274 This
->SetCursorPosition (This
, 0, 0);
1275 This
->EnableCursor (This
, TRUE
);
1282 GraphicsConsoleConOutSetAttribute (
1283 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
1287 Routine Description:
1289 Implements SIMPLE_TEXT_OUTPUT.SetAttribute().
1293 This - Indicates the calling context.
1295 Attrubute - The attribute to set. Only bit0..6 are valid, all other bits
1296 are undefined and must be zero.
1301 The requested attribute is set.
1304 The requested attribute cannot be set due to Graphics Console port error.
1307 The attribute requested is not defined by EFI spec.
1311 if ((Attribute
| 0xFF) != 0xFF) {
1312 return EFI_UNSUPPORTED
;
1315 if ((INT32
) Attribute
== This
->Mode
->Attribute
) {
1321 This
->Mode
->Attribute
= (INT32
) Attribute
;
1330 GraphicsConsoleConOutClearScreen (
1331 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
1334 Routine Description:
1336 Implements SIMPLE_TEXT_OUTPUT.ClearScreen().
1337 It clears the Graphics Console's display to the
1338 currently selected background color.
1343 This - Indicates the calling context.
1348 The operation completed successfully.
1351 The Graphics Console cannot be cleared due to Graphics Console device error.
1354 The Graphics Console is not in a valid text mode.
1359 GRAPHICS_CONSOLE_DEV
*Private
;
1360 GRAPHICS_CONSOLE_MODE_DATA
*ModeData
;
1361 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
1362 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
1363 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground
;
1364 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background
;
1366 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This
);
1367 GraphicsOutput
= Private
->GraphicsOutput
;
1368 UgaDraw
= Private
->UgaDraw
;
1369 ModeData
= &(Private
->ModeData
[This
->Mode
->Mode
]);
1371 GetTextColors (This
, &Foreground
, &Background
);
1372 if (GraphicsOutput
!= NULL
) {
1373 Status
= GraphicsOutput
->Blt (
1382 ModeData
->GopHeight
,
1386 Status
= UgaDraw
->Blt (
1388 (EFI_UGA_PIXEL
*) (UINTN
) &Background
,
1395 ModeData
->GopHeight
,
1400 This
->Mode
->CursorColumn
= 0;
1401 This
->Mode
->CursorRow
= 0;
1410 GraphicsConsoleConOutSetCursorPosition (
1411 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
1416 Routine Description:
1418 Implements SIMPLE_TEXT_OUTPUT.SetCursorPosition().
1422 This - Indicates the calling context.
1424 Column - The row to set cursor to.
1426 Row - The column to set cursor to.
1431 The operation completed successfully.
1434 The request fails due to Graphics Console device error.
1437 The Graphics Console is not in a valid text mode, or the cursor position
1438 is invalid for current mode.
1442 GRAPHICS_CONSOLE_DEV
*Private
;
1443 GRAPHICS_CONSOLE_MODE_DATA
*ModeData
;
1445 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This
);
1446 ModeData
= &(Private
->ModeData
[This
->Mode
->Mode
]);
1448 if ((Column
>= ModeData
->Columns
) || (Row
>= ModeData
->Rows
)) {
1449 return EFI_UNSUPPORTED
;
1452 if (((INT32
) Column
== This
->Mode
->CursorColumn
) && ((INT32
) Row
== This
->Mode
->CursorRow
)) {
1458 This
->Mode
->CursorColumn
= (INT32
) Column
;
1459 This
->Mode
->CursorRow
= (INT32
) Row
;
1468 GraphicsConsoleConOutEnableCursor (
1469 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
1473 Routine Description:
1475 Implements SIMPLE_TEXT_OUTPUT.EnableCursor().
1476 In this driver, the cursor cannot be hidden.
1480 This - Indicates the calling context.
1482 Visible - If TRUE, the cursor is set to be visible,
1483 If FALSE, the cursor is set to be invisible.
1488 The request is valid.
1491 The Graphics Console does not support a hidden cursor.
1497 This
->Mode
->CursorVisible
= Visible
;
1507 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
1508 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Foreground
,
1509 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Background
1514 Attribute
= This
->Mode
->Attribute
& 0x7F;
1516 *Foreground
= mEfiColors
[Attribute
& 0x0f];
1517 *Background
= mEfiColors
[Attribute
>> 4];
1524 DrawUnicodeWeightAtCursorN (
1525 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
1526 IN CHAR16
*UnicodeWeight
,
1530 GRAPHICS_CONSOLE_DEV
*Private
;
1532 EFI_STATUS ReturnStatus
;
1534 GLYPH_UNION GlyphData
;
1537 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
1538 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
1539 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground
;
1540 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background
;
1547 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This
);
1549 ReturnStatus
= EFI_SUCCESS
;
1553 GetTextColors (This
, &Foreground
, &Background
);
1557 while (Index
< Count
) {
1558 if (This
->Mode
->Attribute
& EFI_WIDE_ATTRIBUTE
) {
1559 GlyphStatus
= WIDE_CHAR
;
1561 GlyphStatus
= NARROW_CHAR
;
1564 Status
= mHii
->GetGlyph (
1572 if (EFI_ERROR (Status
)) {
1573 ReturnStatus
= Status
;
1578 CopyMem (&GlyphData
, Glyph
, sizeof (GLYPH_UNION
));
1582 // We are creating the second half of the wide character's BLT buffer
1584 if (GlyphWidth
== 0x10 && Counts
== 1) {
1585 CopyMem (&GlyphData
.NarrowGlyph
.GlyphCol1
, &Glyph
->WideGlyph
.GlyphCol2
, sizeof (Glyph
->WideGlyph
.GlyphCol2
));
1590 if (GlyphWidth
== 0x10) {
1593 (UINT8
*) &GlyphData
,
1599 &Private
->LineBuffer
[ArrayIndex
* GLYPH_WIDTH
]
1604 (UINT8
*) &GlyphData
,
1610 &Private
->LineBuffer
[ArrayIndex
* GLYPH_WIDTH
]
1616 } while (Counts
< 2 && GlyphWidth
== 0x10);
1620 // If we are printing Wide characters, treat the BLT as if it is twice as many characters
1622 if (GlyphWidth
== 0x10) {
1626 // Blt a character to the screen
1628 GlyphX
= This
->Mode
->CursorColumn
* GLYPH_WIDTH
;
1629 GlyphY
= This
->Mode
->CursorRow
* GLYPH_HEIGHT
;
1630 GraphicsOutput
= Private
->GraphicsOutput
;
1631 UgaDraw
= Private
->UgaDraw
;
1632 if (GraphicsOutput
!= NULL
) {
1633 GraphicsOutput
->Blt (
1635 Private
->LineBuffer
,
1636 EfiBltBufferToVideo
,
1639 GlyphX
+ Private
->ModeData
[This
->Mode
->Mode
].DeltaX
,
1640 GlyphY
+ Private
->ModeData
[This
->Mode
->Mode
].DeltaY
,
1641 GLYPH_WIDTH
* Count
,
1643 GLYPH_WIDTH
* Count
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
1648 (EFI_UGA_PIXEL
*) (UINTN
) Private
->LineBuffer
,
1649 EfiUgaBltBufferToVideo
,
1652 GlyphX
+ Private
->ModeData
[This
->Mode
->Mode
].DeltaX
,
1653 GlyphY
+ Private
->ModeData
[This
->Mode
->Mode
].DeltaY
,
1654 GLYPH_WIDTH
* Count
,
1656 GLYPH_WIDTH
* Count
* sizeof (EFI_UGA_PIXEL
)
1660 return ReturnStatus
;
1666 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
1669 GRAPHICS_CONSOLE_DEV
*Private
;
1670 EFI_SIMPLE_TEXT_OUTPUT_MODE
*CurrentMode
;
1673 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
1674 EFI_UGA_DRAW_PROTOCOL
*UgaDraw
;
1675 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Foreground
;
1676 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Background
;
1677 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION BltChar
[GLYPH_HEIGHT
][GLYPH_WIDTH
];
1681 CurrentMode
= This
->Mode
;
1683 if (!CurrentMode
->CursorVisible
) {
1687 Private
= GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This
);
1688 GraphicsOutput
= Private
->GraphicsOutput
;
1689 UgaDraw
= Private
->UgaDraw
;
1692 // BUGBUG - we need to think about what to do with wide and narrow character deletions.
1695 // Blt a character to the screen
1697 GlyphX
= (CurrentMode
->CursorColumn
* GLYPH_WIDTH
) + Private
->ModeData
[CurrentMode
->Mode
].DeltaX
;
1698 GlyphY
= (CurrentMode
->CursorRow
* GLYPH_HEIGHT
) + Private
->ModeData
[CurrentMode
->Mode
].DeltaY
;
1699 if (GraphicsOutput
!= NULL
) {
1700 GraphicsOutput
->Blt (
1702 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) BltChar
,
1703 EfiBltVideoToBltBuffer
,
1710 GLYPH_WIDTH
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
1715 (EFI_UGA_PIXEL
*) (UINTN
) BltChar
,
1716 EfiUgaVideoToBltBuffer
,
1723 GLYPH_WIDTH
* sizeof (EFI_UGA_PIXEL
)
1727 GetTextColors (This
, &Foreground
.Pixel
, &Background
.Pixel
);
1730 // Convert Monochrome bitmap of the Glyph to BltBuffer structure
1732 for (Y
= 0; Y
< GLYPH_HEIGHT
; Y
++) {
1733 for (X
= 0; X
< GLYPH_WIDTH
; X
++) {
1734 if ((mCursorGlyph
.GlyphCol1
[Y
] & (1 << X
)) != 0) {
1735 BltChar
[Y
][GLYPH_WIDTH
- X
- 1].Raw
^= Foreground
.Raw
;
1740 if (GraphicsOutput
!= NULL
) {
1741 GraphicsOutput
->Blt (
1743 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) BltChar
,
1744 EfiBltBufferToVideo
,
1751 GLYPH_WIDTH
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
)
1756 (EFI_UGA_PIXEL
*) (UINTN
) BltChar
,
1757 EfiUgaBltBufferToVideo
,
1764 GLYPH_WIDTH
* sizeof (EFI_UGA_PIXEL
)