]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Console/TerminalDxe/TerminalConOut.c
MdeModulePkg: Clean up source files
[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
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
ffc1fffd
MK
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
95276127 73\r
ffc1fffd
MK
74 { ARROW_LEFT, '<', L'<' },\r
75 { ARROW_UP, '^', L'^' },\r
76 { ARROW_RIGHT, '>', L'>' },\r
77 { ARROW_DOWN, 'v', 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
4d9ea309 191 CHAR8 CrLfStr[2];\r
95276127 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
c97b5672 200 AsciiChar = 0;\r
95276127 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
3012ce5c 208 // Get current display mode\r
95276127 209 //\r
210 Mode = This->Mode;\r
fb0b259e 211\r
79d07c66 212 if (Mode->Mode >= Mode->MaxMode) {\r
95276127 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
8ce87fff
RN
227 case TerminalTypePcAnsi:\r
228 case TerminalTypeVt100:\r
229 case TerminalTypeVt100Plus:\r
230 case TerminalTypeTtyTerm:\r
95276127 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
8ce87fff 256 if (TerminalDevice->TerminalType != TerminalTypePcAnsi) {\r
95276127 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
8ce87fff 274 case TerminalTypeVtUtf8:\r
95276127 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
8ce87fff 320 if (TerminalDevice->TerminalType == TerminalTypeTtyTerm &&\r
851b044f
BJ
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
4d9ea309
DB
330 CrLfStr[0] = '\r';\r
331 CrLfStr[1] = '\n';\r
851b044f
BJ
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
95276127 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
f9876ecf 361 (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_OUTPUT_ERROR),\r
95276127 362 TerminalDevice->DevicePath\r
363 );\r
364\r
365 return EFI_DEVICE_ERROR;\r
366}\r
367\r
e49ef433 368\r
369/**\r
370 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.TestString().\r
ab76200c 371\r
e49ef433 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
00bfdbe1 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
e49ef433 382\r
383**/\r
95276127 384EFI_STATUS\r
385EFIAPI\r
386TerminalConOutTestString (\r
387 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
388 IN CHAR16 *WString\r
389 )\r
95276127 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
8ce87fff
RN
401 case TerminalTypePcAnsi:\r
402 case TerminalTypeVt100:\r
403 case TerminalTypeVt100Plus:\r
404 case TerminalTypeTtyTerm:\r
95276127 405 Status = AnsiTestString (TerminalDevice, WString);\r
406 break;\r
407\r
8ce87fff 408 case TerminalTypeVtUtf8:\r
95276127 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
e49ef433 420\r
421/**\r
422 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.QueryMode().\r
ab76200c 423\r
e49ef433 424 It returns information for an available text mode\r
425 that the terminal supports.\r
e49ef433 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
00bfdbe1 432 @retval EFI_SUCCESS The requested mode information is returned.\r
433 @retval EFI_UNSUPPORTED The mode number is not valid.\r
e49ef433 434\r
435**/\r
95276127 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
95276127 444{\r
79d07c66 445 TERMINAL_DEV *TerminalDevice;\r
95276127 446\r
79d07c66 447 if (ModeNumber >= (UINTN) This->Mode->MaxMode) {\r
448 return EFI_UNSUPPORTED;\r
95276127 449 }\r
450\r
79d07c66 451 //\r
452 // Get Terminal device data structure pointer.\r
453 //\r
d1102dba 454 TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This);\r
79d07c66 455 *Columns = TerminalDevice->TerminalConsoleModeData[ModeNumber].Columns;\r
456 *Rows = TerminalDevice->TerminalConsoleModeData[ModeNumber].Rows;\r
457\r
458 return EFI_SUCCESS;\r
95276127 459}\r
460\r
e49ef433 461\r
462/**\r
463 Implements EFI_SIMPLE_TEXT_OUT.SetMode().\r
ab76200c 464\r
e49ef433 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
00bfdbe1 471 @retval EFI_SUCCESS The requested text mode is set.\r
d1102dba 472 @retval EFI_DEVICE_ERROR The requested text mode cannot be set\r
e49ef433 473 because of serial device error.\r
00bfdbe1 474 @retval EFI_UNSUPPORTED The text mode number is not valid.\r
e49ef433 475\r
476**/\r
95276127 477EFI_STATUS\r
478EFIAPI\r
479TerminalConOutSetMode (\r
480 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
481 IN UINTN ModeNumber\r
482 )\r
95276127 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
79d07c66 492 if (ModeNumber >= (UINTN) This->Mode->MaxMode) {\r
95276127 493 return EFI_UNSUPPORTED;\r
494 }\r
fb0b259e 495\r
3012ce5c 496 //\r
497 // Set the current mode\r
498 //\r
499 This->Mode->Mode = (INT32) ModeNumber;\r
95276127 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
3012ce5c 511 This->Mode->Mode = (INT32) ModeNumber;\r
95276127 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
e49ef433 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
00bfdbe1 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
e49ef433 533\r
534**/\r
95276127 535EFI_STATUS\r
536EFIAPI\r
537TerminalConOutSetAttribute (\r
538 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
539 IN UINTN Attribute\r
540 )\r
95276127 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
0ce1dd70 564\r
565 //\r
566 // Skip outputting the command string for the same attribute\r
11baadb6 567 // It improves the terminal performance significantly\r
0ce1dd70 568 //\r
569 if (This->Mode->Attribute == (INT32) Attribute) {\r
570 return EFI_SUCCESS;\r
571 }\r
572\r
95276127 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
e49ef433 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
00bfdbe1 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
e49ef433 706\r
707**/\r
95276127 708EFI_STATUS\r
709EFIAPI\r
710TerminalConOutClearScreen (\r
711 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This\r
712 )\r
95276127 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
e49ef433 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
00bfdbe1 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
e49ef433 746 is invalid for current mode.\r
747\r
748**/\r
95276127 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
95276127 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
27e80421 762 CHAR16 *String;\r
95276127 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
27e80421
BJ
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
8ce87fff 794 if (TerminalDevice->TerminalType == TerminalTypeTtyTerm &&\r
d1b757e2
MK
795 (UINTN)Mode->CursorRow == Row) {\r
796 if ((UINTN)Mode->CursorColumn > Column) {\r
27e80421
BJ
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
d1b757e2 801 else if (Column > (UINTN)Mode->CursorColumn) {\r
27e80421
BJ
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
95276127 817\r
818 TerminalDevice->OutputEscChar = TRUE;\r
27e80421 819 Status = This->OutputString (This, String);\r
95276127 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
e49ef433 835\r
836/**\r
837 Implements SIMPLE_TEXT_OUTPUT.EnableCursor().\r
ab76200c 838\r
e49ef433 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
00bfdbe1 845 @retval EFI_SUCCESS The request is valid.\r
846 @retval EFI_UNSUPPORTED The terminal does not support cursor hidden.\r
e49ef433 847\r
848**/\r
95276127 849EFI_STATUS\r
850EFIAPI\r
851TerminalConOutEnableCursor (\r
852 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
853 IN BOOLEAN Visible\r
854 )\r
95276127 855{\r
856 if (!Visible) {\r
857 return EFI_UNSUPPORTED;\r
858 }\r
859\r
860 return EFI_SUCCESS;\r
861}\r
862\r
e49ef433 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
00bfdbe1 873 @retval TRUE If Graphic is a supported Unicode Box Drawing character.\r
e49ef433 874\r
875**/\r
95276127 876BOOLEAN\r
877TerminalIsValidTextGraphics (\r
878 IN CHAR16 Graphic,\r
879 OUT CHAR8 *PcAnsi, OPTIONAL\r
880 OUT CHAR8 *Ascii OPTIONAL\r
881 )\r
95276127 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
8fd98315 910/**\r
911 Detects if a valid ASCII char.\r
912\r
913 @param Ascii An ASCII character.\r
d1102dba 914\r
8fd98315 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
95276127 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
8fd98315 934/**\r
935 Detects if a valid EFI control character.\r
936\r
937 @param CharC An input EFI Control character.\r
d1102dba 938\r
8fd98315 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
95276127 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