Add support for curses color output over serial.
[coreboot.git] / payloads / libpayload / drivers / serial.c
1 /*
2  * This file is part of the libpayload project.
3  *
4  * Copyright (C) 2008 Advanced Micro Devices, Inc.
5  * Copyright (C) 2008 Ulf Jordan <jordan@chalmers.se>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30
31 #include <config.h>
32 #include <libpayload.h>
33
34 #define IOBASE lib_sysinfo.ser_ioport
35
36 #ifdef CONFIG_SERIAL_SET_SPEED
37 #define DIVISOR (115200 / CONFIG_SERIAL_BAUD_RATE)
38 #endif
39
40 /* This is a hack - we convert the drawing characters to ASCII */
41
42 static unsigned char translate_special_chars(unsigned char c)
43 {
44         switch(c) {
45         case 196:
46                 return '-';
47         case 179:
48                 return '|';
49         case 218:
50         case 191:
51         case 192:
52         case 217:
53                 return '+';
54         default:
55                 return ' ';
56         }
57 }
58
59 void serial_init(void)
60 {
61 #ifdef CONFIG_SERIAL_SET_SPEED
62         unsigned char reg;
63
64         /* Disable interrupts. */
65         outb(0, IOBASE + 0x01);
66
67         /* Assert RTS and DTR. */
68         outb(3, IOBASE + 0x04);
69
70         /* Set the divisor latch. */
71         reg = inb(IOBASE + 0x03);
72         outb(reg | 0x80, IOBASE + 0x03);
73
74         /* Write the divisor. */
75         outb(DIVISOR & 0xFF, IOBASE);
76         outb(DIVISOR >> 8 & 0xFF, IOBASE + 1);
77
78         /* Restore the previous value of the divisor. */
79         outb(reg &= ~0x80, IOBASE + 0x03);
80 #endif
81 }
82
83 void serial_putchar(unsigned char c)
84 {
85         if (c > 127)
86                 c = translate_special_chars(c);
87
88         while ((inb(IOBASE + 0x05) & 0x20) == 0) ;
89         outb(c, IOBASE);
90 }
91
92 int serial_havechar(void)
93 {
94         return inb(IOBASE + 0x05) & 0x01;
95 }
96
97 int serial_getchar(void)
98 {
99         while (!serial_havechar()) ;
100         return (int)inb(IOBASE);
101 }
102
103 /*  These are thinly veiled vt100 functions used by curses */
104
105 #define VT100_CLEAR       "\e[H\e[J"
106 #define VT100_SBOLD       "\e[1m"
107 #define VT100_EBOLD       "\e[m"
108 #define VT100_CURSOR_ADDR "\e[%d;%dH"
109 /* The following smacs/rmacs are actually for xterm; a real vt100 has
110    enacs=\E(B\E)0, smacs=^N, rmacs=^O.  */
111 #define VT100_SMACS       "\e(0"
112 #define VT100_RMACS       "\e(B"
113 /* A vt100 doesn't do color, setaf/setab below are from xterm-color. */
114 #define VT100_SET_COLOR   "\e[3%d;4%dm"
115
116 static void serial_putcmd(char *str)
117 {
118         while(*str)
119                 serial_putchar(*(str++));
120 }
121
122 void serial_clear(void)
123 {
124         serial_putcmd(VT100_CLEAR);
125 }
126
127 void serial_start_bold(void)
128 {
129         serial_putcmd(VT100_SBOLD);
130 }
131
132 void serial_end_bold(void)
133 {
134         serial_putcmd(VT100_EBOLD);
135 }
136
137 void serial_start_altcharset(void)
138 {
139         serial_putcmd(VT100_SMACS);
140 }
141
142 void serial_end_altcharset(void)
143 {
144         serial_putcmd(VT100_RMACS);
145 }
146
147 /**
148  * Set the foreground and background colors on the serial console.
149  *
150  * @param fg Foreground color number.
151  * @param bg Background color number.
152  */
153 void serial_set_color(short fg, short bg)
154 {
155         char buffer[32];
156         snprintf(buffer, sizeof(buffer), VT100_SET_COLOR, fg, bg);
157         serial_putcmd(buffer);
158 }
159
160 void serial_set_cursor(int y, int x)
161 {
162         char buffer[32];
163         snprintf(buffer, sizeof(buffer), VT100_CURSOR_ADDR, y + 1, x + 1);
164         serial_putcmd(buffer);
165 }