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_BACKGROUND_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
;
609 // convert Attribute value to terminal emulator
610 // understandable foreground color
612 switch (Attribute
& 0x07) {
615 ForegroundControl
= 30;
619 ForegroundControl
= 34;
623 ForegroundControl
= 32;
627 ForegroundControl
= 36;
631 ForegroundControl
= 31;
635 ForegroundControl
= 35;
639 ForegroundControl
= 33;
645 ForegroundControl
= 37;
650 // bit4 of the Attribute indicates bright control
651 // of terminal emulator.
653 BrightControl
= (UINT8
) ((Attribute
>> 3) & 1);
656 // convert Attribute value to terminal emulator
657 // understandable background color.
659 switch ((Attribute
>> 4) & 0x07) {
662 BackgroundControl
= 40;
666 BackgroundControl
= 44;
670 BackgroundControl
= 42;
674 BackgroundControl
= 46;
678 BackgroundControl
= 41;
682 BackgroundControl
= 45;
686 BackgroundControl
= 43;
692 BackgroundControl
= 47;
696 // terminal emulator's control sequence to set attributes
698 mSetAttributeString
[BRIGHT_CONTROL_OFFSET
] = (CHAR16
) ('0' + BrightControl
);
699 mSetAttributeString
[FOREGROUND_CONTROL_OFFSET
+ 0] = (CHAR16
) ('0' + (ForegroundControl
/ 10));
700 mSetAttributeString
[FOREGROUND_CONTROL_OFFSET
+ 1] = (CHAR16
) ('0' + (ForegroundControl
% 10));
701 mSetAttributeString
[BACKGROUND_CONTROL_OFFSET
+ 0] = (CHAR16
) ('0' + (BackgroundControl
/ 10));
702 mSetAttributeString
[BACKGROUND_CONTROL_OFFSET
+ 1] = (CHAR16
) ('0' + (BackgroundControl
% 10));
705 // save current column and row
706 // for future scrolling back use.
708 SavedColumn
= This
->Mode
->CursorColumn
;
709 SavedRow
= This
->Mode
->CursorRow
;
711 TerminalDevice
->OutputEscChar
= TRUE
;
712 Status
= This
->OutputString (This
, mSetAttributeString
);
713 TerminalDevice
->OutputEscChar
= FALSE
;
715 if (EFI_ERROR (Status
)) {
716 return EFI_DEVICE_ERROR
;
719 // scroll back to saved cursor position.
721 This
->Mode
->CursorColumn
= SavedColumn
;
722 This
->Mode
->CursorRow
= SavedRow
;
724 This
->Mode
->Attribute
= (INT32
) Attribute
;
732 TerminalConOutClearScreen (
733 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
738 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.ClearScreen().
739 It clears the ANSI terminal's display to the
740 currently selected background color.
746 Indicates the calling context.
751 The operation completed successfully.
754 The terminal screen cannot be cleared due to serial port error.
757 The terminal is not in a valid display mode.
762 TERMINAL_DEV
*TerminalDevice
;
764 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (This
);
767 // control sequence for clear screen request
769 TerminalDevice
->OutputEscChar
= TRUE
;
770 Status
= This
->OutputString (This
, mClearScreenString
);
771 TerminalDevice
->OutputEscChar
= FALSE
;
773 if (EFI_ERROR (Status
)) {
774 return EFI_DEVICE_ERROR
;
777 Status
= This
->SetCursorPosition (This
, 0, 0);
784 TerminalConOutSetCursorPosition (
785 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
792 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetCursorPosition().
797 Indicates the calling context.
800 The row to set cursor to.
803 The column to set cursor to.
808 The operation completed successfully.
811 The request fails due to serial port error.
814 The terminal is not in a valid text mode, or the cursor position
815 is invalid for current mode.
819 EFI_SIMPLE_TEXT_OUTPUT_MODE
*Mode
;
823 TERMINAL_DEV
*TerminalDevice
;
825 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (This
);
833 // get geometry of current mode
835 Status
= This
->QueryMode (
841 if (EFI_ERROR (Status
)) {
842 return EFI_UNSUPPORTED
;
845 if (Column
>= MaxColumn
|| Row
>= MaxRow
) {
846 return EFI_UNSUPPORTED
;
849 // control sequence to move the cursor
851 mSetCursorPositionString
[ROW_OFFSET
+ 0] = (CHAR16
) ('0' + ((Row
+ 1) / 10));
852 mSetCursorPositionString
[ROW_OFFSET
+ 1] = (CHAR16
) ('0' + ((Row
+ 1) % 10));
853 mSetCursorPositionString
[COLUMN_OFFSET
+ 0] = (CHAR16
) ('0' + ((Column
+ 1) / 10));
854 mSetCursorPositionString
[COLUMN_OFFSET
+ 1] = (CHAR16
) ('0' + ((Column
+ 1) % 10));
856 TerminalDevice
->OutputEscChar
= TRUE
;
857 Status
= This
->OutputString (This
, mSetCursorPositionString
);
858 TerminalDevice
->OutputEscChar
= FALSE
;
860 if (EFI_ERROR (Status
)) {
861 return EFI_DEVICE_ERROR
;
864 // update current cursor position
865 // in the Mode data structure.
867 Mode
->CursorColumn
= (INT32
) Column
;
868 Mode
->CursorRow
= (INT32
) Row
;
875 TerminalConOutEnableCursor (
876 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
882 Implements SIMPLE_TEXT_OUTPUT.EnableCursor().
883 In this driver, the cursor cannot be hidden.
888 Indicates the calling context.
891 If TRUE, the cursor is set to be visible,
892 If FALSE, the cursor is set to be invisible.
897 The request is valid.
900 The terminal does not support cursor hidden.
905 return EFI_UNSUPPORTED
;
912 TerminalIsValidTextGraphics (
914 OUT CHAR8
*PcAnsi
, OPTIONAL
915 OUT CHAR8
*Ascii OPTIONAL
921 Detects if a Unicode char is for Box Drawing text graphics.
925 Graphic - Unicode char to test.
927 PcAnsi - Optional pointer to return PCANSI equivalent of Graphic.
929 Ascii - Optional pointer to return ASCII equivalent of Graphic.
933 TRUE if Graphic is a supported Unicode Box Drawing character.
937 UNICODE_TO_CHAR
*Table
;
939 if ((((Graphic
& 0xff00) != 0x2500) && ((Graphic
& 0xff00) != 0x2100))) {
941 // Unicode drawing code charts are all in the 0x25xx range,
947 for (Table
= UnicodeToPcAnsiOrAscii
; Table
->Unicode
!= 0x0000; Table
++) {
948 if (Graphic
== Table
->Unicode
) {
949 if (PcAnsi
!= NULL
) {
950 *PcAnsi
= Table
->PcAnsi
;
954 *Ascii
= Table
->Ascii
;
965 TerminalIsValidAscii (
970 // valid ascii code lies in the extent of 0x20 ~ 0x7f
972 if ((Ascii
>= 0x20) && (Ascii
<= 0x7f)) {
980 TerminalIsValidEfiCntlChar (
985 // only support four control characters.
987 if (CharC
== CHAR_NULL
||
988 CharC
== CHAR_BACKSPACE
||
989 CharC
== CHAR_LINEFEED
||
990 CharC
== CHAR_CARRIAGE_RETURN
||