Clean codes per ECC for TerminalDxe module.
[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 CHAR16 mSetModeString[]            = { ESC, '[', '=', '3', 'h', 0 };\r
82 CHAR16 mSetAttributeString[]       = { ESC, '[', '0', 'm', ESC, '[', '4', '0', 'm', ESC, '[', '4', '0', 'm', 0 };\r
83 CHAR16 mClearScreenString[]        = { ESC, '[', '2', 'J', 0 };\r
84 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   If ExtendeVerification is TRUE, then perform dependent serial device reset,\r
93   and set display mode to mode 0.\r
94   If ExtendedVerification is FALSE, only set display mode to mode 0.\r
95 \r
96   @param  This                  Indicates the calling context.\r
97   @param  ExtendedVerification  Indicates that the driver may perform a more\r
98                                 exhaustive verification operation of the device\r
99                                 during reset.\r
100 \r
101   @return EFI_SUCCESS\r
102   @return The reset operation succeeds.\r
103   @return EFI_DEVICE_ERROR\r
104   @return The terminal is not functioning correctly or the serial port reset fails.\r
105 \r
106 **/\r
107 EFI_STATUS\r
108 EFIAPI\r
109 TerminalConOutReset (\r
110   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,\r
111   IN  BOOLEAN                          ExtendedVerification\r
112   )\r
113 {\r
114   EFI_STATUS    Status;\r
115   TERMINAL_DEV  *TerminalDevice;\r
116 \r
117   TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This);\r
118 \r
119   //\r
120   // Perform a more exhaustive reset by resetting the serial port.\r
121   //\r
122   if (ExtendedVerification) {\r
123     //\r
124     // Report progress code here\r
125     //\r
126     REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
127       EFI_PROGRESS_CODE,\r
128       PcdGet32 (PcdStatusCodeValueRemoteConsoleReset),\r
129       TerminalDevice->DevicePath\r
130       );\r
131 \r
132     Status = TerminalDevice->SerialIo->Reset (TerminalDevice->SerialIo);\r
133     if (EFI_ERROR (Status)) {\r
134       //\r
135       // Report error code here\r
136       //\r
137       REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
138         EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
139         PcdGet32 (PcdStatusCodeValueRemoteConsoleError),\r
140         TerminalDevice->DevicePath\r
141         );\r
142 \r
143       return Status;\r
144     }\r
145   }\r
146 \r
147   This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BLACK));\r
148 \r
149   Status = This->SetMode (This, 0);\r
150 \r
151   return Status;\r
152 }\r
153 \r
154 \r
155 /**\r
156   Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString().\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   @return EFI_SUCCESS             The string is output successfully.\r
165   @return EFI_DEVICE_ERROR        The serial port fails to send the string out.\r
166   @return 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   @return EFI_UNSUPPORTED\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   If one of the characters in the *Wstring is\r
341   neither valid Unicode drawing characters,\r
342   not ASCII code, then this function will return\r
343   EFI_UNSUPPORTED.\r
344 \r
345   @param  This              Indicates the calling context.\r
346   @param  WString           The Null-terminated Unicode string to be tested.\r
347 \r
348   @return EFI_SUCCESS       The terminal is capable of rendering the output string.\r
349   @return EFI_UNSUPPORTED   Some of the characters in the Unicode string cannot be rendered.\r
350 \r
351 **/\r
352 EFI_STATUS\r
353 EFIAPI\r
354 TerminalConOutTestString (\r
355   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,\r
356   IN  CHAR16                           *WString\r
357   )\r
358 {\r
359   TERMINAL_DEV  *TerminalDevice;\r
360   EFI_STATUS    Status;\r
361 \r
362   //\r
363   //  get Terminal device data structure pointer.\r
364   //\r
365   TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This);\r
366 \r
367   switch (TerminalDevice->TerminalType) {\r
368 \r
369   case PCANSITYPE:\r
370   case VT100TYPE:\r
371   case VT100PLUSTYPE:\r
372     Status = AnsiTestString (TerminalDevice, WString);\r
373     break;\r
374 \r
375   case VTUTF8TYPE:\r
376     Status = VTUTF8TestString (TerminalDevice, WString);\r
377     break;\r
378 \r
379   default:\r
380     Status = EFI_UNSUPPORTED;\r
381     break;\r
382   }\r
383 \r
384   return Status;\r
385 }\r
386 \r
387 \r
388 /**\r
389   Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.QueryMode().\r
390   It returns information for an available text mode\r
391   that the terminal supports.\r
392   In this driver, we support text mode 80x25 (mode 0),\r
393   80x50 (mode 1), 100x31 (mode 2).\r
394 \r
395   @param This        Indicates the calling context.\r
396   @param ModeNumber  The mode number to return information on.\r
397   @param Columns     The returned columns of the requested mode.\r
398   @param Rows        The returned rows of the requested mode.\r
399 \r
400   @return EFI_SUCCESS       The requested mode information is returned.\r
401   @return EFI_UNSUPPORTED   The mode number is not valid.\r
402   @return EFI_DEVICE_ERROR\r
403 \r
404 **/\r
405 EFI_STATUS\r
406 EFIAPI\r
407 TerminalConOutQueryMode (\r
408   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,\r
409   IN  UINTN                            ModeNumber,\r
410   OUT UINTN                            *Columns,\r
411   OUT UINTN                            *Rows\r
412   )\r
413 {\r
414   if (This->Mode->MaxMode > 3) {\r
415     return EFI_DEVICE_ERROR;\r
416   }\r
417 \r
418   if (ModeNumber == 0) {\r
419     *Columns  = MODE0_COLUMN_COUNT;\r
420     *Rows     = MODE0_ROW_COUNT;\r
421     return EFI_SUCCESS;\r
422   } else if (ModeNumber == 1) {\r
423     *Columns  = MODE1_COLUMN_COUNT;\r
424     *Rows     = MODE1_ROW_COUNT;\r
425     return EFI_SUCCESS;\r
426   } else if (ModeNumber == 2) {\r
427     *Columns  = MODE2_COLUMN_COUNT;\r
428     *Rows     = MODE2_ROW_COUNT;\r
429     return EFI_SUCCESS;\r
430   }\r
431 \r
432   return EFI_UNSUPPORTED;\r
433 }\r
434 \r
435 \r
436 /**\r
437   Implements EFI_SIMPLE_TEXT_OUT.SetMode().\r
438   Set the terminal to a specified display mode.\r
439   In this driver, we only support mode 0.\r
440 \r
441   @param This          Indicates the calling context.\r
442   @param ModeNumber    The text mode to set.\r
443 \r
444   @return EFI_SUCCESS       The requested text mode is set.\r
445   @return EFI_DEVICE_ERROR  The requested text mode cannot be set \r
446                             because of serial device error.\r
447   @return EFI_UNSUPPORTED   The text mode number is not valid.\r
448 \r
449 **/\r
450 EFI_STATUS\r
451 EFIAPI\r
452 TerminalConOutSetMode (\r
453   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,\r
454   IN  UINTN                            ModeNumber\r
455   )\r
456 {\r
457   EFI_STATUS    Status;\r
458   TERMINAL_DEV  *TerminalDevice;\r
459 \r
460   //\r
461   //  get Terminal device data structure pointer.\r
462   //\r
463   TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This);\r
464 \r
465   if (ModeNumber > 2) {\r
466     return EFI_UNSUPPORTED;\r
467   }\r
468 \r
469   //\r
470   // Set the current mode\r
471   //\r
472   This->Mode->Mode = (INT32) ModeNumber;\r
473 \r
474   This->ClearScreen (This);\r
475 \r
476   TerminalDevice->OutputEscChar = TRUE;\r
477   Status                        = This->OutputString (This, mSetModeString);\r
478   TerminalDevice->OutputEscChar = FALSE;\r
479 \r
480   if (EFI_ERROR (Status)) {\r
481     return EFI_DEVICE_ERROR;\r
482   }\r
483 \r
484   This->Mode->Mode  = (INT32) ModeNumber;\r
485 \r
486   Status            = This->ClearScreen (This);\r
487   if (EFI_ERROR (Status)) {\r
488     return EFI_DEVICE_ERROR;\r
489   }\r
490 \r
491   return EFI_SUCCESS;\r
492 \r
493 }\r
494 \r
495 \r
496 /**\r
497   Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetAttribute().\r
498 \r
499   @param This        Indicates the calling context.\r
500   @param Attribute   The attribute to set. Only bit0..6 are valid, all other bits\r
501                      are undefined and must be zero.\r
502 \r
503   @return EFI_SUCCESS        The requested attribute is set.\r
504   @return EFI_DEVICE_ERROR   The requested attribute cannot be set due to serial port error.\r
505   @return EFI_UNSUPPORTED    The attribute requested is not defined by EFI spec.\r
506 \r
507 **/\r
508 EFI_STATUS\r
509 EFIAPI\r
510 TerminalConOutSetAttribute (\r
511   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,\r
512   IN  UINTN                            Attribute\r
513   )\r
514 {\r
515   UINT8         ForegroundControl;\r
516   UINT8         BackgroundControl;\r
517   UINT8         BrightControl;\r
518   INT32         SavedColumn;\r
519   INT32         SavedRow;\r
520   EFI_STATUS    Status;\r
521   TERMINAL_DEV  *TerminalDevice;\r
522 \r
523   SavedColumn = 0;\r
524   SavedRow    = 0;\r
525 \r
526   //\r
527   //  get Terminal device data structure pointer.\r
528   //\r
529   TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This);\r
530 \r
531   //\r
532   //  only the bit0..6 of the Attribute is valid\r
533   //\r
534   if ((Attribute | 0x7f) != 0x7f) {\r
535     return EFI_UNSUPPORTED;\r
536   }\r
537 \r
538   //\r
539   // Skip outputting the command string for the same attribute\r
540   // It improves the terminal performance siginificantly\r
541   //\r
542   if (This->Mode->Attribute == (INT32) Attribute) {\r
543     return EFI_SUCCESS;\r
544   }\r
545 \r
546   //\r
547   //  convert Attribute value to terminal emulator\r
548   //  understandable foreground color\r
549   //\r
550   switch (Attribute & 0x07) {\r
551 \r
552   case EFI_BLACK:\r
553     ForegroundControl = 30;\r
554     break;\r
555 \r
556   case EFI_BLUE:\r
557     ForegroundControl = 34;\r
558     break;\r
559 \r
560   case EFI_GREEN:\r
561     ForegroundControl = 32;\r
562     break;\r
563 \r
564   case EFI_CYAN:\r
565     ForegroundControl = 36;\r
566     break;\r
567 \r
568   case EFI_RED:\r
569     ForegroundControl = 31;\r
570     break;\r
571 \r
572   case EFI_MAGENTA:\r
573     ForegroundControl = 35;\r
574     break;\r
575 \r
576   case EFI_BROWN:\r
577     ForegroundControl = 33;\r
578     break;\r
579 \r
580   default:\r
581 \r
582   case EFI_LIGHTGRAY:\r
583     ForegroundControl = 37;\r
584     break;\r
585 \r
586   }\r
587   //\r
588   //  bit4 of the Attribute indicates bright control\r
589   //  of terminal emulator.\r
590   //\r
591   BrightControl = (UINT8) ((Attribute >> 3) & 1);\r
592 \r
593   //\r
594   //  convert Attribute value to terminal emulator\r
595   //  understandable background color.\r
596   //\r
597   switch ((Attribute >> 4) & 0x07) {\r
598 \r
599   case EFI_BLACK:\r
600     BackgroundControl = 40;\r
601     break;\r
602 \r
603   case EFI_BLUE:\r
604     BackgroundControl = 44;\r
605     break;\r
606 \r
607   case EFI_GREEN:\r
608     BackgroundControl = 42;\r
609     break;\r
610 \r
611   case EFI_CYAN:\r
612     BackgroundControl = 46;\r
613     break;\r
614 \r
615   case EFI_RED:\r
616     BackgroundControl = 41;\r
617     break;\r
618 \r
619   case EFI_MAGENTA:\r
620     BackgroundControl = 45;\r
621     break;\r
622 \r
623   case EFI_BROWN:\r
624     BackgroundControl = 43;\r
625     break;\r
626 \r
627   default:\r
628 \r
629   case EFI_LIGHTGRAY:\r
630     BackgroundControl = 47;\r
631     break;\r
632   }\r
633   //\r
634   // terminal emulator's control sequence to set attributes\r
635   //\r
636   mSetAttributeString[BRIGHT_CONTROL_OFFSET]          = (CHAR16) ('0' + BrightControl);\r
637   mSetAttributeString[FOREGROUND_CONTROL_OFFSET + 0]  = (CHAR16) ('0' + (ForegroundControl / 10));\r
638   mSetAttributeString[FOREGROUND_CONTROL_OFFSET + 1]  = (CHAR16) ('0' + (ForegroundControl % 10));\r
639   mSetAttributeString[BACKGROUND_CONTROL_OFFSET + 0]  = (CHAR16) ('0' + (BackgroundControl / 10));\r
640   mSetAttributeString[BACKGROUND_CONTROL_OFFSET + 1]  = (CHAR16) ('0' + (BackgroundControl % 10));\r
641 \r
642   //\r
643   // save current column and row\r
644   // for future scrolling back use.\r
645   //\r
646   SavedColumn                   = This->Mode->CursorColumn;\r
647   SavedRow                      = This->Mode->CursorRow;\r
648 \r
649   TerminalDevice->OutputEscChar = TRUE;\r
650   Status                        = This->OutputString (This, mSetAttributeString);\r
651   TerminalDevice->OutputEscChar = FALSE;\r
652 \r
653   if (EFI_ERROR (Status)) {\r
654     return EFI_DEVICE_ERROR;\r
655   }\r
656   //\r
657   //  scroll back to saved cursor position.\r
658   //\r
659   This->Mode->CursorColumn  = SavedColumn;\r
660   This->Mode->CursorRow     = SavedRow;\r
661 \r
662   This->Mode->Attribute     = (INT32) Attribute;\r
663 \r
664   return EFI_SUCCESS;\r
665 \r
666 }\r
667 \r
668 \r
669 /**\r
670   Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.ClearScreen().\r
671   It clears the ANSI terminal's display to the\r
672   currently selected background color.\r
673 \r
674   @param This     Indicates the calling context.\r
675 \r
676   @return EFI_SUCCESS       The operation completed successfully.\r
677   @return EFI_DEVICE_ERROR  The terminal screen cannot be cleared due to serial port error.\r
678   @return EFI_UNSUPPORTED   The terminal is not in a valid display mode.\r
679 \r
680 **/\r
681 EFI_STATUS\r
682 EFIAPI\r
683 TerminalConOutClearScreen (\r
684   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This\r
685   )\r
686 {\r
687   EFI_STATUS    Status;\r
688   TERMINAL_DEV  *TerminalDevice;\r
689 \r
690   TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This);\r
691 \r
692   //\r
693   //  control sequence for clear screen request\r
694   //\r
695   TerminalDevice->OutputEscChar = TRUE;\r
696   Status                        = This->OutputString (This, mClearScreenString);\r
697   TerminalDevice->OutputEscChar = FALSE;\r
698 \r
699   if (EFI_ERROR (Status)) {\r
700     return EFI_DEVICE_ERROR;\r
701   }\r
702 \r
703   Status = This->SetCursorPosition (This, 0, 0);\r
704 \r
705   return Status;\r
706 }\r
707 \r
708 \r
709 /**\r
710   Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetCursorPosition().\r
711 \r
712   @param This      Indicates the calling context.\r
713   @param Column    The row to set cursor to.\r
714   @param Row       The column to set cursor to.\r
715 \r
716   @return EFI_SUCCESS       The operation completed successfully.\r
717   @return EFI_DEVICE_ERROR  The request fails due to serial port error.\r
718   @return EFI_UNSUPPORTED   The terminal is not in a valid text mode, or the cursor position\r
719                             is invalid for current mode.\r
720 \r
721 **/\r
722 EFI_STATUS\r
723 EFIAPI\r
724 TerminalConOutSetCursorPosition (\r
725   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,\r
726   IN  UINTN                            Column,\r
727   IN  UINTN                            Row\r
728   )\r
729 {\r
730   EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode;\r
731   UINTN                       MaxColumn;\r
732   UINTN                       MaxRow;\r
733   EFI_STATUS                  Status;\r
734   TERMINAL_DEV                *TerminalDevice;\r
735 \r
736   TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This);\r
737 \r
738   //\r
739   //  get current mode\r
740   //\r
741   Mode = This->Mode;\r
742 \r
743   //\r
744   //  get geometry of current mode\r
745   //\r
746   Status = This->QueryMode (\r
747                   This,\r
748                   Mode->Mode,\r
749                   &MaxColumn,\r
750                   &MaxRow\r
751                   );\r
752   if (EFI_ERROR (Status)) {\r
753     return EFI_UNSUPPORTED;\r
754   }\r
755 \r
756   if (Column >= MaxColumn || Row >= MaxRow) {\r
757     return EFI_UNSUPPORTED;\r
758   }\r
759   //\r
760   // control sequence to move the cursor\r
761   //\r
762   mSetCursorPositionString[ROW_OFFSET + 0]    = (CHAR16) ('0' + ((Row + 1) / 10));\r
763   mSetCursorPositionString[ROW_OFFSET + 1]    = (CHAR16) ('0' + ((Row + 1) % 10));\r
764   mSetCursorPositionString[COLUMN_OFFSET + 0] = (CHAR16) ('0' + ((Column + 1) / 10));\r
765   mSetCursorPositionString[COLUMN_OFFSET + 1] = (CHAR16) ('0' + ((Column + 1) % 10));\r
766 \r
767   TerminalDevice->OutputEscChar               = TRUE;\r
768   Status = This->OutputString (This, mSetCursorPositionString);\r
769   TerminalDevice->OutputEscChar = FALSE;\r
770 \r
771   if (EFI_ERROR (Status)) {\r
772     return EFI_DEVICE_ERROR;\r
773   }\r
774   //\r
775   //  update current cursor position\r
776   //  in the Mode data structure.\r
777   //\r
778   Mode->CursorColumn  = (INT32) Column;\r
779   Mode->CursorRow     = (INT32) Row;\r
780 \r
781   return EFI_SUCCESS;\r
782 }\r
783 \r
784 \r
785 /**\r
786   Implements SIMPLE_TEXT_OUTPUT.EnableCursor().\r
787   In this driver, the cursor cannot be hidden.\r
788 \r
789   @param This      Indicates the calling context.\r
790   @param Visible   If TRUE, the cursor is set to be visible,\r
791                    If FALSE, the cursor is set to be invisible.\r
792 \r
793   @return EFI_SUCCESS      The request is valid.\r
794   @return EFI_UNSUPPORTED  The terminal does not support cursor hidden.\r
795 \r
796 **/\r
797 EFI_STATUS\r
798 EFIAPI\r
799 TerminalConOutEnableCursor (\r
800   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,\r
801   IN  BOOLEAN                          Visible\r
802   )\r
803 {\r
804   if (!Visible) {\r
805     return EFI_UNSUPPORTED;\r
806   }\r
807 \r
808   return EFI_SUCCESS;\r
809 }\r
810 \r
811 \r
812 /**\r
813   Detects if a Unicode char is for Box Drawing text graphics.\r
814 \r
815   @param  Graphic      Unicode char to test.\r
816   @param  PcAnsi       Optional pointer to return PCANSI equivalent of\r
817                        Graphic.\r
818   @param  Ascii        Optional pointer to return ASCII equivalent of\r
819                        Graphic.\r
820 \r
821   @return TRUE         If Graphic is a supported Unicode Box Drawing character.\r
822 \r
823 **/\r
824 BOOLEAN\r
825 TerminalIsValidTextGraphics (\r
826   IN  CHAR16  Graphic,\r
827   OUT CHAR8   *PcAnsi, OPTIONAL\r
828   OUT CHAR8   *Ascii OPTIONAL\r
829   )\r
830 {\r
831   UNICODE_TO_CHAR *Table;\r
832 \r
833   if ((((Graphic & 0xff00) != 0x2500) && ((Graphic & 0xff00) != 0x2100))) {\r
834     //\r
835     // Unicode drawing code charts are all in the 0x25xx range,\r
836     //  arrows are 0x21xx\r
837     //\r
838     return FALSE;\r
839   }\r
840 \r
841   for (Table = UnicodeToPcAnsiOrAscii; Table->Unicode != 0x0000; Table++) {\r
842     if (Graphic == Table->Unicode) {\r
843       if (PcAnsi != NULL) {\r
844         *PcAnsi = Table->PcAnsi;\r
845       }\r
846 \r
847       if (Ascii != NULL) {\r
848         *Ascii = Table->Ascii;\r
849       }\r
850 \r
851       return TRUE;\r
852     }\r
853   }\r
854 \r
855   return FALSE;\r
856 }\r
857 \r
858 BOOLEAN\r
859 TerminalIsValidAscii (\r
860   IN  CHAR16  Ascii\r
861   )\r
862 {\r
863   //\r
864   // valid ascii code lies in the extent of 0x20 ~ 0x7f\r
865   //\r
866   if ((Ascii >= 0x20) && (Ascii <= 0x7f)) {\r
867     return TRUE;\r
868   }\r
869 \r
870   return FALSE;\r
871 }\r
872 \r
873 BOOLEAN\r
874 TerminalIsValidEfiCntlChar (\r
875   IN  CHAR16  CharC\r
876   )\r
877 {\r
878   //\r
879   // only support four control characters.\r
880   //\r
881   if (CharC == CHAR_NULL ||\r
882       CharC == CHAR_BACKSPACE ||\r
883       CharC == CHAR_LINEFEED ||\r
884       CharC == CHAR_CARRIAGE_RETURN ||\r
885       CharC == CHAR_TAB\r
886       ) {\r
887     return TRUE;\r
888   }\r
889 \r
890   return FALSE;\r
891 }\r