]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Console/TerminalDxe/TerminalConOut.c
b11e83f4f24a648ac3015f4f87a21a2c8806a44b
[mirror_edk2.git] / MdeModulePkg / Universal / Console / TerminalDxe / TerminalConOut.c
1 /** @file
2 Implementation for EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL protocol.
3
4 Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
5 Copyright (C) 2016 Silicon Graphics, Inc. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include "Terminal.h"
17
18 //
19 // This list is used to define the valid extend chars.
20 // It also provides a mapping from Unicode to PCANSI or
21 // ASCII. The ASCII mapping we just made up.
22 //
23 //
24 UNICODE_TO_CHAR UnicodeToPcAnsiOrAscii[] = {
25 { BOXDRAW_HORIZONTAL, 0xc4, L'-' },
26 { BOXDRAW_VERTICAL, 0xb3, L'|' },
27 { BOXDRAW_DOWN_RIGHT, 0xda, L'/' },
28 { BOXDRAW_DOWN_LEFT, 0xbf, L'\\' },
29 { BOXDRAW_UP_RIGHT, 0xc0, L'\\' },
30 { BOXDRAW_UP_LEFT, 0xd9, L'/' },
31 { BOXDRAW_VERTICAL_RIGHT, 0xc3, L'|' },
32 { BOXDRAW_VERTICAL_LEFT, 0xb4, L'|' },
33 { BOXDRAW_DOWN_HORIZONTAL, 0xc2, L'+' },
34 { BOXDRAW_UP_HORIZONTAL, 0xc1, L'+' },
35 { BOXDRAW_VERTICAL_HORIZONTAL, 0xc5, L'+' },
36 { BOXDRAW_DOUBLE_HORIZONTAL, 0xcd, L'-' },
37 { BOXDRAW_DOUBLE_VERTICAL, 0xba, L'|' },
38 { BOXDRAW_DOWN_RIGHT_DOUBLE, 0xd5, L'/' },
39 { BOXDRAW_DOWN_DOUBLE_RIGHT, 0xd6, L'/' },
40 { BOXDRAW_DOUBLE_DOWN_RIGHT, 0xc9, L'/' },
41 { BOXDRAW_DOWN_LEFT_DOUBLE, 0xb8, L'\\' },
42 { BOXDRAW_DOWN_DOUBLE_LEFT, 0xb7, L'\\' },
43 { BOXDRAW_DOUBLE_DOWN_LEFT, 0xbb, L'\\' },
44 { BOXDRAW_UP_RIGHT_DOUBLE, 0xd4, L'\\' },
45 { BOXDRAW_UP_DOUBLE_RIGHT, 0xd3, L'\\' },
46 { BOXDRAW_DOUBLE_UP_RIGHT, 0xc8, L'\\' },
47 { BOXDRAW_UP_LEFT_DOUBLE, 0xbe, L'/' },
48 { BOXDRAW_UP_DOUBLE_LEFT, 0xbd, L'/' },
49 { BOXDRAW_DOUBLE_UP_LEFT, 0xbc, L'/' },
50 { BOXDRAW_VERTICAL_RIGHT_DOUBLE, 0xc6, L'|' },
51 { BOXDRAW_VERTICAL_DOUBLE_RIGHT, 0xc7, L'|' },
52 { BOXDRAW_DOUBLE_VERTICAL_RIGHT, 0xcc, L'|' },
53 { BOXDRAW_VERTICAL_LEFT_DOUBLE, 0xb5, L'|' },
54 { BOXDRAW_VERTICAL_DOUBLE_LEFT, 0xb6, L'|' },
55 { BOXDRAW_DOUBLE_VERTICAL_LEFT, 0xb9, L'|' },
56 { BOXDRAW_DOWN_HORIZONTAL_DOUBLE, 0xd1, L'+' },
57 { BOXDRAW_DOWN_DOUBLE_HORIZONTAL, 0xd2, L'+' },
58 { BOXDRAW_DOUBLE_DOWN_HORIZONTAL, 0xcb, L'+' },
59 { BOXDRAW_UP_HORIZONTAL_DOUBLE, 0xcf, L'+' },
60 { BOXDRAW_UP_DOUBLE_HORIZONTAL, 0xd0, L'+' },
61 { BOXDRAW_DOUBLE_UP_HORIZONTAL, 0xca, L'+' },
62 { BOXDRAW_VERTICAL_HORIZONTAL_DOUBLE, 0xd8, L'+' },
63 { BOXDRAW_VERTICAL_DOUBLE_HORIZONTAL, 0xd7, L'+' },
64 { BOXDRAW_DOUBLE_VERTICAL_HORIZONTAL, 0xce, L'+' },
65
66 { BLOCKELEMENT_FULL_BLOCK, 0xdb, L'*' },
67 { BLOCKELEMENT_LIGHT_SHADE, 0xb0, L'+' },
68
69 { GEOMETRICSHAPE_UP_TRIANGLE, 0x1e, L'^' },
70 { GEOMETRICSHAPE_RIGHT_TRIANGLE, 0x10, L'>' },
71 { GEOMETRICSHAPE_DOWN_TRIANGLE, 0x1f, L'v' },
72 { GEOMETRICSHAPE_LEFT_TRIANGLE, 0x11, L'<' },
73
74 { ARROW_LEFT, 0x3c, L'<' },
75 { ARROW_UP, 0x18, L'^' },
76 { ARROW_RIGHT, 0x3e, L'>' },
77 { ARROW_DOWN, 0x19, L'v' },
78
79 { 0x0000, 0x00, L'\0' }
80 };
81
82 CHAR16 mSetModeString[] = { ESC, '[', '=', '3', 'h', 0 };
83 CHAR16 mSetAttributeString[] = { ESC, '[', '0', 'm', ESC, '[', '4', '0', 'm', ESC, '[', '4', '0', 'm', 0 };
84 CHAR16 mClearScreenString[] = { ESC, '[', '2', 'J', 0 };
85 CHAR16 mSetCursorPositionString[] = { ESC, '[', '0', '0', ';', '0', '0', 'H', 0 };
86
87 //
88 // Body of the ConOut functions
89 //
90
91 /**
92 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.Reset().
93
94 If ExtendeVerification is TRUE, then perform dependent serial device reset,
95 and set display mode to mode 0.
96 If ExtendedVerification is FALSE, only set display mode to mode 0.
97
98 @param This Indicates the calling context.
99 @param ExtendedVerification Indicates that the driver may perform a more
100 exhaustive verification operation of the device
101 during reset.
102
103 @retval EFI_SUCCESS The reset operation succeeds.
104 @retval EFI_DEVICE_ERROR The terminal is not functioning correctly or the serial port reset fails.
105
106 **/
107 EFI_STATUS
108 EFIAPI
109 TerminalConOutReset (
110 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
111 IN BOOLEAN ExtendedVerification
112 )
113 {
114 EFI_STATUS Status;
115 TERMINAL_DEV *TerminalDevice;
116
117 TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This);
118
119 //
120 // Perform a more exhaustive reset by resetting the serial port.
121 //
122 if (ExtendedVerification) {
123 //
124 // Report progress code here
125 //
126 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
127 EFI_PROGRESS_CODE,
128 (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_PC_RESET),
129 TerminalDevice->DevicePath
130 );
131
132 Status = TerminalDevice->SerialIo->Reset (TerminalDevice->SerialIo);
133 if (EFI_ERROR (Status)) {
134 //
135 // Report error code here
136 //
137 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
138 EFI_ERROR_CODE | EFI_ERROR_MINOR,
139 (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_CONTROLLER_ERROR),
140 TerminalDevice->DevicePath
141 );
142
143 return Status;
144 }
145 }
146
147 This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BLACK));
148
149 Status = This->SetMode (This, 0);
150
151 return Status;
152 }
153
154
155 /**
156 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString().
157
158 The Unicode string will be converted to terminal expressible data stream
159 and send to terminal via serial port.
160
161 @param This Indicates the calling context.
162 @param WString The Null-terminated Unicode string to be displayed
163 on the terminal screen.
164
165 @retval EFI_SUCCESS The string is output successfully.
166 @retval EFI_DEVICE_ERROR The serial port fails to send the string out.
167 @retval EFI_WARN_UNKNOWN_GLYPH Indicates that some of the characters in the Unicode string could not
168 be rendered and are skipped.
169 @retval EFI_UNSUPPORTED If current display mode is out of range.
170
171 **/
172 EFI_STATUS
173 EFIAPI
174 TerminalConOutOutputString (
175 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
176 IN CHAR16 *WString
177 )
178 {
179 TERMINAL_DEV *TerminalDevice;
180 EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode;
181 UINTN MaxColumn;
182 UINTN MaxRow;
183 UINTN Length;
184 UTF8_CHAR Utf8Char;
185 CHAR8 GraphicChar;
186 CHAR8 AsciiChar;
187 EFI_STATUS Status;
188 UINT8 ValidBytes;
189 //
190 // flag used to indicate whether condition happens which will cause
191 // return EFI_WARN_UNKNOWN_GLYPH
192 //
193 BOOLEAN Warning;
194
195 ValidBytes = 0;
196 Warning = FALSE;
197 AsciiChar = 0;
198
199 //
200 // get Terminal device data structure pointer.
201 //
202 TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This);
203
204 //
205 // Get current display mode
206 //
207 Mode = This->Mode;
208
209 if (Mode->Mode >= Mode->MaxMode) {
210 return EFI_UNSUPPORTED;
211 }
212
213 This->QueryMode (
214 This,
215 Mode->Mode,
216 &MaxColumn,
217 &MaxRow
218 );
219
220 for (; *WString != CHAR_NULL; WString++) {
221
222 switch (TerminalDevice->TerminalType) {
223
224 case PCANSITYPE:
225 case VT100TYPE:
226 case VT100PLUSTYPE:
227 case TTYTERMTYPE:
228
229 if (!TerminalIsValidTextGraphics (*WString, &GraphicChar, &AsciiChar)) {
230 //
231 // If it's not a graphic character convert Unicode to ASCII.
232 //
233 GraphicChar = (CHAR8) *WString;
234
235 if (!(TerminalIsValidAscii (GraphicChar) || TerminalIsValidEfiCntlChar (GraphicChar))) {
236 //
237 // when this driver use the OutputString to output control string,
238 // TerminalDevice->OutputEscChar is set to let the Esc char
239 // to be output to the terminal emulation software.
240 //
241 if ((GraphicChar == 27) && TerminalDevice->OutputEscChar) {
242 GraphicChar = 27;
243 } else {
244 GraphicChar = '?';
245 Warning = TRUE;
246 }
247 }
248
249 AsciiChar = GraphicChar;
250
251 }
252
253 if (TerminalDevice->TerminalType != PCANSITYPE) {
254 GraphicChar = AsciiChar;
255 }
256
257 Length = 1;
258
259 Status = TerminalDevice->SerialIo->Write (
260 TerminalDevice->SerialIo,
261 &Length,
262 &GraphicChar
263 );
264
265 if (EFI_ERROR (Status)) {
266 goto OutputError;
267 }
268
269 break;
270
271 case VTUTF8TYPE:
272 UnicodeToUtf8 (*WString, &Utf8Char, &ValidBytes);
273 Length = ValidBytes;
274 Status = TerminalDevice->SerialIo->Write (
275 TerminalDevice->SerialIo,
276 &Length,
277 (UINT8 *) &Utf8Char
278 );
279 if (EFI_ERROR (Status)) {
280 goto OutputError;
281 }
282 break;
283 }
284 //
285 // Update cursor position.
286 //
287 switch (*WString) {
288
289 case CHAR_BACKSPACE:
290 if (Mode->CursorColumn > 0) {
291 Mode->CursorColumn--;
292 }
293 break;
294
295 case CHAR_LINEFEED:
296 if (Mode->CursorRow < (INT32) (MaxRow - 1)) {
297 Mode->CursorRow++;
298 }
299 break;
300
301 case CHAR_CARRIAGE_RETURN:
302 Mode->CursorColumn = 0;
303 break;
304
305 default:
306 if (Mode->CursorColumn < (INT32) (MaxColumn - 1)) {
307
308 Mode->CursorColumn++;
309
310 } else {
311
312 Mode->CursorColumn = 0;
313 if (Mode->CursorRow < (INT32) (MaxRow - 1)) {
314 Mode->CursorRow++;
315 }
316
317 if (TerminalDevice->TerminalType == TTYTERMTYPE &&
318 !TerminalDevice->OutputEscChar) {
319 //
320 // We've written the last character on the line. The
321 // terminal doesn't actually wrap its cursor until we print
322 // the next character, but the driver thinks it has wrapped
323 // already. Print CR LF to synchronize the terminal with
324 // the driver, but only if we're not in the middle of
325 // printing an escape sequence.
326 //
327 CHAR8 CrLfStr[] = {'\r', '\n'};
328
329 Length = sizeof(CrLfStr);
330
331 Status = TerminalDevice->SerialIo->Write (
332 TerminalDevice->SerialIo,
333 &Length,
334 CrLfStr
335 );
336
337 if (EFI_ERROR (Status)) {
338 goto OutputError;
339 }
340 }
341 }
342 break;
343
344 };
345
346 }
347
348 if (Warning) {
349 return EFI_WARN_UNKNOWN_GLYPH;
350 }
351
352 return EFI_SUCCESS;
353
354 OutputError:
355 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
356 EFI_ERROR_CODE | EFI_ERROR_MINOR,
357 (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_OUTPUT_ERROR),
358 TerminalDevice->DevicePath
359 );
360
361 return EFI_DEVICE_ERROR;
362 }
363
364
365 /**
366 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.TestString().
367
368 If one of the characters in the *Wstring is
369 neither valid Unicode drawing characters,
370 not ASCII code, then this function will return
371 EFI_UNSUPPORTED.
372
373 @param This Indicates the calling context.
374 @param WString The Null-terminated Unicode string to be tested.
375
376 @retval EFI_SUCCESS The terminal is capable of rendering the output string.
377 @retval EFI_UNSUPPORTED Some of the characters in the Unicode string cannot be rendered.
378
379 **/
380 EFI_STATUS
381 EFIAPI
382 TerminalConOutTestString (
383 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
384 IN CHAR16 *WString
385 )
386 {
387 TERMINAL_DEV *TerminalDevice;
388 EFI_STATUS Status;
389
390 //
391 // get Terminal device data structure pointer.
392 //
393 TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This);
394
395 switch (TerminalDevice->TerminalType) {
396
397 case PCANSITYPE:
398 case VT100TYPE:
399 case VT100PLUSTYPE:
400 case TTYTERMTYPE:
401 Status = AnsiTestString (TerminalDevice, WString);
402 break;
403
404 case VTUTF8TYPE:
405 Status = VTUTF8TestString (TerminalDevice, WString);
406 break;
407
408 default:
409 Status = EFI_UNSUPPORTED;
410 break;
411 }
412
413 return Status;
414 }
415
416
417 /**
418 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.QueryMode().
419
420 It returns information for an available text mode
421 that the terminal supports.
422
423 @param This Indicates the calling context.
424 @param ModeNumber The mode number to return information on.
425 @param Columns The returned columns of the requested mode.
426 @param Rows The returned rows of the requested mode.
427
428 @retval EFI_SUCCESS The requested mode information is returned.
429 @retval EFI_UNSUPPORTED The mode number is not valid.
430
431 **/
432 EFI_STATUS
433 EFIAPI
434 TerminalConOutQueryMode (
435 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
436 IN UINTN ModeNumber,
437 OUT UINTN *Columns,
438 OUT UINTN *Rows
439 )
440 {
441 TERMINAL_DEV *TerminalDevice;
442
443 if (ModeNumber >= (UINTN) This->Mode->MaxMode) {
444 return EFI_UNSUPPORTED;
445 }
446
447 //
448 // Get Terminal device data structure pointer.
449 //
450 TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This);
451 *Columns = TerminalDevice->TerminalConsoleModeData[ModeNumber].Columns;
452 *Rows = TerminalDevice->TerminalConsoleModeData[ModeNumber].Rows;
453
454 return EFI_SUCCESS;
455 }
456
457
458 /**
459 Implements EFI_SIMPLE_TEXT_OUT.SetMode().
460
461 Set the terminal to a specified display mode.
462 In this driver, we only support mode 0.
463
464 @param This Indicates the calling context.
465 @param ModeNumber The text mode to set.
466
467 @retval EFI_SUCCESS The requested text mode is set.
468 @retval EFI_DEVICE_ERROR The requested text mode cannot be set
469 because of serial device error.
470 @retval EFI_UNSUPPORTED The text mode number is not valid.
471
472 **/
473 EFI_STATUS
474 EFIAPI
475 TerminalConOutSetMode (
476 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
477 IN UINTN ModeNumber
478 )
479 {
480 EFI_STATUS Status;
481 TERMINAL_DEV *TerminalDevice;
482
483 //
484 // get Terminal device data structure pointer.
485 //
486 TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This);
487
488 if (ModeNumber >= (UINTN) This->Mode->MaxMode) {
489 return EFI_UNSUPPORTED;
490 }
491
492 //
493 // Set the current mode
494 //
495 This->Mode->Mode = (INT32) ModeNumber;
496
497 This->ClearScreen (This);
498
499 TerminalDevice->OutputEscChar = TRUE;
500 Status = This->OutputString (This, mSetModeString);
501 TerminalDevice->OutputEscChar = FALSE;
502
503 if (EFI_ERROR (Status)) {
504 return EFI_DEVICE_ERROR;
505 }
506
507 This->Mode->Mode = (INT32) ModeNumber;
508
509 Status = This->ClearScreen (This);
510 if (EFI_ERROR (Status)) {
511 return EFI_DEVICE_ERROR;
512 }
513
514 return EFI_SUCCESS;
515
516 }
517
518
519 /**
520 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetAttribute().
521
522 @param This Indicates the calling context.
523 @param Attribute The attribute to set. Only bit0..6 are valid, all other bits
524 are undefined and must be zero.
525
526 @retval EFI_SUCCESS The requested attribute is set.
527 @retval EFI_DEVICE_ERROR The requested attribute cannot be set due to serial port error.
528 @retval EFI_UNSUPPORTED The attribute requested is not defined by EFI spec.
529
530 **/
531 EFI_STATUS
532 EFIAPI
533 TerminalConOutSetAttribute (
534 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
535 IN UINTN Attribute
536 )
537 {
538 UINT8 ForegroundControl;
539 UINT8 BackgroundControl;
540 UINT8 BrightControl;
541 INT32 SavedColumn;
542 INT32 SavedRow;
543 EFI_STATUS Status;
544 TERMINAL_DEV *TerminalDevice;
545
546 SavedColumn = 0;
547 SavedRow = 0;
548
549 //
550 // get Terminal device data structure pointer.
551 //
552 TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This);
553
554 //
555 // only the bit0..6 of the Attribute is valid
556 //
557 if ((Attribute | 0x7f) != 0x7f) {
558 return EFI_UNSUPPORTED;
559 }
560
561 //
562 // Skip outputting the command string for the same attribute
563 // It improves the terminal performance significantly
564 //
565 if (This->Mode->Attribute == (INT32) Attribute) {
566 return EFI_SUCCESS;
567 }
568
569 //
570 // convert Attribute value to terminal emulator
571 // understandable foreground color
572 //
573 switch (Attribute & 0x07) {
574
575 case EFI_BLACK:
576 ForegroundControl = 30;
577 break;
578
579 case EFI_BLUE:
580 ForegroundControl = 34;
581 break;
582
583 case EFI_GREEN:
584 ForegroundControl = 32;
585 break;
586
587 case EFI_CYAN:
588 ForegroundControl = 36;
589 break;
590
591 case EFI_RED:
592 ForegroundControl = 31;
593 break;
594
595 case EFI_MAGENTA:
596 ForegroundControl = 35;
597 break;
598
599 case EFI_BROWN:
600 ForegroundControl = 33;
601 break;
602
603 default:
604
605 case EFI_LIGHTGRAY:
606 ForegroundControl = 37;
607 break;
608
609 }
610 //
611 // bit4 of the Attribute indicates bright control
612 // of terminal emulator.
613 //
614 BrightControl = (UINT8) ((Attribute >> 3) & 1);
615
616 //
617 // convert Attribute value to terminal emulator
618 // understandable background color.
619 //
620 switch ((Attribute >> 4) & 0x07) {
621
622 case EFI_BLACK:
623 BackgroundControl = 40;
624 break;
625
626 case EFI_BLUE:
627 BackgroundControl = 44;
628 break;
629
630 case EFI_GREEN:
631 BackgroundControl = 42;
632 break;
633
634 case EFI_CYAN:
635 BackgroundControl = 46;
636 break;
637
638 case EFI_RED:
639 BackgroundControl = 41;
640 break;
641
642 case EFI_MAGENTA:
643 BackgroundControl = 45;
644 break;
645
646 case EFI_BROWN:
647 BackgroundControl = 43;
648 break;
649
650 default:
651
652 case EFI_LIGHTGRAY:
653 BackgroundControl = 47;
654 break;
655 }
656 //
657 // terminal emulator's control sequence to set attributes
658 //
659 mSetAttributeString[BRIGHT_CONTROL_OFFSET] = (CHAR16) ('0' + BrightControl);
660 mSetAttributeString[FOREGROUND_CONTROL_OFFSET + 0] = (CHAR16) ('0' + (ForegroundControl / 10));
661 mSetAttributeString[FOREGROUND_CONTROL_OFFSET + 1] = (CHAR16) ('0' + (ForegroundControl % 10));
662 mSetAttributeString[BACKGROUND_CONTROL_OFFSET + 0] = (CHAR16) ('0' + (BackgroundControl / 10));
663 mSetAttributeString[BACKGROUND_CONTROL_OFFSET + 1] = (CHAR16) ('0' + (BackgroundControl % 10));
664
665 //
666 // save current column and row
667 // for future scrolling back use.
668 //
669 SavedColumn = This->Mode->CursorColumn;
670 SavedRow = This->Mode->CursorRow;
671
672 TerminalDevice->OutputEscChar = TRUE;
673 Status = This->OutputString (This, mSetAttributeString);
674 TerminalDevice->OutputEscChar = FALSE;
675
676 if (EFI_ERROR (Status)) {
677 return EFI_DEVICE_ERROR;
678 }
679 //
680 // scroll back to saved cursor position.
681 //
682 This->Mode->CursorColumn = SavedColumn;
683 This->Mode->CursorRow = SavedRow;
684
685 This->Mode->Attribute = (INT32) Attribute;
686
687 return EFI_SUCCESS;
688
689 }
690
691
692 /**
693 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.ClearScreen().
694 It clears the ANSI terminal's display to the
695 currently selected background color.
696
697 @param This Indicates the calling context.
698
699 @retval EFI_SUCCESS The operation completed successfully.
700 @retval EFI_DEVICE_ERROR The terminal screen cannot be cleared due to serial port error.
701 @retval EFI_UNSUPPORTED The terminal is not in a valid display mode.
702
703 **/
704 EFI_STATUS
705 EFIAPI
706 TerminalConOutClearScreen (
707 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
708 )
709 {
710 EFI_STATUS Status;
711 TERMINAL_DEV *TerminalDevice;
712
713 TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This);
714
715 //
716 // control sequence for clear screen request
717 //
718 TerminalDevice->OutputEscChar = TRUE;
719 Status = This->OutputString (This, mClearScreenString);
720 TerminalDevice->OutputEscChar = FALSE;
721
722 if (EFI_ERROR (Status)) {
723 return EFI_DEVICE_ERROR;
724 }
725
726 Status = This->SetCursorPosition (This, 0, 0);
727
728 return Status;
729 }
730
731
732 /**
733 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetCursorPosition().
734
735 @param This Indicates the calling context.
736 @param Column The row to set cursor to.
737 @param Row The column to set cursor to.
738
739 @retval EFI_SUCCESS The operation completed successfully.
740 @retval EFI_DEVICE_ERROR The request fails due to serial port error.
741 @retval EFI_UNSUPPORTED The terminal is not in a valid text mode, or the cursor position
742 is invalid for current mode.
743
744 **/
745 EFI_STATUS
746 EFIAPI
747 TerminalConOutSetCursorPosition (
748 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
749 IN UINTN Column,
750 IN UINTN Row
751 )
752 {
753 EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode;
754 UINTN MaxColumn;
755 UINTN MaxRow;
756 EFI_STATUS Status;
757 TERMINAL_DEV *TerminalDevice;
758
759 TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This);
760
761 //
762 // get current mode
763 //
764 Mode = This->Mode;
765
766 //
767 // get geometry of current mode
768 //
769 Status = This->QueryMode (
770 This,
771 Mode->Mode,
772 &MaxColumn,
773 &MaxRow
774 );
775 if (EFI_ERROR (Status)) {
776 return EFI_UNSUPPORTED;
777 }
778
779 if (Column >= MaxColumn || Row >= MaxRow) {
780 return EFI_UNSUPPORTED;
781 }
782 //
783 // control sequence to move the cursor
784 //
785 mSetCursorPositionString[ROW_OFFSET + 0] = (CHAR16) ('0' + ((Row + 1) / 10));
786 mSetCursorPositionString[ROW_OFFSET + 1] = (CHAR16) ('0' + ((Row + 1) % 10));
787 mSetCursorPositionString[COLUMN_OFFSET + 0] = (CHAR16) ('0' + ((Column + 1) / 10));
788 mSetCursorPositionString[COLUMN_OFFSET + 1] = (CHAR16) ('0' + ((Column + 1) % 10));
789
790 TerminalDevice->OutputEscChar = TRUE;
791 Status = This->OutputString (This, mSetCursorPositionString);
792 TerminalDevice->OutputEscChar = FALSE;
793
794 if (EFI_ERROR (Status)) {
795 return EFI_DEVICE_ERROR;
796 }
797 //
798 // update current cursor position
799 // in the Mode data structure.
800 //
801 Mode->CursorColumn = (INT32) Column;
802 Mode->CursorRow = (INT32) Row;
803
804 return EFI_SUCCESS;
805 }
806
807
808 /**
809 Implements SIMPLE_TEXT_OUTPUT.EnableCursor().
810
811 In this driver, the cursor cannot be hidden.
812
813 @param This Indicates the calling context.
814 @param Visible If TRUE, the cursor is set to be visible,
815 If FALSE, the cursor is set to be invisible.
816
817 @retval EFI_SUCCESS The request is valid.
818 @retval EFI_UNSUPPORTED The terminal does not support cursor hidden.
819
820 **/
821 EFI_STATUS
822 EFIAPI
823 TerminalConOutEnableCursor (
824 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
825 IN BOOLEAN Visible
826 )
827 {
828 if (!Visible) {
829 return EFI_UNSUPPORTED;
830 }
831
832 return EFI_SUCCESS;
833 }
834
835
836 /**
837 Detects if a Unicode char is for Box Drawing text graphics.
838
839 @param Graphic Unicode char to test.
840 @param PcAnsi Optional pointer to return PCANSI equivalent of
841 Graphic.
842 @param Ascii Optional pointer to return ASCII equivalent of
843 Graphic.
844
845 @retval TRUE If Graphic is a supported Unicode Box Drawing character.
846
847 **/
848 BOOLEAN
849 TerminalIsValidTextGraphics (
850 IN CHAR16 Graphic,
851 OUT CHAR8 *PcAnsi, OPTIONAL
852 OUT CHAR8 *Ascii OPTIONAL
853 )
854 {
855 UNICODE_TO_CHAR *Table;
856
857 if ((((Graphic & 0xff00) != 0x2500) && ((Graphic & 0xff00) != 0x2100))) {
858 //
859 // Unicode drawing code charts are all in the 0x25xx range,
860 // arrows are 0x21xx
861 //
862 return FALSE;
863 }
864
865 for (Table = UnicodeToPcAnsiOrAscii; Table->Unicode != 0x0000; Table++) {
866 if (Graphic == Table->Unicode) {
867 if (PcAnsi != NULL) {
868 *PcAnsi = Table->PcAnsi;
869 }
870
871 if (Ascii != NULL) {
872 *Ascii = Table->Ascii;
873 }
874
875 return TRUE;
876 }
877 }
878
879 return FALSE;
880 }
881
882 /**
883 Detects if a valid ASCII char.
884
885 @param Ascii An ASCII character.
886
887 @retval TRUE If it is a valid ASCII character.
888 @retval FALSE If it is not a valid ASCII character.
889
890 **/
891 BOOLEAN
892 TerminalIsValidAscii (
893 IN CHAR16 Ascii
894 )
895 {
896 //
897 // valid ascii code lies in the extent of 0x20 ~ 0x7f
898 //
899 if ((Ascii >= 0x20) && (Ascii <= 0x7f)) {
900 return TRUE;
901 }
902
903 return FALSE;
904 }
905
906 /**
907 Detects if a valid EFI control character.
908
909 @param CharC An input EFI Control character.
910
911 @retval TRUE If it is a valid EFI control character.
912 @retval FALSE If it is not a valid EFI control character.
913
914 **/
915 BOOLEAN
916 TerminalIsValidEfiCntlChar (
917 IN CHAR16 CharC
918 )
919 {
920 //
921 // only support four control characters.
922 //
923 if (CharC == CHAR_NULL ||
924 CharC == CHAR_BACKSPACE ||
925 CharC == CHAR_LINEFEED ||
926 CharC == CHAR_CARRIAGE_RETURN ||
927 CharC == CHAR_TAB
928 ) {
929 return TRUE;
930 }
931
932 return FALSE;
933 }