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>
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>
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>
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
},
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
;
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
);
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
=
83 .readkey
= serial_fetch
87 static const struct grub_serial_output_state grub_serial_terminfo_output_template
=
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
=
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
=
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)
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],
148 FOR_SERIAL_PORTS (port
)
149 if (grub_strcmp (port
->name
, name
) == 0)
158 grub_cmd_serial (grub_extcmd_context_t ctxt
, int argc
, char **args
)
160 struct grub_arg_list
*state
= ctxt
->state
;
162 const char *name
= NULL
;
163 struct grub_serial_port
*port
;
164 struct grub_serial_config config
;
169 grub_snprintf (pname
, sizeof (pname
), "com%ld",
170 grub_strtoul (state
[0].arg
, 0, 0));
176 grub_snprintf (pname
, sizeof (pname
), "port%lx",
177 grub_strtoul (state
[1].arg
, 0, 0));
187 port
= grub_serial_find (name
);
189 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
190 N_("serial port `%s' isn't found"),
193 config
= port
->config
;
196 config
.speed
= grub_strtoul (state
[2].arg
, 0, 0);
199 config
.word_len
= grub_strtoul (state
[3].arg
, 0, 0);
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
;
210 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
211 N_("unsupported serial port parity"));
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
;
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
);
231 #if !defined (GRUB_MACHINE_EMU) && (defined(__mips__) || defined (__i386__) || defined (__x86_64__))
233 /* Compatibility kludge. */
234 if (port
->driver
== &grub_ns8250_driver
)
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
;
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"
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
));
272 indata
= grub_malloc (sizeof (*indata
));
279 grub_memcpy (in
, &grub_serial_term_input
, sizeof (*in
));
281 in
->name
= grub_xasprintf ("serial_%s", port
->name
);
282 grub_memcpy (indata
, &grub_serial_terminfo_input
, sizeof (*indata
));
291 out
= grub_malloc (sizeof (*out
));
296 grub_free ((char *) in
->name
);
300 outdata
= grub_malloc (sizeof (*outdata
));
305 grub_free ((char *) in
->name
);
310 grub_memcpy (out
, &grub_serial_term_output
, sizeof (*out
));
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
;
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
);
329 grub_term_register_input_inactive ("serial_*", in
);
330 grub_term_register_output_inactive ("serial_*", out
);
333 grub_term_register_input ("serial_*", in
);
334 grub_term_register_output ("serial_*", out
);
337 return GRUB_ERR_NONE
;
341 grub_serial_unregister (struct grub_serial_port
*port
)
343 if (port
->driver
->fini
)
344 port
->driver
->fini (port
);
347 grub_term_unregister_input (port
->term_in
);
349 grub_term_unregister_output (port
->term_out
);
351 grub_list_remove (GRUB_AS_LIST (port
));
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
)
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)
371 GRUB_MOD_INIT(serial
)
374 cmd
= grub_register_extcmd ("serial", grub_cmd_serial
, 0,
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__))
388 #ifdef GRUB_MACHINE_IEEE1275
389 grub_ofserial_init ();
391 #ifdef GRUB_MACHINE_EFI
392 grub_efiserial_init ();
396 #if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS)
397 void grub_serial_fini (void)
399 GRUB_MOD_FINI(serial
)
402 while (grub_serial_ports
)
403 grub_serial_unregister (grub_serial_ports
);
406 grub_term_unregister_input (&grub_serial_term_input
);
407 grub_term_unregister_output (&grub_serial_term_output
);
409 grub_unregister_extcmd (cmd
);