code scrub.
[people/mcb30/edk2.git] / edk2 / MdeModulePkg / Universal / Console / TerminalDxe / TerminalConOut.c
1 /** @file\r
2   Implementation for EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL protocol.\r
3 \r
4 Copyright (c) 2006 - 2008, Intel Corporation. <BR>\r
5 All rights reserved. This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution.  The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9 \r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12 \r
13 **/\r
14 \r
15 #include "Terminal.h"\r
16 \r
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
23 STATIC UNICODE_TO_CHAR  UnicodeToPcAnsiOrAscii[] = {\r
24   { BOXDRAW_HORIZONTAL,                 0xc4, L'-' },\r
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
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
77 \r
78   { 0x0000,                             0x00, L'\0' }\r
79 };\r
80 \r
81 STATIC CHAR16 mSetModeString[]            = { ESC, '[', '=', '3', 'h', 0 };\r
82 STATIC CHAR16 mSetAttributeString[]       = { ESC, '[', '0', 'm', ESC, '[', '4', '0', 'm', ESC, '[', '4', '0', 'm', 0 };\r
83 STATIC CHAR16 mClearScreenString[]        = { ESC, '[', '2', 'J', 0 };\r
84 STATIC CHAR16 mSetCursorPositionString[]  = { ESC, '[', '0', '0', ';', '0', '0', 'H', 0 };\r
85 \r
86 //\r
87 // Body of the ConOut functions\r
88 //\r
89 \r
90 /**\r
91   Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.Reset().\r
92 \r
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
102   @return EFI_SUCCESS           The reset operation succeeds.\r
103   @return EFI_DEVICE_ERROR      The terminal is not functioning correctly or the serial port reset fails.\r
104 \r
105 **/\r
106 EFI_STATUS\r
107 EFIAPI\r
108 TerminalConOutReset (\r
109   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,\r
110   IN  BOOLEAN                          ExtendedVerification\r
111   )\r
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
127       PcdGet32 (PcdStatusCodeValueRemoteConsoleReset),\r
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
138         PcdGet32 (PcdStatusCodeValueRemoteConsoleError),\r
139         TerminalDevice->DevicePath\r
140         );\r
141 \r
142       return Status;\r
143     }\r
144   }\r
145 \r
146   This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BLACK));\r
147 \r
148   Status = This->SetMode (This, 0);\r
149 \r
150   return Status;\r
151 }\r
152 \r
153 \r
154 /**\r
155   Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString().\r
156 \r
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
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
167                                   be rendered and are skipped.\r
168   @retval EFI_UNSUPPORTED         If current display mode is out of range.\r
169 \r
170 **/\r
171 EFI_STATUS\r
172 EFIAPI\r
173 TerminalConOutOutputString (\r
174   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,\r
175   IN  CHAR16                           *WString\r
176   )\r
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
185   CHAR8                       AsciiChar;\r
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
196 \r
197   //\r
198   //  get Terminal device data structure pointer.\r
199   //\r
200   TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This);\r
201 \r
202   //\r
203   //  Get current display mode\r
204   //\r
205   Mode = This->Mode;\r
206 \r
207   if (Mode->Mode > 2) {\r
208     return EFI_UNSUPPORTED;\r
209   }\r
210 \r
211   This->QueryMode (\r
212           This,\r
213           Mode->Mode,\r
214           &MaxColumn,\r
215           &MaxRow\r
216           );\r
217 \r
218   for (; *WString != CHAR_NULL; WString++) {\r
219 \r
220     switch (TerminalDevice->TerminalType) {\r
221 \r
222     case PCANSITYPE:\r
223     case VT100TYPE:\r
224     case VT100PLUSTYPE:\r
225 \r
226       if (!TerminalIsValidTextGraphics (*WString, &GraphicChar, &AsciiChar)) {\r
227         //\r
228         // If it's not a graphic character convert Unicode to ASCII.\r
229         //\r
230         GraphicChar = (CHAR8) *WString;\r
231 \r
232         if (!(TerminalIsValidAscii (GraphicChar) || TerminalIsValidEfiCntlChar (GraphicChar))) {\r
233           //\r
234           // when this driver use the OutputString to output control string,\r
235           // TerminalDevice->OutputEscChar is set to let the Esc char\r
236           // to be output to the terminal emulation software.\r
237           //\r
238           if ((GraphicChar == 27) && TerminalDevice->OutputEscChar) {\r
239             GraphicChar = 27;\r
240           } else {\r
241             GraphicChar = '?';\r
242             Warning     = TRUE;\r
243           }\r
244         }\r
245 \r
246         AsciiChar = GraphicChar;\r
247 \r
248       }\r
249 \r
250       if (TerminalDevice->TerminalType != PCANSITYPE) {\r
251         GraphicChar = AsciiChar;\r
252       }\r
253 \r
254       Length = 1;\r
255 \r
256       Status = TerminalDevice->SerialIo->Write (\r
257                                           TerminalDevice->SerialIo,\r
258                                           &Length,\r
259                                           &GraphicChar\r
260                                           );\r
261 \r
262       if (EFI_ERROR (Status)) {\r
263         goto OutputError;\r
264       }\r
265 \r
266       break;\r
267 \r
268     case VTUTF8TYPE:\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
279       break;\r
280     }\r
281     //\r
282     //  Update cursor position.\r
283     //\r
284     switch (*WString) {\r
285 \r
286     case CHAR_BACKSPACE:\r
287       if (Mode->CursorColumn > 0) {\r
288         Mode->CursorColumn--;\r
289       }\r
290       break;\r
291 \r
292     case CHAR_LINEFEED:\r
293       if (Mode->CursorRow < (INT32) (MaxRow - 1)) {\r
294         Mode->CursorRow++;\r
295       }\r
296       break;\r
297 \r
298     case CHAR_CARRIAGE_RETURN:\r
299       Mode->CursorColumn = 0;\r
300       break;\r
301 \r
302     default:\r
303       if (Mode->CursorColumn < (INT32) (MaxColumn - 1)) {\r
304 \r
305         Mode->CursorColumn++;\r
306 \r
307       } else {\r
308 \r
309         Mode->CursorColumn = 0;\r
310         if (Mode->CursorRow < (INT32) (MaxRow - 1)) {\r
311           Mode->CursorRow++;\r
312         }\r
313 \r
314       }\r
315       break;\r
316 \r
317     };\r
318 \r
319   }\r
320 \r
321   if (Warning) {\r
322     return EFI_WARN_UNKNOWN_GLYPH;\r
323   }\r
324 \r
325   return EFI_SUCCESS;\r
326 \r
327 OutputError:\r
328   REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
329     EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
330     PcdGet32 (PcdStatusCodeValueRemoteConsoleOutputError),\r
331     TerminalDevice->DevicePath\r
332     );\r
333 \r
334   return EFI_DEVICE_ERROR;\r
335 }\r
336 \r
337 \r
338 /**\r
339   Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.TestString().\r
340 \r
341   If one of the characters in the *Wstring is\r
342   neither valid Unicode drawing characters,\r
343   not ASCII code, then this function will return\r
344   EFI_UNSUPPORTED.\r
345 \r
346   @param  This              Indicates the calling context.\r
347   @param  WString           The Null-terminated Unicode string to be tested.\r
348 \r
349   @return EFI_SUCCESS       The terminal is capable of rendering the output string.\r
350   @return EFI_UNSUPPORTED   Some of the characters in the Unicode string cannot be rendered.\r
351 \r
352 **/\r
353 EFI_STATUS\r
354 EFIAPI\r
355 TerminalConOutTestString (\r
356   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,\r
357   IN  CHAR16                           *WString\r
358   )\r
359 {\r
360   TERMINAL_DEV  *TerminalDevice;\r
361   EFI_STATUS    Status;\r
362 \r
363   //\r
364   //  get Terminal device data structure pointer.\r
365   //\r
366   TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This);\r
367 \r
368   switch (TerminalDevice->TerminalType) {\r
369 \r
370   case PCANSITYPE:\r
371   case VT100TYPE:\r
372   case VT100PLUSTYPE:\r
373     Status = AnsiTestString (TerminalDevice, WString);\r
374     break;\r
375 \r
376   case VTUTF8TYPE:\r
377     Status = VTUTF8TestString (TerminalDevice, WString);\r
378     break;\r
379 \r
380   default:\r
381     Status = EFI_UNSUPPORTED;\r
382     break;\r
383   }\r
384 \r
385   return Status;\r
386 }\r
387 \r
388 \r
389 /**\r
390   Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.QueryMode().\r
391 \r
392   It returns information for an available text mode\r
393   that the terminal supports.\r
394   In this driver, we support text mode 80x25 (mode 0),\r
395   80x50 (mode 1), 100x31 (mode 2).\r
396 \r
397   @param This        Indicates the calling context.\r
398   @param ModeNumber  The mode number to return information on.\r
399   @param Columns     The returned columns of the requested mode.\r
400   @param Rows        The returned rows of the requested mode.\r
401 \r
402   @return EFI_SUCCESS       The requested mode information is returned.\r
403   @return EFI_UNSUPPORTED   The mode number is not valid.\r
404   @return EFI_DEVICE_ERROR\r
405 \r
406 **/\r
407 EFI_STATUS\r
408 EFIAPI\r
409 TerminalConOutQueryMode (\r
410   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,\r
411   IN  UINTN                            ModeNumber,\r
412   OUT UINTN                            *Columns,\r
413   OUT UINTN                            *Rows\r
414   )\r
415 {\r
416   if (This->Mode->MaxMode > 3) {\r
417     return EFI_DEVICE_ERROR;\r
418   }\r
419 \r
420   if (ModeNumber == 0) {\r
421     *Columns  = MODE0_COLUMN_COUNT;\r
422     *Rows     = MODE0_ROW_COUNT;\r
423     return EFI_SUCCESS;\r
424   } else if (ModeNumber == 1) {\r
425     *Columns  = MODE1_COLUMN_COUNT;\r
426     *Rows     = MODE1_ROW_COUNT;\r
427     return EFI_SUCCESS;\r
428   } else if (ModeNumber == 2) {\r
429     *Columns  = MODE2_COLUMN_COUNT;\r
430     *Rows     = MODE2_ROW_COUNT;\r
431     return EFI_SUCCESS;\r
432   }\r
433 \r
434   return EFI_UNSUPPORTED;\r
435 }\r
436 \r
437 \r
438 /**\r
439   Implements EFI_SIMPLE_TEXT_OUT.SetMode().\r
440 \r
441   Set the terminal to a specified display mode.\r
442   In this driver, we only support mode 0.\r
443 \r
444   @param This          Indicates the calling context.\r
445   @param ModeNumber    The text mode to set.\r
446 \r
447   @return EFI_SUCCESS       The requested text mode is set.\r
448   @return EFI_DEVICE_ERROR  The requested text mode cannot be set \r
449                             because of serial device error.\r
450   @return EFI_UNSUPPORTED   The text mode number is not valid.\r
451 \r
452 **/\r
453 EFI_STATUS\r
454 EFIAPI\r
455 TerminalConOutSetMode (\r
456   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,\r
457   IN  UINTN                            ModeNumber\r
458   )\r
459 {\r
460   EFI_STATUS    Status;\r
461   TERMINAL_DEV  *TerminalDevice;\r
462 \r
463   //\r
464   //  get Terminal device data structure pointer.\r
465   //\r
466   TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This);\r
467 \r
468   if (ModeNumber > 2) {\r
469     return EFI_UNSUPPORTED;\r
470   }\r
471 \r
472   //\r
473   // Set the current mode\r
474   //\r
475   This->Mode->Mode = (INT32) ModeNumber;\r
476 \r
477   This->ClearScreen (This);\r
478 \r
479   TerminalDevice->OutputEscChar = TRUE;\r
480   Status                        = This->OutputString (This, mSetModeString);\r
481   TerminalDevice->OutputEscChar = FALSE;\r
482 \r
483   if (EFI_ERROR (Status)) {\r
484     return EFI_DEVICE_ERROR;\r
485   }\r
486 \r
487   This->Mode->Mode  = (INT32) ModeNumber;\r
488 \r
489   Status            = This->ClearScreen (This);\r
490   if (EFI_ERROR (Status)) {\r
491     return EFI_DEVICE_ERROR;\r
492   }\r
493 \r
494   return EFI_SUCCESS;\r
495 \r
496 }\r
497 \r
498 \r
499 /**\r
500   Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetAttribute().\r
501 \r
502   @param This        Indicates the calling context.\r
503   @param Attribute   The attribute to set. Only bit0..6 are valid, all other bits\r
504                      are undefined and must be zero.\r
505 \r
506   @return EFI_SUCCESS        The requested attribute is set.\r
507   @return EFI_DEVICE_ERROR   The requested attribute cannot be set due to serial port error.\r
508   @return EFI_UNSUPPORTED    The attribute requested is not defined by EFI spec.\r
509 \r
510 **/\r
511 EFI_STATUS\r
512 EFIAPI\r
513 TerminalConOutSetAttribute (\r
514   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,\r
515   IN  UINTN                            Attribute\r
516   )\r
517 {\r
518   UINT8         ForegroundControl;\r
519   UINT8         BackgroundControl;\r
520   UINT8         BrightControl;\r
521   INT32         SavedColumn;\r
522   INT32         SavedRow;\r
523   EFI_STATUS    Status;\r
524   TERMINAL_DEV  *TerminalDevice;\r
525 \r
526   SavedColumn = 0;\r
527   SavedRow    = 0;\r
528 \r
529   //\r
530   //  get Terminal device data structure pointer.\r
531   //\r
532   TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This);\r
533 \r
534   //\r
535   //  only the bit0..6 of the Attribute is valid\r
536   //\r
537   if ((Attribute | 0x7f) != 0x7f) {\r
538     return EFI_UNSUPPORTED;\r
539   }\r
540 \r
541   //\r
542   // Skip outputting the command string for the same attribute\r
543   // It improves the terminal performance siginificantly\r
544   //\r
545   if (This->Mode->Attribute == (INT32) Attribute) {\r
546     return EFI_SUCCESS;\r
547   }\r
548 \r
549   //\r
550   //  convert Attribute value to terminal emulator\r
551   //  understandable foreground color\r
552   //\r
553   switch (Attribute & 0x07) {\r
554 \r
555   case EFI_BLACK:\r
556     ForegroundControl = 30;\r
557     break;\r
558 \r
559   case EFI_BLUE:\r
560     ForegroundControl = 34;\r
561     break;\r
562 \r
563   case EFI_GREEN:\r
564     ForegroundControl = 32;\r
565     break;\r
566 \r
567   case EFI_CYAN:\r
568     ForegroundControl = 36;\r
569     break;\r
570 \r
571   case EFI_RED:\r
572     ForegroundControl = 31;\r
573     break;\r
574 \r
575   case EFI_MAGENTA:\r
576     ForegroundControl = 35;\r
577     break;\r
578 \r
579   case EFI_BROWN:\r
580     ForegroundControl = 33;\r
581     break;\r
582 \r
583   default:\r
584 \r
585   case EFI_LIGHTGRAY:\r
586     ForegroundControl = 37;\r
587     break;\r
588 \r
589   }\r
590   //\r
591   //  bit4 of the Attribute indicates bright control\r
592   //  of terminal emulator.\r
593   //\r
594   BrightControl = (UINT8) ((Attribute >> 3) & 1);\r
595 \r
596   //\r
597   //  convert Attribute value to terminal emulator\r
598   //  understandable background color.\r
599   //\r
600   switch ((Attribute >> 4) & 0x07) {\r
601 \r
602   case EFI_BLACK:\r
603     BackgroundControl = 40;\r
604     break;\r
605 \r
606   case EFI_BLUE:\r
607     BackgroundControl = 44;\r
608     break;\r
609 \r
610   case EFI_GREEN:\r
611     BackgroundControl = 42;\r
612     break;\r
613 \r
614   case EFI_CYAN:\r
615     BackgroundControl = 46;\r
616     break;\r
617 \r
618   case EFI_RED:\r
619     BackgroundControl = 41;\r
620     break;\r
621 \r
622   case EFI_MAGENTA:\r
623     BackgroundControl = 45;\r
624     break;\r
625 \r
626   case EFI_BROWN:\r
627     BackgroundControl = 43;\r
628     break;\r
629 \r
630   default:\r
631 \r
632   case EFI_LIGHTGRAY:\r
633     BackgroundControl = 47;\r
634     break;\r
635   }\r
636   //\r
637   // terminal emulator's control sequence to set attributes\r
638   //\r
639   mSetAttributeString[BRIGHT_CONTROL_OFFSET]          = (CHAR16) ('0' + BrightControl);\r
640   mSetAttributeString[FOREGROUND_CONTROL_OFFSET + 0]  = (CHAR16) ('0' + (ForegroundControl / 10));\r
641   mSetAttributeString[FOREGROUND_CONTROL_OFFSET + 1]  = (CHAR16) ('0' + (ForegroundControl % 10));\r
642   mSetAttributeString[BACKGROUND_CONTROL_OFFSET + 0]  = (CHAR16) ('0' + (BackgroundControl / 10));\r
643   mSetAttributeString[BACKGROUND_CONTROL_OFFSET + 1]  = (CHAR16) ('0' + (BackgroundControl % 10));\r
644 \r
645   //\r
646   // save current column and row\r
647   // for future scrolling back use.\r
648   //\r
649   SavedColumn                   = This->Mode->CursorColumn;\r
650   SavedRow                      = This->Mode->CursorRow;\r
651 \r
652   TerminalDevice->OutputEscChar = TRUE;\r
653   Status                        = This->OutputString (This, mSetAttributeString);\r
654   TerminalDevice->OutputEscChar = FALSE;\r
655 \r
656   if (EFI_ERROR (Status)) {\r
657     return EFI_DEVICE_ERROR;\r
658   }\r
659   //\r
660   //  scroll back to saved cursor position.\r
661   //\r
662   This->Mode->CursorColumn  = SavedColumn;\r
663   This->Mode->CursorRow     = SavedRow;\r
664 \r
665   This->Mode->Attribute     = (INT32) Attribute;\r
666 \r
667   return EFI_SUCCESS;\r
668 \r
669 }\r
670 \r
671 \r
672 /**\r
673   Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.ClearScreen().\r
674   It clears the ANSI terminal's display to the\r
675   currently selected background color.\r
676 \r
677   @param This     Indicates the calling context.\r
678 \r
679   @return EFI_SUCCESS       The operation completed successfully.\r
680   @return EFI_DEVICE_ERROR  The terminal screen cannot be cleared due to serial port error.\r
681   @return EFI_UNSUPPORTED   The terminal is not in a valid display mode.\r
682 \r
683 **/\r
684 EFI_STATUS\r
685 EFIAPI\r
686 TerminalConOutClearScreen (\r
687   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This\r
688   )\r
689 {\r
690   EFI_STATUS    Status;\r
691   TERMINAL_DEV  *TerminalDevice;\r
692 \r
693   TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This);\r
694 \r
695   //\r
696   //  control sequence for clear screen request\r
697   //\r
698   TerminalDevice->OutputEscChar = TRUE;\r
699   Status                        = This->OutputString (This, mClearScreenString);\r
700   TerminalDevice->OutputEscChar = FALSE;\r
701 \r
702   if (EFI_ERROR (Status)) {\r
703     return EFI_DEVICE_ERROR;\r
704   }\r
705 \r
706   Status = This->SetCursorPosition (This, 0, 0);\r
707 \r
708   return Status;\r
709 }\r
710 \r
711 \r
712 /**\r
713   Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetCursorPosition().\r
714 \r
715   @param This      Indicates the calling context.\r
716   @param Column    The row to set cursor to.\r
717   @param Row       The column to set cursor to.\r
718 \r
719   @return EFI_SUCCESS       The operation completed successfully.\r
720   @return EFI_DEVICE_ERROR  The request fails due to serial port error.\r
721   @return EFI_UNSUPPORTED   The terminal is not in a valid text mode, or the cursor position\r
722                             is invalid for current mode.\r
723 \r
724 **/\r
725 EFI_STATUS\r
726 EFIAPI\r
727 TerminalConOutSetCursorPosition (\r
728   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,\r
729   IN  UINTN                            Column,\r
730   IN  UINTN                            Row\r
731   )\r
732 {\r
733   EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode;\r
734   UINTN                       MaxColumn;\r
735   UINTN                       MaxRow;\r
736   EFI_STATUS                  Status;\r
737   TERMINAL_DEV                *TerminalDevice;\r
738 \r
739   TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This);\r
740 \r
741   //\r
742   //  get current mode\r
743   //\r
744   Mode = This->Mode;\r
745 \r
746   //\r
747   //  get geometry of current mode\r
748   //\r
749   Status = This->QueryMode (\r
750                   This,\r
751                   Mode->Mode,\r
752                   &MaxColumn,\r
753                   &MaxRow\r
754                   );\r
755   if (EFI_ERROR (Status)) {\r
756     return EFI_UNSUPPORTED;\r
757   }\r
758 \r
759   if (Column >= MaxColumn || Row >= MaxRow) {\r
760     return EFI_UNSUPPORTED;\r
761   }\r
762   //\r
763   // control sequence to move the cursor\r
764   //\r
765   mSetCursorPositionString[ROW_OFFSET + 0]    = (CHAR16) ('0' + ((Row + 1) / 10));\r
766   mSetCursorPositionString[ROW_OFFSET + 1]    = (CHAR16) ('0' + ((Row + 1) % 10));\r
767   mSetCursorPositionString[COLUMN_OFFSET + 0] = (CHAR16) ('0' + ((Column + 1) / 10));\r
768   mSetCursorPositionString[COLUMN_OFFSET + 1] = (CHAR16) ('0' + ((Column + 1) % 10));\r
769 \r
770   TerminalDevice->OutputEscChar               = TRUE;\r
771   Status = This->OutputString (This, mSetCursorPositionString);\r
772   TerminalDevice->OutputEscChar = FALSE;\r
773 \r
774   if (EFI_ERROR (Status)) {\r
775     return EFI_DEVICE_ERROR;\r
776   }\r
777   //\r
778   //  update current cursor position\r
779   //  in the Mode data structure.\r
780   //\r
781   Mode->CursorColumn  = (INT32) Column;\r
782   Mode->CursorRow     = (INT32) Row;\r
783 \r
784   return EFI_SUCCESS;\r
785 }\r
786 \r
787 \r
788 /**\r
789   Implements SIMPLE_TEXT_OUTPUT.EnableCursor().\r
790 \r
791   In this driver, the cursor cannot be hidden.\r
792 \r
793   @param This      Indicates the calling context.\r
794   @param Visible   If TRUE, the cursor is set to be visible,\r
795                    If FALSE, the cursor is set to be invisible.\r
796 \r
797   @return EFI_SUCCESS      The request is valid.\r
798   @return EFI_UNSUPPORTED  The terminal does not support cursor hidden.\r
799 \r
800 **/\r
801 EFI_STATUS\r
802 EFIAPI\r
803 TerminalConOutEnableCursor (\r
804   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,\r
805   IN  BOOLEAN                          Visible\r
806   )\r
807 {\r
808   if (!Visible) {\r
809     return EFI_UNSUPPORTED;\r
810   }\r
811 \r
812   return EFI_SUCCESS;\r
813 }\r
814 \r
815 \r
816 /**\r
817   Detects if a Unicode char is for Box Drawing text graphics.\r
818 \r
819   @param  Graphic      Unicode char to test.\r
820   @param  PcAnsi       Optional pointer to return PCANSI equivalent of\r
821                        Graphic.\r
822   @param  Ascii        Optional pointer to return ASCII equivalent of\r
823                        Graphic.\r
824 \r
825   @return TRUE         If Graphic is a supported Unicode Box Drawing character.\r
826 \r
827 **/\r
828 BOOLEAN\r
829 TerminalIsValidTextGraphics (\r
830   IN  CHAR16  Graphic,\r
831   OUT CHAR8   *PcAnsi, OPTIONAL\r
832   OUT CHAR8   *Ascii OPTIONAL\r
833   )\r
834 {\r
835   UNICODE_TO_CHAR *Table;\r
836 \r
837   if ((((Graphic & 0xff00) != 0x2500) && ((Graphic & 0xff00) != 0x2100))) {\r
838     //\r
839     // Unicode drawing code charts are all in the 0x25xx range,\r
840     //  arrows are 0x21xx\r
841     //\r
842     return FALSE;\r
843   }\r
844 \r
845   for (Table = UnicodeToPcAnsiOrAscii; Table->Unicode != 0x0000; Table++) {\r
846     if (Graphic == Table->Unicode) {\r
847       if (PcAnsi != NULL) {\r
848         *PcAnsi = Table->PcAnsi;\r
849       }\r
850 \r
851       if (Ascii != NULL) {\r
852         *Ascii = Table->Ascii;\r
853       }\r
854 \r
855       return TRUE;\r
856     }\r
857   }\r
858 \r
859   return FALSE;\r
860 }\r
861 \r
862 /**\r
863   Detects if a valid ASCII char.\r
864 \r
865   @param  Ascii        An ASCII character.\r
866                        \r
867   @retval TRUE         If it is a valid ASCII character.\r
868   @retval FALSE        If it is not a valid ASCII character.\r
869 \r
870 **/\r
871 BOOLEAN\r
872 TerminalIsValidAscii (\r
873   IN  CHAR16  Ascii\r
874   )\r
875 {\r
876   //\r
877   // valid ascii code lies in the extent of 0x20 ~ 0x7f\r
878   //\r
879   if ((Ascii >= 0x20) && (Ascii <= 0x7f)) {\r
880     return TRUE;\r
881   }\r
882 \r
883   return FALSE;\r
884 }\r
885 \r
886 /**\r
887   Detects if a valid EFI control character.\r
888 \r
889   @param  CharC        An input EFI Control character.\r
890                        \r
891   @retval TRUE         If it is a valid EFI control character.\r
892   @retval FALSE        If it is not a valid EFI control character.\r
893 \r
894 **/\r
895 BOOLEAN\r
896 TerminalIsValidEfiCntlChar (\r
897   IN  CHAR16  CharC\r
898   )\r
899 {\r
900   //\r
901   // only support four control characters.\r
902   //\r
903   if (CharC == CHAR_NULL ||\r
904       CharC == CHAR_BACKSPACE ||\r
905       CharC == CHAR_LINEFEED ||\r
906       CharC == CHAR_CARRIAGE_RETURN ||\r
907       CharC == CHAR_TAB\r
908       ) {\r
909     return TRUE;\r
910   }\r
911 \r
912   return FALSE;\r
913 }\r