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