2 Implementation for EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL protocol.
4 Copyright (c) 2006 - 2008, Intel Corporation. <BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 // This list is used to define the valid extend chars.
19 // It also provides a mapping from Unicode to PCANSI or
20 // ASCII. The ASCII mapping we just made up.
23 STATIC UNICODE_TO_CHAR UnicodeToPcAnsiOrAscii
[] = {
24 { BOXDRAW_HORIZONTAL
, 0xc4, L
'-' },
25 { BOXDRAW_VERTICAL
, 0xb3, L
'|' },
26 { BOXDRAW_DOWN_RIGHT
, 0xda, L
'/' },
27 { BOXDRAW_DOWN_LEFT
, 0xbf, L
'\\' },
28 { BOXDRAW_UP_RIGHT
, 0xc0, L
'\\' },
29 { BOXDRAW_UP_LEFT
, 0xd9, L
'/' },
30 { BOXDRAW_VERTICAL_RIGHT
, 0xc3, L
'|' },
31 { BOXDRAW_VERTICAL_LEFT
, 0xb4, L
'|' },
32 { BOXDRAW_DOWN_HORIZONTAL
, 0xc2, L
'+' },
33 { BOXDRAW_UP_HORIZONTAL
, 0xc1, L
'+' },
34 { BOXDRAW_VERTICAL_HORIZONTAL
, 0xc5, L
'+' },
35 { BOXDRAW_DOUBLE_HORIZONTAL
, 0xcd, L
'-' },
36 { BOXDRAW_DOUBLE_VERTICAL
, 0xba, L
'|' },
37 { BOXDRAW_DOWN_RIGHT_DOUBLE
, 0xd5, L
'/' },
38 { BOXDRAW_DOWN_DOUBLE_RIGHT
, 0xd6, L
'/' },
39 { BOXDRAW_DOUBLE_DOWN_RIGHT
, 0xc9, L
'/' },
40 { BOXDRAW_DOWN_LEFT_DOUBLE
, 0xb8, L
'\\' },
41 { BOXDRAW_DOWN_DOUBLE_LEFT
, 0xb7, L
'\\' },
42 { BOXDRAW_DOUBLE_DOWN_LEFT
, 0xbb, L
'\\' },
43 { BOXDRAW_UP_RIGHT_DOUBLE
, 0xd4, L
'\\' },
44 { BOXDRAW_UP_DOUBLE_RIGHT
, 0xd3, L
'\\' },
45 { BOXDRAW_DOUBLE_UP_RIGHT
, 0xc8, L
'\\' },
46 { BOXDRAW_UP_LEFT_DOUBLE
, 0xbe, L
'/' },
47 { BOXDRAW_UP_DOUBLE_LEFT
, 0xbd, L
'/' },
48 { BOXDRAW_DOUBLE_UP_LEFT
, 0xbc, L
'/' },
49 { BOXDRAW_VERTICAL_RIGHT_DOUBLE
, 0xc6, L
'|' },
50 { BOXDRAW_VERTICAL_DOUBLE_RIGHT
, 0xc7, L
'|' },
51 { BOXDRAW_DOUBLE_VERTICAL_RIGHT
, 0xcc, L
'|' },
52 { BOXDRAW_VERTICAL_LEFT_DOUBLE
, 0xb5, L
'|' },
53 { BOXDRAW_VERTICAL_DOUBLE_LEFT
, 0xb6, L
'|' },
54 { BOXDRAW_DOUBLE_VERTICAL_LEFT
, 0xb9, L
'|' },
55 { BOXDRAW_DOWN_HORIZONTAL_DOUBLE
, 0xd1, L
'+' },
56 { BOXDRAW_DOWN_DOUBLE_HORIZONTAL
, 0xd2, L
'+' },
57 { BOXDRAW_DOUBLE_DOWN_HORIZONTAL
, 0xcb, L
'+' },
58 { BOXDRAW_UP_HORIZONTAL_DOUBLE
, 0xcf, L
'+' },
59 { BOXDRAW_UP_DOUBLE_HORIZONTAL
, 0xd0, L
'+' },
60 { BOXDRAW_DOUBLE_UP_HORIZONTAL
, 0xca, L
'+' },
61 { BOXDRAW_VERTICAL_HORIZONTAL_DOUBLE
, 0xd8, L
'+' },
62 { BOXDRAW_VERTICAL_DOUBLE_HORIZONTAL
, 0xd7, L
'+' },
63 { BOXDRAW_DOUBLE_VERTICAL_HORIZONTAL
, 0xce, L
'+' },
65 { BLOCKELEMENT_FULL_BLOCK
, 0xdb, L
'*' },
66 { BLOCKELEMENT_LIGHT_SHADE
, 0xb0, L
'+' },
68 { GEOMETRICSHAPE_UP_TRIANGLE
, 0x1e, L
'^' },
69 { GEOMETRICSHAPE_RIGHT_TRIANGLE
, 0x10, L
'>' },
70 { GEOMETRICSHAPE_DOWN_TRIANGLE
, 0x1f, L
'v' },
71 { GEOMETRICSHAPE_LEFT_TRIANGLE
, 0x11, L
'<' },
73 { ARROW_LEFT
, 0x3c, L
'<' },
74 { ARROW_UP
, 0x18, L
'^' },
75 { ARROW_RIGHT
, 0x3e, L
'>' },
76 { ARROW_DOWN
, 0x19, L
'v' },
78 { 0x0000, 0x00, L
'\0' }
81 CHAR16 mSetModeString
[] = { ESC
, '[', '=', '3', 'h', 0 };
82 CHAR16 mSetAttributeString
[] = { ESC
, '[', '0', 'm', ESC
, '[', '4', '0', 'm', ESC
, '[', '4', '0', 'm', 0 };
83 CHAR16 mClearScreenString
[] = { ESC
, '[', '2', 'J', 0 };
84 CHAR16 mSetCursorPositionString
[] = { ESC
, '[', '0', '0', ';', '0', '0', 'H', 0 };
87 // Body of the ConOut functions
92 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
93 IN BOOLEAN ExtendedVerification
98 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.Reset().
99 If ExtendeVerification is TRUE, then perform dependent serial device reset,
100 and set display mode to mode 0.
101 If ExtendedVerification is FALSE, only set display mode to mode 0.
105 This - Indicates the calling context.
107 ExtendedVerification - Indicates that the driver may perform a more exhaustive
108 verification operation of the device during reset.
113 The reset operation succeeds.
116 The terminal is not functioning correctly or the serial port reset fails.
121 TERMINAL_DEV
*TerminalDevice
;
123 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (This
);
126 // Perform a more exhaustive reset by resetting the serial port.
128 if (ExtendedVerification
) {
130 // Report progress code here
132 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
134 PcdGet32 (PcdStatusCodeValueRemoteConsoleReset
),
135 TerminalDevice
->DevicePath
138 Status
= TerminalDevice
->SerialIo
->Reset (TerminalDevice
->SerialIo
);
139 if (EFI_ERROR (Status
)) {
141 // Report error code here
143 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
144 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
145 PcdGet32 (PcdStatusCodeValueRemoteConsoleError
),
146 TerminalDevice
->DevicePath
153 This
->SetAttribute (This
, EFI_TEXT_ATTR (This
->Mode
->Attribute
& 0x0F, EFI_BLACK
));
155 Status
= This
->SetMode (This
, 0);
162 TerminalConOutOutputString (
163 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
169 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString().
170 The Unicode string will be converted to terminal expressible data stream
171 and send to terminal via serial port.
176 This - Indicates the calling context.
178 WString - The Null-terminated Unicode string to be displayed on
184 The string is output successfully.
187 The serial port fails to send the string out.
189 EFI_WARN_UNKNOWN_GLYPH
190 Indicates that some of the characters in the Unicode string could not
191 be rendered and are skipped.
197 TERMINAL_DEV
*TerminalDevice
;
198 EFI_SIMPLE_TEXT_OUTPUT_MODE
*Mode
;
208 // flag used to indicate whether condition happens which will cause
209 // return EFI_WARN_UNKNOWN_GLYPH
217 // get Terminal device data structure pointer.
219 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (This
);
222 // Get current display mode
226 if (Mode
->Mode
> 2) {
227 return EFI_UNSUPPORTED
;
237 for (; *WString
!= CHAR_NULL
; WString
++) {
239 switch (TerminalDevice
->TerminalType
) {
245 if (!TerminalIsValidTextGraphics (*WString
, &GraphicChar
, &AsciiChar
)) {
247 // If it's not a graphic character convert Unicode to ASCII.
249 GraphicChar
= (CHAR8
) *WString
;
251 if (!(TerminalIsValidAscii (GraphicChar
) || TerminalIsValidEfiCntlChar (GraphicChar
))) {
253 // when this driver use the OutputString to output control string,
254 // TerminalDevice->OutputEscChar is set to let the Esc char
255 // to be output to the terminal emulation software.
257 if ((GraphicChar
== 27) && TerminalDevice
->OutputEscChar
) {
265 AsciiChar
= GraphicChar
;
269 if (TerminalDevice
->TerminalType
!= PcAnsiType
) {
270 GraphicChar
= AsciiChar
;
275 Status
= TerminalDevice
->SerialIo
->Write (
276 TerminalDevice
->SerialIo
,
281 if (EFI_ERROR (Status
)) {
288 UnicodeToUtf8 (*WString
, &Utf8Char
, &ValidBytes
);
290 Status
= TerminalDevice
->SerialIo
->Write (
291 TerminalDevice
->SerialIo
,
295 if (EFI_ERROR (Status
)) {
301 // Update cursor position.
306 if (Mode
->CursorColumn
> 0) {
307 Mode
->CursorColumn
--;
312 if (Mode
->CursorRow
< (INT32
) (MaxRow
- 1)) {
317 case CHAR_CARRIAGE_RETURN
:
318 Mode
->CursorColumn
= 0;
322 if (Mode
->CursorColumn
< (INT32
) (MaxColumn
- 1)) {
324 Mode
->CursorColumn
++;
328 Mode
->CursorColumn
= 0;
329 if (Mode
->CursorRow
< (INT32
) (MaxRow
- 1)) {
341 return EFI_WARN_UNKNOWN_GLYPH
;
347 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
348 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
349 PcdGet32 (PcdStatusCodeValueRemoteConsoleOutputError
),
350 TerminalDevice
->DevicePath
353 return EFI_DEVICE_ERROR
;
358 TerminalConOutTestString (
359 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
365 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.TestString().
366 If one of the characters in the *Wstring is
367 neither valid Unicode drawing characters,
368 not ASCII code, then this function will return
374 This - Indicates the calling context.
376 WString - The Null-terminated Unicode string to be tested.
381 The terminal is capable of rendering the output string.
384 Some of the characters in the Unicode string cannot be rendered.
388 TERMINAL_DEV
*TerminalDevice
;
392 // get Terminal device data structure pointer.
394 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (This
);
396 switch (TerminalDevice
->TerminalType
) {
401 Status
= AnsiTestString (TerminalDevice
, WString
);
405 Status
= VTUTF8TestString (TerminalDevice
, WString
);
409 Status
= EFI_UNSUPPORTED
;
418 TerminalConOutQueryMode (
419 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
427 Implements EFI_SIMPLE_TEXT_OUT_PROTOCOL.QueryMode().
428 It returns information for an available text mode
429 that the terminal supports.
430 In this driver, we support text mode 80x25 (mode 0),
431 80x50 (mode 1), 100x31 (mode 2).
437 Indicates the calling context.
440 The mode number to return information on.
443 The returned columns of the requested mode.
446 The returned rows of the requested mode.
451 The requested mode information is returned.
454 The mode number is not valid.
460 if (This
->Mode
->MaxMode
> 3) {
461 return EFI_DEVICE_ERROR
;
464 if (ModeNumber
== 0) {
465 *Columns
= MODE0_COLUMN_COUNT
;
466 *Rows
= MODE0_ROW_COUNT
;
468 } else if (ModeNumber
== 1) {
469 *Columns
= MODE1_COLUMN_COUNT
;
470 *Rows
= MODE1_ROW_COUNT
;
472 } else if (ModeNumber
== 2) {
473 *Columns
= MODE2_COLUMN_COUNT
;
474 *Rows
= MODE2_ROW_COUNT
;
478 return EFI_UNSUPPORTED
;
483 TerminalConOutSetMode (
484 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
490 Implements EFI_SIMPLE_TEXT_OUT.SetMode().
491 Set the terminal to a specified display mode.
492 In this driver, we only support mode 0.
497 Indicates the calling context.
500 The text mode to set.
505 The requested text mode is set.
508 The requested text mode cannot be set because of serial device error.
511 The text mode number is not valid.
516 TERMINAL_DEV
*TerminalDevice
;
519 // get Terminal device data structure pointer.
521 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (This
);
523 if (ModeNumber
> 2) {
524 return EFI_UNSUPPORTED
;
528 // Set the current mode
530 This
->Mode
->Mode
= (INT32
) ModeNumber
;
532 This
->ClearScreen (This
);
534 TerminalDevice
->OutputEscChar
= TRUE
;
535 Status
= This
->OutputString (This
, mSetModeString
);
536 TerminalDevice
->OutputEscChar
= FALSE
;
538 if (EFI_ERROR (Status
)) {
539 return EFI_DEVICE_ERROR
;
542 This
->Mode
->Mode
= (INT32
) ModeNumber
;
544 Status
= This
->ClearScreen (This
);
545 if (EFI_ERROR (Status
)) {
546 return EFI_DEVICE_ERROR
;
555 TerminalConOutSetAttribute (
556 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
562 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetAttribute().
567 Indicates the calling context.
570 The attribute to set. Only bit0..6 are valid, all other bits
571 are undefined and must be zero.
576 The requested attribute is set.
579 The requested attribute cannot be set due to serial port error.
582 The attribute requested is not defined by EFI spec.
586 UINT8 ForegroundControl
;
587 UINT8 BackgroundControl
;
592 TERMINAL_DEV
*TerminalDevice
;
598 // get Terminal device data structure pointer.
600 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (This
);
603 // only the bit0..6 of the Attribute is valid
605 if ((Attribute
| 0x7f) != 0x7f) {
606 return EFI_UNSUPPORTED
;
610 // Skip outputting the command string for the same attribute
611 // It improves the terminal performance siginificantly
613 if (This
->Mode
->Attribute
== (INT32
) Attribute
) {
618 // convert Attribute value to terminal emulator
619 // understandable foreground color
621 switch (Attribute
& 0x07) {
624 ForegroundControl
= 30;
628 ForegroundControl
= 34;
632 ForegroundControl
= 32;
636 ForegroundControl
= 36;
640 ForegroundControl
= 31;
644 ForegroundControl
= 35;
648 ForegroundControl
= 33;
654 ForegroundControl
= 37;
659 // bit4 of the Attribute indicates bright control
660 // of terminal emulator.
662 BrightControl
= (UINT8
) ((Attribute
>> 3) & 1);
665 // convert Attribute value to terminal emulator
666 // understandable background color.
668 switch ((Attribute
>> 4) & 0x07) {
671 BackgroundControl
= 40;
675 BackgroundControl
= 44;
679 BackgroundControl
= 42;
683 BackgroundControl
= 46;
687 BackgroundControl
= 41;
691 BackgroundControl
= 45;
695 BackgroundControl
= 43;
701 BackgroundControl
= 47;
705 // terminal emulator's control sequence to set attributes
707 mSetAttributeString
[BRIGHT_CONTROL_OFFSET
] = (CHAR16
) ('0' + BrightControl
);
708 mSetAttributeString
[FOREGROUND_CONTROL_OFFSET
+ 0] = (CHAR16
) ('0' + (ForegroundControl
/ 10));
709 mSetAttributeString
[FOREGROUND_CONTROL_OFFSET
+ 1] = (CHAR16
) ('0' + (ForegroundControl
% 10));
710 mSetAttributeString
[BACKGROUND_CONTROL_OFFSET
+ 0] = (CHAR16
) ('0' + (BackgroundControl
/ 10));
711 mSetAttributeString
[BACKGROUND_CONTROL_OFFSET
+ 1] = (CHAR16
) ('0' + (BackgroundControl
% 10));
714 // save current column and row
715 // for future scrolling back use.
717 SavedColumn
= This
->Mode
->CursorColumn
;
718 SavedRow
= This
->Mode
->CursorRow
;
720 TerminalDevice
->OutputEscChar
= TRUE
;
721 Status
= This
->OutputString (This
, mSetAttributeString
);
722 TerminalDevice
->OutputEscChar
= FALSE
;
724 if (EFI_ERROR (Status
)) {
725 return EFI_DEVICE_ERROR
;
728 // scroll back to saved cursor position.
730 This
->Mode
->CursorColumn
= SavedColumn
;
731 This
->Mode
->CursorRow
= SavedRow
;
733 This
->Mode
->Attribute
= (INT32
) Attribute
;
741 TerminalConOutClearScreen (
742 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
747 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.ClearScreen().
748 It clears the ANSI terminal's display to the
749 currently selected background color.
755 Indicates the calling context.
760 The operation completed successfully.
763 The terminal screen cannot be cleared due to serial port error.
766 The terminal is not in a valid display mode.
771 TERMINAL_DEV
*TerminalDevice
;
773 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (This
);
776 // control sequence for clear screen request
778 TerminalDevice
->OutputEscChar
= TRUE
;
779 Status
= This
->OutputString (This
, mClearScreenString
);
780 TerminalDevice
->OutputEscChar
= FALSE
;
782 if (EFI_ERROR (Status
)) {
783 return EFI_DEVICE_ERROR
;
786 Status
= This
->SetCursorPosition (This
, 0, 0);
793 TerminalConOutSetCursorPosition (
794 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
801 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetCursorPosition().
806 Indicates the calling context.
809 The row to set cursor to.
812 The column to set cursor to.
817 The operation completed successfully.
820 The request fails due to serial port error.
823 The terminal is not in a valid text mode, or the cursor position
824 is invalid for current mode.
828 EFI_SIMPLE_TEXT_OUTPUT_MODE
*Mode
;
832 TERMINAL_DEV
*TerminalDevice
;
834 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (This
);
842 // get geometry of current mode
844 Status
= This
->QueryMode (
850 if (EFI_ERROR (Status
)) {
851 return EFI_UNSUPPORTED
;
854 if (Column
>= MaxColumn
|| Row
>= MaxRow
) {
855 return EFI_UNSUPPORTED
;
858 // control sequence to move the cursor
860 mSetCursorPositionString
[ROW_OFFSET
+ 0] = (CHAR16
) ('0' + ((Row
+ 1) / 10));
861 mSetCursorPositionString
[ROW_OFFSET
+ 1] = (CHAR16
) ('0' + ((Row
+ 1) % 10));
862 mSetCursorPositionString
[COLUMN_OFFSET
+ 0] = (CHAR16
) ('0' + ((Column
+ 1) / 10));
863 mSetCursorPositionString
[COLUMN_OFFSET
+ 1] = (CHAR16
) ('0' + ((Column
+ 1) % 10));
865 TerminalDevice
->OutputEscChar
= TRUE
;
866 Status
= This
->OutputString (This
, mSetCursorPositionString
);
867 TerminalDevice
->OutputEscChar
= FALSE
;
869 if (EFI_ERROR (Status
)) {
870 return EFI_DEVICE_ERROR
;
873 // update current cursor position
874 // in the Mode data structure.
876 Mode
->CursorColumn
= (INT32
) Column
;
877 Mode
->CursorRow
= (INT32
) Row
;
884 TerminalConOutEnableCursor (
885 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
891 Implements SIMPLE_TEXT_OUTPUT.EnableCursor().
892 In this driver, the cursor cannot be hidden.
897 Indicates the calling context.
900 If TRUE, the cursor is set to be visible,
901 If FALSE, the cursor is set to be invisible.
906 The request is valid.
909 The terminal does not support cursor hidden.
914 return EFI_UNSUPPORTED
;
921 TerminalIsValidTextGraphics (
923 OUT CHAR8
*PcAnsi
, OPTIONAL
924 OUT CHAR8
*Ascii OPTIONAL
930 Detects if a Unicode char is for Box Drawing text graphics.
934 Graphic - Unicode char to test.
936 PcAnsi - Optional pointer to return PCANSI equivalent of Graphic.
938 Ascii - Optional pointer to return ASCII equivalent of Graphic.
942 TRUE if Graphic is a supported Unicode Box Drawing character.
946 UNICODE_TO_CHAR
*Table
;
948 if ((((Graphic
& 0xff00) != 0x2500) && ((Graphic
& 0xff00) != 0x2100))) {
950 // Unicode drawing code charts are all in the 0x25xx range,
956 for (Table
= UnicodeToPcAnsiOrAscii
; Table
->Unicode
!= 0x0000; Table
++) {
957 if (Graphic
== Table
->Unicode
) {
958 if (PcAnsi
!= NULL
) {
959 *PcAnsi
= Table
->PcAnsi
;
963 *Ascii
= Table
->Ascii
;
974 TerminalIsValidAscii (
979 // valid ascii code lies in the extent of 0x20 ~ 0x7f
981 if ((Ascii
>= 0x20) && (Ascii
<= 0x7f)) {
989 TerminalIsValidEfiCntlChar (
994 // only support four control characters.
996 if (CharC
== CHAR_NULL
||
997 CharC
== CHAR_BACKSPACE
||
998 CharC
== CHAR_LINEFEED
||
999 CharC
== CHAR_CARRIAGE_RETURN
||