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