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