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