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