]> git.proxmox.com Git - grub2.git/blame - grub-core/term/serial.c
Make color variables global instead of it being per-terminal.
[grub2.git] / grub-core / term / serial.c
CommitLineData
47d2d65e 1/*
2 * GRUB -- GRand Unified Bootloader
75eb7d11 3 * Copyright (C) 2000,2001,2002,2003,2004,2005,2007,2008,2009,2010 Free Software Foundation, Inc.
47d2d65e 4 *
5a79f472 5 * GRUB is free software: you can redistribute it and/or modify
47d2d65e 6 * it under the terms of the GNU General Public License as published by
5a79f472 7 * the Free Software Foundation, either version 3 of the License, or
47d2d65e 8 * (at your option) any later version.
9 *
5a79f472 10 * GRUB is distributed in the hope that it will be useful,
47d2d65e 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
5a79f472 16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
47d2d65e 17 */
18
ffa9860a 19#include <grub/serial.h>
47d2d65e 20#include <grub/term.h>
21#include <grub/types.h>
22#include <grub/dl.h>
23#include <grub/misc.h>
47d2d65e 24#include <grub/terminfo.h>
a9c7fd1c 25#if !defined (GRUB_MACHINE_EMU) && (defined(__mips__) || defined (__i386__) || defined (__x86_64__))
5c58b791 26#include <grub/cpu/io.h>
a9c7fd1c 27#endif
b1b797cb 28#include <grub/extcmd.h>
77a79592 29#include <grub/i18n.h>
75eb7d11 30#include <grub/list.h>
54da1feb 31#ifdef GRUB_MACHINE_MIPS_LOONGSON
74eea126
VS
32#include <grub/machine/kernel.h>
33#endif
47d2d65e 34
e745cf0c
VS
35GRUB_MOD_LICENSE ("GPLv3+");
36
75eb7d11 37#define FOR_SERIAL_PORTS(var) FOR_LIST_ELEMENTS((var), (grub_serial_ports))
47d2d65e 38
47d2d65e 39/* Argument options. */
40static const struct grub_arg_option options[] =
41{
29c44ad1 42 {"unit", 'u', 0, N_("Set the serial unit."), 0, ARG_TYPE_INT},
43 {"port", 'p', 0, N_("Set the serial port address."), 0, ARG_TYPE_STRING},
44 {"speed", 's', 0, N_("Set the serial port speed."), 0, ARG_TYPE_INT},
45 {"word", 'w', 0, N_("Set the serial port word length."), 0, ARG_TYPE_INT},
46 {"parity", 'r', 0, N_("Set the serial port parity."), 0, ARG_TYPE_STRING},
47 {"stop", 't', 0, N_("Set the serial port stop bits."), 0, ARG_TYPE_INT},
47d2d65e 48 {0, 0, 0, 0, 0, 0}
49};
50
7d4e39d6 51static struct grub_serial_port *grub_serial_ports;
47d2d65e 52
75eb7d11 53struct grub_serial_output_state
47d2d65e 54{
75eb7d11
VS
55 struct grub_terminfo_output_state tinfo;
56 struct grub_serial_port *port;
57};
47d2d65e 58
75eb7d11 59struct grub_serial_input_state
47d2d65e 60{
75eb7d11
VS
61 struct grub_terminfo_input_state tinfo;
62 struct grub_serial_port *port;
63};
47d2d65e 64
75eb7d11
VS
65static void
66serial_put (grub_term_output_t term, const int c)
47d2d65e 67{
75eb7d11
VS
68 struct grub_serial_output_state *data = term->data;
69 data->port->driver->put (data->port, c);
47d2d65e 70}
71
75eb7d11
VS
72static int
73serial_fetch (grub_term_input_t term)
47d2d65e 74{
75eb7d11
VS
75 struct grub_serial_input_state *data = term->data;
76 return data->port->driver->fetch (data->port);
47d2d65e 77}
78
7d4e39d6 79static const struct grub_serial_input_state grub_serial_terminfo_input_template =
bf873374 80 {
75eb7d11
VS
81 .tinfo =
82 {
83 .readkey = serial_fetch
84 }
bf873374 85 };
47d2d65e 86
7d4e39d6 87static const struct grub_serial_output_state grub_serial_terminfo_output_template =
bf873374 88 {
75eb7d11
VS
89 .tinfo =
90 {
a9cc5438
VS
91 .put = serial_put,
92 .width = 80,
93 .height = 24
75eb7d11 94 }
bf873374 95 };
47d2d65e 96
7d4e39d6 97static struct grub_serial_input_state grub_serial_terminfo_input;
9c693bd6 98
7d4e39d6 99static struct grub_serial_output_state grub_serial_terminfo_output;
9c693bd6 100
7d4e39d6 101static int registered = 0;
75eb7d11 102
651c29b7 103static struct grub_term_input grub_serial_term_input =
47d2d65e 104{
105 .name = "serial",
bf873374 106 .init = grub_terminfo_input_init,
bf873374
VS
107 .getkey = grub_terminfo_getkey,
108 .data = &grub_serial_terminfo_input
651c29b7 109};
110
111static struct grub_term_output grub_serial_term_output =
112{
113 .name = "serial",
b3f8d28a 114 .init = grub_terminfo_output_init,
bf873374 115 .putchar = grub_terminfo_putchar,
a9cc5438 116 .getwh = grub_terminfo_getwh,
bf873374
VS
117 .getxy = grub_terminfo_getxy,
118 .gotoxy = grub_terminfo_gotoxy,
119 .cls = grub_terminfo_cls,
120 .setcolorstate = grub_terminfo_setcolorstate,
bf873374 121 .setcursor = grub_terminfo_setcursor,
d6e0e85b 122 .flags = GRUB_TERM_CODE_TYPE_ASCII,
3c151d94 123 .data = &grub_serial_terminfo_output,
47d2d65e 124};
125
126\f
127
33f784e8 128struct grub_serial_port *
bf3a3857 129grub_serial_find (const char *name)
75eb7d11
VS
130{
131 struct grub_serial_port *port;
132
133 FOR_SERIAL_PORTS (port)
134 if (grub_strcmp (port->name, name) == 0)
135 break;
136
a9c7fd1c 137#if (defined(__mips__) || defined (__i386__) || defined (__x86_64__)) && !defined(GRUB_MACHINE_EMU)
75eb7d11 138 if (!port && grub_memcmp (name, "port", sizeof ("port") - 1) == 0
0eb8ffb1 139 && grub_isxdigit (name [sizeof ("port") - 1]))
75eb7d11
VS
140 {
141 name = grub_serial_ns8250_add_port (grub_strtoul (&name[sizeof ("port") - 1],
142 0, 16));
143 if (!name)
144 return NULL;
145
146 FOR_SERIAL_PORTS (port)
147 if (grub_strcmp (port->name, name) == 0)
148 break;
149 }
44e7b8cb 150#endif
75eb7d11
VS
151
152 return port;
153}
154
47d2d65e 155static grub_err_t
928bad47 156grub_cmd_serial (grub_extcmd_context_t ctxt, int argc, char **args)
47d2d65e 157{
928bad47 158 struct grub_arg_list *state = ctxt->state;
75eb7d11 159 char pname[40];
bf3a3857 160 const char *name = NULL;
75eb7d11 161 struct grub_serial_port *port;
8c8e2699 162 struct grub_serial_config config;
75eb7d11 163 grub_err_t err;
47d2d65e 164
165 if (state[0].set)
166 {
75eb7d11
VS
167 grub_snprintf (pname, sizeof (pname), "com%ld",
168 grub_strtoul (state[0].arg, 0, 0));
169 name = pname;
47d2d65e 170 }
b39f9d20 171
47d2d65e 172 if (state[1].set)
47d2d65e 173 {
75eb7d11
VS
174 grub_snprintf (pname, sizeof (pname), "port%lx",
175 grub_strtoul (state[1].arg, 0, 0));
176 name = pname;
47d2d65e 177 }
b39f9d20 178
75eb7d11
VS
179 if (argc >= 1)
180 name = args[0];
181
182 if (!name)
183 name = "com0";
184
185 port = grub_serial_find (name);
186 if (!port)
d61386e2
VS
187 return grub_error (GRUB_ERR_BAD_ARGUMENT,
188 N_("serial port `%s' isn't found"),
189 name);
75eb7d11 190
8c8e2699 191 config = port->config;
75eb7d11
VS
192
193 if (state[2].set)
8c8e2699 194 config.speed = grub_strtoul (state[2].arg, 0, 0);
75eb7d11 195
47d2d65e 196 if (state[3].set)
fd5b6637 197 config.word_len = grub_strtoul (state[3].arg, 0, 0);
b39f9d20 198
47d2d65e 199 if (state[4].set)
200 {
201 if (! grub_strcmp (state[4].arg, "no"))
1da07b14 202 config.parity = GRUB_SERIAL_PARITY_NONE;
47d2d65e 203 else if (! grub_strcmp (state[4].arg, "odd"))
1da07b14 204 config.parity = GRUB_SERIAL_PARITY_ODD;
47d2d65e 205 else if (! grub_strcmp (state[4].arg, "even"))
1da07b14 206 config.parity = GRUB_SERIAL_PARITY_EVEN;
47d2d65e 207 else
d61386e2
VS
208 return grub_error (GRUB_ERR_BAD_ARGUMENT,
209 N_("unsupported serial port parity"));
47d2d65e 210 }
b39f9d20 211
47d2d65e 212 if (state[5].set)
213 {
214 if (! grub_strcmp (state[5].arg, "1"))
1da07b14 215 config.stop_bits = GRUB_SERIAL_STOP_BITS_1;
47d2d65e 216 else if (! grub_strcmp (state[5].arg, "2"))
1da07b14 217 config.stop_bits = GRUB_SERIAL_STOP_BITS_2;
08dafeea
VS
218 else if (! grub_strcmp (state[5].arg, "1.5"))
219 config.stop_bits = GRUB_SERIAL_STOP_BITS_1_5;
47d2d65e 220 else
d61386e2
VS
221 return grub_error (GRUB_ERR_BAD_ARGUMENT,
222 N_("unsupported serial port stop bits number"));
47d2d65e 223 }
224
225 /* Initialize with new settings. */
8c8e2699 226 err = port->driver->configure (port, &config);
75eb7d11
VS
227 if (err)
228 return err;
a9c7fd1c
VS
229#if !defined (GRUB_MACHINE_EMU) && (defined(__mips__) || defined (__i386__) || defined (__x86_64__))
230
24494d47
VS
231 /* Compatibility kludge. */
232 if (port->driver == &grub_ns8250_driver)
75eb7d11 233 {
24494d47
VS
234 if (!registered)
235 {
9c693bd6
VS
236 grub_terminfo_output_register (&grub_serial_term_output, "vt100");
237
24494d47
VS
238 grub_term_register_input ("serial", &grub_serial_term_input);
239 grub_term_register_output ("serial", &grub_serial_term_output);
240 }
241 grub_serial_terminfo_output.port = port;
242 grub_serial_terminfo_input.port = port;
243 registered = 1;
75eb7d11 244 }
44e7b8cb 245#endif
75eb7d11
VS
246 return GRUB_ERR_NONE;
247}
248
14a2562c
VS
249#ifdef GRUB_MACHINE_MIPS_LOONGSON
250const char loongson_defserial[][6] =
251 {
252 [GRUB_ARCH_MACHINE_YEELOONG] = "com0",
253 [GRUB_ARCH_MACHINE_FULOONG2F] = "com2",
254 [GRUB_ARCH_MACHINE_FULOONG2E] = "com1"
255 };
256#endif
257
75eb7d11
VS
258grub_err_t
259grub_serial_register (struct grub_serial_port *port)
260{
261 struct grub_term_input *in;
262 struct grub_term_output *out;
263 struct grub_serial_input_state *indata;
264 struct grub_serial_output_state *outdata;
b39f9d20 265
75eb7d11
VS
266 in = grub_malloc (sizeof (*in));
267 if (!in)
268 return grub_errno;
269
270 indata = grub_malloc (sizeof (*indata));
271 if (!indata)
47d2d65e 272 {
75eb7d11
VS
273 grub_free (in);
274 return grub_errno;
47d2d65e 275 }
75eb7d11
VS
276
277 grub_memcpy (in, &grub_serial_term_input, sizeof (*in));
278 in->data = indata;
279 in->name = grub_xasprintf ("serial_%s", port->name);
280 grub_memcpy (indata, &grub_serial_terminfo_input, sizeof (*indata));
281
282 if (!in->name)
283 {
284 grub_free (in);
285 grub_free (indata);
286 return grub_errno;
287 }
288
289 out = grub_malloc (sizeof (*out));
290 if (!out)
291 {
292 grub_free (in);
293 grub_free (indata);
294 grub_free ((char *) in->name);
295 return grub_errno;
296 }
297
298 outdata = grub_malloc (sizeof (*outdata));
299 if (!outdata)
47d2d65e 300 {
75eb7d11
VS
301 grub_free (in);
302 grub_free (indata);
303 grub_free ((char *) in->name);
304 grub_free (out);
305 return grub_errno;
47d2d65e 306 }
b39f9d20 307
75eb7d11
VS
308 grub_memcpy (out, &grub_serial_term_output, sizeof (*out));
309 out->data = outdata;
310 out->name = in->name;
311 grub_memcpy (outdata, &grub_serial_terminfo_output, sizeof (*outdata));
312
313 grub_list_push (GRUB_AS_LIST_P (&grub_serial_ports), GRUB_AS_LIST (port));
314 ((struct grub_serial_input_state *) in->data)->port = port;
315 ((struct grub_serial_output_state *) out->data)->port = port;
24494d47
VS
316 port->term_in = in;
317 port->term_out = out;
75eb7d11 318 grub_terminfo_output_register (out, "vt100");
54da1feb 319#ifdef GRUB_MACHINE_MIPS_LOONGSON
14a2562c 320 if (grub_strcmp (port->name, loongson_defserial[grub_arch_machine]) == 0)
24494d47
VS
321 {
322 grub_term_register_input_active ("serial_*", in);
323 grub_term_register_output_active ("serial_*", out);
324 }
d7345994
VS
325 else
326 {
327 grub_term_register_input_inactive ("serial_*", in);
328 grub_term_register_output_inactive ("serial_*", out);
329 }
74eea126
VS
330#else
331 grub_term_register_input ("serial_*", in);
332 grub_term_register_output ("serial_*", out);
333#endif
75eb7d11
VS
334
335 return GRUB_ERR_NONE;
336}
337
338void
339grub_serial_unregister (struct grub_serial_port *port)
340{
24494d47
VS
341 if (port->driver->fini)
342 port->driver->fini (port);
343
344 if (port->term_in)
345 grub_term_unregister_input (port->term_in);
346 if (port->term_out)
347 grub_term_unregister_output (port->term_out);
348
87edb894 349 grub_list_remove (GRUB_AS_LIST (port));
24494d47
VS
350}
351
352void
353grub_serial_unregister_driver (struct grub_serial_driver *driver)
354{
355 struct grub_serial_port *port, *next;
356 for (port = grub_serial_ports; port; port = next)
357 {
358 next = port->next;
359 if (port->driver == driver)
360 grub_serial_unregister (port);
361 }
47d2d65e 362}
363
b1b797cb 364static grub_extcmd_t cmd;
365
036985b8
VS
366#if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS)
367void grub_serial_init (void)
368#else
6d099807 369GRUB_MOD_INIT(serial)
036985b8 370#endif
47d2d65e 371{
ed80f7d5 372 cmd = grub_register_extcmd ("serial", grub_cmd_serial, 0,
d8b5cd40
VS
373 N_("[OPTIONS...]"),
374 N_("Configure serial port."), options);
9c693bd6
VS
375 grub_memcpy (&grub_serial_terminfo_output,
376 &grub_serial_terminfo_output_template,
377 sizeof (grub_serial_terminfo_output));
378
379 grub_memcpy (&grub_serial_terminfo_input,
380 &grub_serial_terminfo_input_template,
381 sizeof (grub_serial_terminfo_input));
a9c7fd1c
VS
382
383#if !defined (GRUB_MACHINE_EMU) && (defined(__mips__) || defined (__i386__) || defined (__x86_64__))
75eb7d11 384 grub_ns8250_init ();
44e7b8cb 385#endif
a9c7fd1c
VS
386#ifdef GRUB_MACHINE_IEEE1275
387 grub_ofserial_init ();
388#endif
389#ifdef GRUB_MACHINE_EFI
390 grub_efiserial_init ();
391#endif
47d2d65e 392}
393
036985b8
VS
394#if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS)
395void grub_serial_fini (void)
396#else
6d099807 397GRUB_MOD_FINI(serial)
036985b8 398#endif
47d2d65e 399{
75eb7d11
VS
400 while (grub_serial_ports)
401 grub_serial_unregister (grub_serial_ports);
24494d47
VS
402 if (registered)
403 {
404 grub_term_unregister_input (&grub_serial_term_input);
405 grub_term_unregister_output (&grub_serial_term_output);
406 }
b1b797cb 407 grub_unregister_extcmd (cmd);
47d2d65e 408}