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