Upgraded GRUB2 to 2.00 release.
[AROS.git] / arch / all-pc / boot / grub2-aros / grub-core / term / serial.c
blobe1469e57ae813b14e96f1405dd8045e1dde6c9e3
1 /*
2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2000,2001,2002,2003,2004,2005,2007,2008,2009,2010 Free Software Foundation, Inc.
5 * GRUB is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * GRUB is distributed in the hope that it will be useful,
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.
15 * You should have received a copy of the GNU General Public License
16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
19 #include <grub/serial.h>
20 #include <grub/term.h>
21 #include <grub/types.h>
22 #include <grub/dl.h>
23 #include <grub/misc.h>
24 #include <grub/terminfo.h>
25 #if !defined (GRUB_MACHINE_EMU) && (defined(__mips__) || defined (__i386__) || defined (__x86_64__))
26 #include <grub/cpu/io.h>
27 #endif
28 #include <grub/extcmd.h>
29 #include <grub/i18n.h>
30 #include <grub/list.h>
31 #ifdef GRUB_MACHINE_MIPS_LOONGSON
32 #include <grub/machine/kernel.h>
33 #endif
35 GRUB_MOD_LICENSE ("GPLv3+");
37 #define FOR_SERIAL_PORTS(var) FOR_LIST_ELEMENTS((var), (grub_serial_ports))
39 /* Argument options. */
40 static const struct grub_arg_option options[] =
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},
48 {0, 0, 0, 0, 0, 0}
51 static struct grub_serial_port *grub_serial_ports;
53 struct grub_serial_output_state
55 struct grub_terminfo_output_state tinfo;
56 struct grub_serial_port *port;
59 struct grub_serial_input_state
61 struct grub_terminfo_input_state tinfo;
62 struct grub_serial_port *port;
65 static void
66 serial_put (grub_term_output_t term, const int c)
68 struct grub_serial_output_state *data = term->data;
69 data->port->driver->put (data->port, c);
72 static int
73 serial_fetch (grub_term_input_t term)
75 struct grub_serial_input_state *data = term->data;
76 return data->port->driver->fetch (data->port);
79 static const struct grub_serial_input_state grub_serial_terminfo_input_template =
81 .tinfo =
83 .readkey = serial_fetch
87 static const struct grub_serial_output_state grub_serial_terminfo_output_template =
89 .tinfo =
91 .put = serial_put,
92 .width = 80,
93 .height = 24
97 static struct grub_serial_input_state grub_serial_terminfo_input;
99 static struct grub_serial_output_state grub_serial_terminfo_output;
101 static int registered = 0;
103 static struct grub_term_input grub_serial_term_input =
105 .name = "serial",
106 .init = grub_terminfo_input_init,
107 .getkey = grub_terminfo_getkey,
108 .data = &grub_serial_terminfo_input
111 static struct grub_term_output grub_serial_term_output =
113 .name = "serial",
114 .init = grub_terminfo_output_init,
115 .putchar = grub_terminfo_putchar,
116 .getwh = grub_terminfo_getwh,
117 .getxy = grub_terminfo_getxy,
118 .gotoxy = grub_terminfo_gotoxy,
119 .cls = grub_terminfo_cls,
120 .setcolorstate = grub_terminfo_setcolorstate,
121 .setcursor = grub_terminfo_setcursor,
122 .flags = GRUB_TERM_CODE_TYPE_ASCII,
123 .data = &grub_serial_terminfo_output,
124 .normal_color = GRUB_TERM_DEFAULT_NORMAL_COLOR,
125 .highlight_color = GRUB_TERM_DEFAULT_HIGHLIGHT_COLOR,
130 struct grub_serial_port *
131 grub_serial_find (const char *name)
133 struct grub_serial_port *port;
135 FOR_SERIAL_PORTS (port)
136 if (grub_strcmp (port->name, name) == 0)
137 break;
139 #if (defined(__mips__) || defined (__i386__) || defined (__x86_64__)) && !defined(GRUB_MACHINE_EMU)
140 if (!port && grub_memcmp (name, "port", sizeof ("port") - 1) == 0
141 && grub_isxdigit (name [sizeof ("port") - 1]))
143 name = grub_serial_ns8250_add_port (grub_strtoul (&name[sizeof ("port") - 1],
144 0, 16));
145 if (!name)
146 return NULL;
148 FOR_SERIAL_PORTS (port)
149 if (grub_strcmp (port->name, name) == 0)
150 break;
152 #endif
154 return port;
157 static grub_err_t
158 grub_cmd_serial (grub_extcmd_context_t ctxt, int argc, char **args)
160 struct grub_arg_list *state = ctxt->state;
161 char pname[40];
162 const char *name = NULL;
163 struct grub_serial_port *port;
164 struct grub_serial_config config;
165 grub_err_t err;
167 if (state[0].set)
169 grub_snprintf (pname, sizeof (pname), "com%ld",
170 grub_strtoul (state[0].arg, 0, 0));
171 name = pname;
174 if (state[1].set)
176 grub_snprintf (pname, sizeof (pname), "port%lx",
177 grub_strtoul (state[1].arg, 0, 0));
178 name = pname;
181 if (argc >= 1)
182 name = args[0];
184 if (!name)
185 name = "com0";
187 port = grub_serial_find (name);
188 if (!port)
189 return grub_error (GRUB_ERR_BAD_ARGUMENT,
190 N_("serial port `%s' isn't found"),
191 name);
193 config = port->config;
195 if (state[2].set)
196 config.speed = grub_strtoul (state[2].arg, 0, 0);
198 if (state[3].set)
199 config.word_len = grub_strtoul (state[3].arg, 0, 0);
201 if (state[4].set)
203 if (! grub_strcmp (state[4].arg, "no"))
204 config.parity = GRUB_SERIAL_PARITY_NONE;
205 else if (! grub_strcmp (state[4].arg, "odd"))
206 config.parity = GRUB_SERIAL_PARITY_ODD;
207 else if (! grub_strcmp (state[4].arg, "even"))
208 config.parity = GRUB_SERIAL_PARITY_EVEN;
209 else
210 return grub_error (GRUB_ERR_BAD_ARGUMENT,
211 N_("unsupported serial port parity"));
214 if (state[5].set)
216 if (! grub_strcmp (state[5].arg, "1"))
217 config.stop_bits = GRUB_SERIAL_STOP_BITS_1;
218 else if (! grub_strcmp (state[5].arg, "2"))
219 config.stop_bits = GRUB_SERIAL_STOP_BITS_2;
220 else if (! grub_strcmp (state[5].arg, "1.5"))
221 config.stop_bits = GRUB_SERIAL_STOP_BITS_1_5;
222 else
223 return grub_error (GRUB_ERR_BAD_ARGUMENT,
224 N_("unsupported serial port stop bits number"));
227 /* Initialize with new settings. */
228 err = port->driver->configure (port, &config);
229 if (err)
230 return err;
231 #if !defined (GRUB_MACHINE_EMU) && (defined(__mips__) || defined (__i386__) || defined (__x86_64__))
233 /* Compatibility kludge. */
234 if (port->driver == &grub_ns8250_driver)
236 if (!registered)
238 grub_terminfo_output_register (&grub_serial_term_output, "vt100");
240 grub_term_register_input ("serial", &grub_serial_term_input);
241 grub_term_register_output ("serial", &grub_serial_term_output);
243 grub_serial_terminfo_output.port = port;
244 grub_serial_terminfo_input.port = port;
245 registered = 1;
247 #endif
248 return GRUB_ERR_NONE;
251 #ifdef GRUB_MACHINE_MIPS_LOONGSON
252 const char loongson_defserial[][6] =
254 [GRUB_ARCH_MACHINE_YEELOONG] = "com0",
255 [GRUB_ARCH_MACHINE_FULOONG2F] = "com2",
256 [GRUB_ARCH_MACHINE_FULOONG2E] = "com1"
258 #endif
260 grub_err_t
261 grub_serial_register (struct grub_serial_port *port)
263 struct grub_term_input *in;
264 struct grub_term_output *out;
265 struct grub_serial_input_state *indata;
266 struct grub_serial_output_state *outdata;
268 in = grub_malloc (sizeof (*in));
269 if (!in)
270 return grub_errno;
272 indata = grub_malloc (sizeof (*indata));
273 if (!indata)
275 grub_free (in);
276 return grub_errno;
279 grub_memcpy (in, &grub_serial_term_input, sizeof (*in));
280 in->data = indata;
281 in->name = grub_xasprintf ("serial_%s", port->name);
282 grub_memcpy (indata, &grub_serial_terminfo_input, sizeof (*indata));
284 if (!in->name)
286 grub_free (in);
287 grub_free (indata);
288 return grub_errno;
291 out = grub_malloc (sizeof (*out));
292 if (!out)
294 grub_free (in);
295 grub_free (indata);
296 grub_free ((char *) in->name);
297 return grub_errno;
300 outdata = grub_malloc (sizeof (*outdata));
301 if (!outdata)
303 grub_free (in);
304 grub_free (indata);
305 grub_free ((char *) in->name);
306 grub_free (out);
307 return grub_errno;
310 grub_memcpy (out, &grub_serial_term_output, sizeof (*out));
311 out->data = outdata;
312 out->name = in->name;
313 grub_memcpy (outdata, &grub_serial_terminfo_output, sizeof (*outdata));
315 grub_list_push (GRUB_AS_LIST_P (&grub_serial_ports), GRUB_AS_LIST (port));
316 ((struct grub_serial_input_state *) in->data)->port = port;
317 ((struct grub_serial_output_state *) out->data)->port = port;
318 port->term_in = in;
319 port->term_out = out;
320 grub_terminfo_output_register (out, "vt100");
321 #ifdef GRUB_MACHINE_MIPS_LOONGSON
322 if (grub_strcmp (port->name, loongson_defserial[grub_arch_machine]) == 0)
324 grub_term_register_input_active ("serial_*", in);
325 grub_term_register_output_active ("serial_*", out);
327 else
329 grub_term_register_input_inactive ("serial_*", in);
330 grub_term_register_output_inactive ("serial_*", out);
332 #else
333 grub_term_register_input ("serial_*", in);
334 grub_term_register_output ("serial_*", out);
335 #endif
337 return GRUB_ERR_NONE;
340 void
341 grub_serial_unregister (struct grub_serial_port *port)
343 if (port->driver->fini)
344 port->driver->fini (port);
346 if (port->term_in)
347 grub_term_unregister_input (port->term_in);
348 if (port->term_out)
349 grub_term_unregister_output (port->term_out);
351 grub_list_remove (GRUB_AS_LIST (port));
354 void
355 grub_serial_unregister_driver (struct grub_serial_driver *driver)
357 struct grub_serial_port *port, *next;
358 for (port = grub_serial_ports; port; port = next)
360 next = port->next;
361 if (port->driver == driver)
362 grub_serial_unregister (port);
366 static grub_extcmd_t cmd;
368 #if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS)
369 void grub_serial_init (void)
370 #else
371 GRUB_MOD_INIT(serial)
372 #endif
374 cmd = grub_register_extcmd ("serial", grub_cmd_serial, 0,
375 N_("[OPTIONS...]"),
376 N_("Configure serial port."), options);
377 grub_memcpy (&grub_serial_terminfo_output,
378 &grub_serial_terminfo_output_template,
379 sizeof (grub_serial_terminfo_output));
381 grub_memcpy (&grub_serial_terminfo_input,
382 &grub_serial_terminfo_input_template,
383 sizeof (grub_serial_terminfo_input));
385 #if !defined (GRUB_MACHINE_EMU) && (defined(__mips__) || defined (__i386__) || defined (__x86_64__))
386 grub_ns8250_init ();
387 #endif
388 #ifdef GRUB_MACHINE_IEEE1275
389 grub_ofserial_init ();
390 #endif
391 #ifdef GRUB_MACHINE_EFI
392 grub_efiserial_init ();
393 #endif
396 #if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS)
397 void grub_serial_fini (void)
398 #else
399 GRUB_MOD_FINI(serial)
400 #endif
402 while (grub_serial_ports)
403 grub_serial_unregister (grub_serial_ports);
404 if (registered)
406 grub_term_unregister_input (&grub_serial_term_input);
407 grub_term_unregister_output (&grub_serial_term_output);
409 grub_unregister_extcmd (cmd);