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