3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
25 // This list is used to define the valid extend chars.
26 // It also provides a mapping from Unicode to PCANSI or
27 // ASCII. The ASCII mapping we just made up.
30 STATIC UNICODE_TO_CHAR UnicodeToPcAnsiOrAscii
[] = {
31 { BOXDRAW_HORIZONTAL
, 0xc4, L
'-' },
32 { BOXDRAW_VERTICAL
, 0xb3, L
'|' },
33 { BOXDRAW_DOWN_RIGHT
, 0xda, L
'/' },
34 { BOXDRAW_DOWN_LEFT
, 0xbf, L
'\\' },
35 { BOXDRAW_UP_RIGHT
, 0xc0, L
'\\' },
36 { BOXDRAW_UP_LEFT
, 0xd9, L
'/' },
37 { BOXDRAW_VERTICAL_RIGHT
, 0xc3, L
'|' },
38 { BOXDRAW_VERTICAL_LEFT
, 0xb4, L
'|' },
39 { BOXDRAW_DOWN_HORIZONTAL
, 0xc2, L
'+' },
40 { BOXDRAW_UP_HORIZONTAL
, 0xc1, L
'+' },
41 { BOXDRAW_VERTICAL_HORIZONTAL
, 0xc5, L
'+' },
42 { BOXDRAW_DOUBLE_HORIZONTAL
, 0xcd, L
'-' },
43 { BOXDRAW_DOUBLE_VERTICAL
, 0xba, L
'|' },
44 { BOXDRAW_DOWN_RIGHT_DOUBLE
, 0xd5, L
'/' },
45 { BOXDRAW_DOWN_DOUBLE_RIGHT
, 0xd6, L
'/' },
46 { BOXDRAW_DOUBLE_DOWN_RIGHT
, 0xc9, L
'/' },
47 { BOXDRAW_DOWN_LEFT_DOUBLE
, 0xb8, L
'\\' },
48 { BOXDRAW_DOWN_DOUBLE_LEFT
, 0xb7, L
'\\' },
49 { BOXDRAW_DOUBLE_DOWN_LEFT
, 0xbb, L
'\\' },
50 { BOXDRAW_UP_RIGHT_DOUBLE
, 0xd4, L
'\\' },
51 { BOXDRAW_UP_DOUBLE_RIGHT
, 0xd3, L
'\\' },
52 { BOXDRAW_DOUBLE_UP_RIGHT
, 0xc8, L
'\\' },
53 { BOXDRAW_UP_LEFT_DOUBLE
, 0xbe, L
'/' },
54 { BOXDRAW_UP_DOUBLE_LEFT
, 0xbd, L
'/' },
55 { BOXDRAW_DOUBLE_UP_LEFT
, 0xbc, L
'/' },
56 { BOXDRAW_VERTICAL_RIGHT_DOUBLE
, 0xc6, L
'|' },
57 { BOXDRAW_VERTICAL_DOUBLE_RIGHT
, 0xc7, L
'|' },
58 { BOXDRAW_DOUBLE_VERTICAL_RIGHT
, 0xcc, L
'|' },
59 { BOXDRAW_VERTICAL_LEFT_DOUBLE
, 0xb5, L
'|' },
60 { BOXDRAW_VERTICAL_DOUBLE_LEFT
, 0xb6, L
'|' },
61 { BOXDRAW_DOUBLE_VERTICAL_LEFT
, 0xb9, L
'|' },
62 { BOXDRAW_DOWN_HORIZONTAL_DOUBLE
, 0xd1, L
'+' },
63 { BOXDRAW_DOWN_DOUBLE_HORIZONTAL
, 0xd2, L
'+' },
64 { BOXDRAW_DOUBLE_DOWN_HORIZONTAL
, 0xcb, L
'+' },
65 { BOXDRAW_UP_HORIZONTAL_DOUBLE
, 0xcf, L
'+' },
66 { BOXDRAW_UP_DOUBLE_HORIZONTAL
, 0xd0, L
'+' },
67 { BOXDRAW_DOUBLE_UP_HORIZONTAL
, 0xca, L
'+' },
68 { BOXDRAW_VERTICAL_HORIZONTAL_DOUBLE
, 0xd8, L
'+' },
69 { BOXDRAW_VERTICAL_DOUBLE_HORIZONTAL
, 0xd7, L
'+' },
70 { BOXDRAW_DOUBLE_VERTICAL_HORIZONTAL
, 0xce, L
'+' },
72 { BLOCKELEMENT_FULL_BLOCK
, 0xdb, L
'*' },
73 { BLOCKELEMENT_LIGHT_SHADE
, 0xb0, L
'+' },
75 { GEOMETRICSHAPE_UP_TRIANGLE
, 0x1e, L
'^' },
76 { GEOMETRICSHAPE_RIGHT_TRIANGLE
, 0x10, L
'>' },
77 { GEOMETRICSHAPE_DOWN_TRIANGLE
, 0x1f, L
'v' },
78 { GEOMETRICSHAPE_LEFT_TRIANGLE
, 0x11, L
'<' },
80 { ARROW_LEFT
, 0x3c, L
'<' },
81 { ARROW_UP
, 0x18, L
'^' },
82 { ARROW_RIGHT
, 0x3e, L
'>' },
83 { ARROW_DOWN
, 0x19, L
'v' },
85 { 0x0000, 0x00, L
'\0' }
88 CHAR16 mSetModeString
[] = { ESC
, '[', '=', '3', 'h', 0 };
89 CHAR16 mSetAttributeString
[] = { ESC
, '[', '0', 'm', ESC
, '[', '4', '0', 'm', ESC
, '[', '4', '0', 'm', 0 };
90 CHAR16 mClearScreenString
[] = { ESC
, '[', '2', 'J', 0 };
91 CHAR16 mSetCursorPositionString
[] = { ESC
, '[', '0', '0', ';', '0', '0', 'H', 0 };
94 // Body of the ConOut functions
99 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
100 IN BOOLEAN ExtendedVerification
105 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.Reset().
106 If ExtendeVerification is TRUE, then perform dependent serial device reset,
107 and set display mode to mode 0.
108 If ExtendedVerification is FALSE, only set display mode to mode 0.
112 This - Indicates the calling context.
114 ExtendedVerification - Indicates that the driver may perform a more exhaustive
115 verification operation of the device during reset.
120 The reset operation succeeds.
123 The terminal is not functioning correctly or the serial port reset fails.
128 TERMINAL_DEV
*TerminalDevice
;
130 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (This
);
133 // Perform a more exhaustive reset by resetting the serial port.
135 if (ExtendedVerification
) {
137 // Report progress code here
139 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
141 PcdGet32 (PcdStatusCodeValueRemoteConsoleReset
),
142 TerminalDevice
->DevicePath
145 Status
= TerminalDevice
->SerialIo
->Reset (TerminalDevice
->SerialIo
);
146 if (EFI_ERROR (Status
)) {
148 // Report error code here
150 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
151 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
152 PcdGet32 (PcdStatusCodeValueRemoteConsoleError
),
153 TerminalDevice
->DevicePath
160 This
->SetAttribute (This
, EFI_TEXT_ATTR (This
->Mode
->Attribute
& 0x0F, EFI_BACKGROUND_BLACK
));
162 Status
= This
->SetMode (This
, 0);
169 TerminalConOutOutputString (
170 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
176 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString().
177 The Unicode string will be converted to terminal expressible data stream
178 and send to terminal via serial port.
183 This - Indicates the calling context.
185 WString - The Null-terminated Unicode string to be displayed on
191 The string is output successfully.
194 The serial port fails to send the string out.
196 EFI_WARN_UNKNOWN_GLYPH
197 Indicates that some of the characters in the Unicode string could not
198 be rendered and are skipped.
204 TERMINAL_DEV
*TerminalDevice
;
205 EFI_SIMPLE_TEXT_OUTPUT_MODE
*Mode
;
215 // flag used to indicate whether condition happens which will cause
216 // return EFI_WARN_UNKNOWN_GLYPH
224 // get Terminal device data structure pointer.
226 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (This
);
229 // Get current display mode
233 if (Mode
->Mode
> 1) {
234 return EFI_UNSUPPORTED
;
244 for (; *WString
!= CHAR_NULL
; WString
++) {
246 switch (TerminalDevice
->TerminalType
) {
252 if (!TerminalIsValidTextGraphics (*WString
, &GraphicChar
, &AsciiChar
)) {
254 // If it's not a graphic character convert Unicode to ASCII.
256 GraphicChar
= (CHAR8
) *WString
;
258 if (!(TerminalIsValidAscii (GraphicChar
) || TerminalIsValidEfiCntlChar (GraphicChar
))) {
260 // when this driver use the OutputString to output control string,
261 // TerminalDevice->OutputEscChar is set to let the Esc char
262 // to be output to the terminal emulation software.
264 if ((GraphicChar
== 27) && TerminalDevice
->OutputEscChar
) {
272 AsciiChar
= GraphicChar
;
276 if (TerminalDevice
->TerminalType
!= PcAnsiType
) {
277 GraphicChar
= AsciiChar
;
282 Status
= TerminalDevice
->SerialIo
->Write (
283 TerminalDevice
->SerialIo
,
288 if (EFI_ERROR (Status
)) {
295 UnicodeToUtf8 (*WString
, &Utf8Char
, &ValidBytes
);
297 Status
= TerminalDevice
->SerialIo
->Write (
298 TerminalDevice
->SerialIo
,
302 if (EFI_ERROR (Status
)) {
308 // Update cursor position.
313 if (Mode
->CursorColumn
> 0) {
314 Mode
->CursorColumn
--;
319 if (Mode
->CursorRow
< (INT32
) (MaxRow
- 1)) {
324 case CHAR_CARRIAGE_RETURN
:
325 Mode
->CursorColumn
= 0;
329 if (Mode
->CursorColumn
< (INT32
) (MaxColumn
- 1)) {
331 Mode
->CursorColumn
++;
335 Mode
->CursorColumn
= 0;
336 if (Mode
->CursorRow
< (INT32
) (MaxRow
- 1)) {
348 return EFI_WARN_UNKNOWN_GLYPH
;
354 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
355 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
356 PcdGet32 (PcdStatusCodeValueRemoteConsoleOutputError
),
357 TerminalDevice
->DevicePath
360 return EFI_DEVICE_ERROR
;
365 TerminalConOutTestString (
366 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
372 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.TestString().
373 If one of the characters in the *Wstring is
374 neither valid Unicode drawing characters,
375 not ASCII code, then this function will return
381 This - Indicates the calling context.
383 WString - The Null-terminated Unicode string to be tested.
388 The terminal is capable of rendering the output string.
391 Some of the characters in the Unicode string cannot be rendered.
395 TERMINAL_DEV
*TerminalDevice
;
399 // get Terminal device data structure pointer.
401 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (This
);
403 switch (TerminalDevice
->TerminalType
) {
408 Status
= AnsiTestString (TerminalDevice
, WString
);
412 Status
= VTUTF8TestString (TerminalDevice
, WString
);
416 Status
= EFI_UNSUPPORTED
;
425 TerminalConOutQueryMode (
426 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
434 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.QueryMode().
435 It returns information for an available text mode
436 that the terminal supports.
437 In this driver, we only support text mode 80x25, which is
444 Indicates the calling context.
447 The mode number to return information on.
450 The returned columns of the requested mode.
453 The returned rows of the requested mode.
458 The requested mode information is returned.
461 The mode number is not valid.
467 if (This
->Mode
->MaxMode
> 2) {
468 return EFI_DEVICE_ERROR
;
471 if (ModeNumber
== 0) {
472 *Columns
= MODE0_COLUMN_COUNT
;
473 *Rows
= MODE0_ROW_COUNT
;
475 } else if (ModeNumber
== 1) {
476 *Columns
= MODE1_COLUMN_COUNT
;
477 *Rows
= MODE1_ROW_COUNT
;
481 return EFI_UNSUPPORTED
;
486 TerminalConOutSetMode (
487 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
493 Implements EFI_SIMPLE_TEXT_OUT.SetMode().
494 Set the terminal to a specified display mode.
495 In this driver, we only support mode 0.
500 Indicates the calling context.
503 The text mode to set.
508 The requested text mode is set.
511 The requested text mode cannot be set because of serial device error.
514 The text mode number is not valid.
519 TERMINAL_DEV
*TerminalDevice
;
522 // get Terminal device data structure pointer.
524 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (This
);
526 if (ModeNumber
> 1) {
527 return EFI_UNSUPPORTED
;
531 // Set the current mode
533 This
->Mode
->Mode
= (INT32
) ModeNumber
;
535 This
->ClearScreen (This
);
537 TerminalDevice
->OutputEscChar
= TRUE
;
538 Status
= This
->OutputString (This
, mSetModeString
);
539 TerminalDevice
->OutputEscChar
= FALSE
;
541 if (EFI_ERROR (Status
)) {
542 return EFI_DEVICE_ERROR
;
545 This
->Mode
->Mode
= (INT32
) ModeNumber
;
547 Status
= This
->ClearScreen (This
);
548 if (EFI_ERROR (Status
)) {
549 return EFI_DEVICE_ERROR
;
558 TerminalConOutSetAttribute (
559 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
565 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetAttribute().
570 Indicates the calling context.
573 The attribute to set. Only bit0..6 are valid, all other bits
574 are undefined and must be zero.
579 The requested attribute is set.
582 The requested attribute cannot be set due to serial port error.
585 The attribute requested is not defined by EFI spec.
589 UINT8 ForegroundControl
;
590 UINT8 BackgroundControl
;
595 TERMINAL_DEV
*TerminalDevice
;
601 // get Terminal device data structure pointer.
603 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (This
);
606 // only the bit0..6 of the Attribute is valid
608 if ((Attribute
| 0x7f) != 0x7f) {
609 return EFI_UNSUPPORTED
;
612 // convert Attribute value to terminal emulator
613 // understandable foreground color
615 switch (Attribute
& 0x07) {
618 ForegroundControl
= 30;
622 ForegroundControl
= 34;
626 ForegroundControl
= 32;
630 ForegroundControl
= 36;
634 ForegroundControl
= 31;
638 ForegroundControl
= 35;
642 ForegroundControl
= 33;
648 ForegroundControl
= 37;
653 // bit4 of the Attribute indicates bright control
654 // of terminal emulator.
656 BrightControl
= (UINT8
) ((Attribute
>> 3) & 1);
659 // convert Attribute value to terminal emulator
660 // understandable background color.
662 switch ((Attribute
>> 4) & 0x07) {
665 BackgroundControl
= 40;
669 BackgroundControl
= 44;
673 BackgroundControl
= 42;
677 BackgroundControl
= 46;
681 BackgroundControl
= 41;
685 BackgroundControl
= 45;
689 BackgroundControl
= 43;
695 BackgroundControl
= 47;
699 // terminal emulator's control sequence to set attributes
701 mSetAttributeString
[BRIGHT_CONTROL_OFFSET
] = (CHAR16
) ('0' + BrightControl
);
702 mSetAttributeString
[FOREGROUND_CONTROL_OFFSET
+ 0] = (CHAR16
) ('0' + (ForegroundControl
/ 10));
703 mSetAttributeString
[FOREGROUND_CONTROL_OFFSET
+ 1] = (CHAR16
) ('0' + (ForegroundControl
% 10));
704 mSetAttributeString
[BACKGROUND_CONTROL_OFFSET
+ 0] = (CHAR16
) ('0' + (BackgroundControl
/ 10));
705 mSetAttributeString
[BACKGROUND_CONTROL_OFFSET
+ 1] = (CHAR16
) ('0' + (BackgroundControl
% 10));
708 // save current column and row
709 // for future scrolling back use.
711 SavedColumn
= This
->Mode
->CursorColumn
;
712 SavedRow
= This
->Mode
->CursorRow
;
714 TerminalDevice
->OutputEscChar
= TRUE
;
715 Status
= This
->OutputString (This
, mSetAttributeString
);
716 TerminalDevice
->OutputEscChar
= FALSE
;
718 if (EFI_ERROR (Status
)) {
719 return EFI_DEVICE_ERROR
;
722 // scroll back to saved cursor position.
724 This
->Mode
->CursorColumn
= SavedColumn
;
725 This
->Mode
->CursorRow
= SavedRow
;
727 This
->Mode
->Attribute
= (INT32
) Attribute
;
735 TerminalConOutClearScreen (
736 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
741 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.ClearScreen().
742 It clears the ANSI terminal's display to the
743 currently selected background color.
749 Indicates the calling context.
754 The operation completed successfully.
757 The terminal screen cannot be cleared due to serial port error.
760 The terminal is not in a valid display mode.
765 TERMINAL_DEV
*TerminalDevice
;
767 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (This
);
770 // control sequence for clear screen request
772 TerminalDevice
->OutputEscChar
= TRUE
;
773 Status
= This
->OutputString (This
, mClearScreenString
);
774 TerminalDevice
->OutputEscChar
= FALSE
;
776 if (EFI_ERROR (Status
)) {
777 return EFI_DEVICE_ERROR
;
780 Status
= This
->SetCursorPosition (This
, 0, 0);
787 TerminalConOutSetCursorPosition (
788 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
795 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetCursorPosition().
800 Indicates the calling context.
803 The row to set cursor to.
806 The column to set cursor to.
811 The operation completed successfully.
814 The request fails due to serial port error.
817 The terminal is not in a valid text mode, or the cursor position
818 is invalid for current mode.
822 EFI_SIMPLE_TEXT_OUTPUT_MODE
*Mode
;
826 TERMINAL_DEV
*TerminalDevice
;
828 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (This
);
836 // get geometry of current mode
838 Status
= This
->QueryMode (
844 if (EFI_ERROR (Status
)) {
845 return EFI_UNSUPPORTED
;
848 if (Column
>= MaxColumn
|| Row
>= MaxRow
) {
849 return EFI_UNSUPPORTED
;
852 // control sequence to move the cursor
854 mSetCursorPositionString
[ROW_OFFSET
+ 0] = (CHAR16
) ('0' + ((Row
+ 1) / 10));
855 mSetCursorPositionString
[ROW_OFFSET
+ 1] = (CHAR16
) ('0' + ((Row
+ 1) % 10));
856 mSetCursorPositionString
[COLUMN_OFFSET
+ 0] = (CHAR16
) ('0' + ((Column
+ 1) / 10));
857 mSetCursorPositionString
[COLUMN_OFFSET
+ 1] = (CHAR16
) ('0' + ((Column
+ 1) % 10));
859 TerminalDevice
->OutputEscChar
= TRUE
;
860 Status
= This
->OutputString (This
, mSetCursorPositionString
);
861 TerminalDevice
->OutputEscChar
= FALSE
;
863 if (EFI_ERROR (Status
)) {
864 return EFI_DEVICE_ERROR
;
867 // update current cursor position
868 // in the Mode data structure.
870 Mode
->CursorColumn
= (INT32
) Column
;
871 Mode
->CursorRow
= (INT32
) Row
;
878 TerminalConOutEnableCursor (
879 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
885 Implements SIMPLE_TEXT_OUTPUT.EnableCursor().
886 In this driver, the cursor cannot be hidden.
891 Indicates the calling context.
894 If TRUE, the cursor is set to be visible,
895 If FALSE, the cursor is set to be invisible.
900 The request is valid.
903 The terminal does not support cursor hidden.
908 return EFI_UNSUPPORTED
;
915 TerminalIsValidTextGraphics (
917 OUT CHAR8
*PcAnsi
, OPTIONAL
918 OUT CHAR8
*Ascii OPTIONAL
924 Detects if a Unicode char is for Box Drawing text graphics.
928 Graphic - Unicode char to test.
930 PcAnsi - Optional pointer to return PCANSI equivalent of Graphic.
932 Ascii - Optional pointer to return ASCII equivalent of Graphic.
936 TRUE if Graphic is a supported Unicode Box Drawing character.
940 UNICODE_TO_CHAR
*Table
;
942 if ((((Graphic
& 0xff00) != 0x2500) && ((Graphic
& 0xff00) != 0x2100))) {
944 // Unicode drawing code charts are all in the 0x25xx range,
950 for (Table
= UnicodeToPcAnsiOrAscii
; Table
->Unicode
!= 0x0000; Table
++) {
951 if (Graphic
== Table
->Unicode
) {
952 if (PcAnsi
!= NULL
) {
953 *PcAnsi
= Table
->PcAnsi
;
957 *Ascii
= Table
->Ascii
;
968 TerminalIsValidAscii (
973 // valid ascii code lies in the extent of 0x20 ~ 0x7f
975 if ((Ascii
>= 0x20) && (Ascii
<= 0x7f)) {
983 TerminalIsValidEfiCntlChar (
988 // only support four control characters.
990 if (CharC
== CHAR_NULL
||
991 CharC
== CHAR_BACKSPACE
||
992 CharC
== CHAR_LINEFEED
||
993 CharC
== CHAR_CARRIAGE_RETURN
||