~darkmuggle-deactivatedaccount/ubuntu/quantal/grub2/fix-872244

« back to all changes in this revision

Viewing changes to grub-core/term/serial.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson, Colin Watson, Evan Broder, Mario Limonciello
  • Date: 2010-11-24 13:59:55 UTC
  • mfrom: (1.17.6 upstream) (17.6.15 experimental)
  • Revision ID: james.westby@ubuntu.com-20101124135955-r6ii5sepayr7jt53
Tags: 1.99~20101124-1ubuntu1
[ Colin Watson ]
* Resynchronise with Debian experimental.  Remaining changes:
  - Adjust for default Ubuntu boot options ("quiet splash").
  - Default to hiding the menu; holding down Shift at boot will show it.
  - Set a monochromatic theme for Ubuntu.
  - Apply Ubuntu GRUB Legacy changes to legacy update-grub script: title,
    recovery mode, quiet option, tweak how memtest86+ is displayed, and
    use UUIDs where appropriate.
  - Fix backslash-escaping in merge_debconf_into_conf.
  - Remove "GNU/Linux" from default distributor string.
  - Add crashkernel= options if kdump and makedumpfile are available.
  - If other operating systems are installed, then automatically unhide
    the menu.  Otherwise, if GRUB_HIDDEN_TIMEOUT is 0, then use keystatus
    if available to check whether Shift is pressed.  If it is, show the
    menu, otherwise boot immediately.  If keystatus is not available, then
    fall back to a short delay interruptible with Escape.
  - Allow Shift to interrupt 'sleep --interruptible'.
  - Don't display introductory message about line editing unless we're
    actually offering a shell prompt.  Don't clear the screen just before
    booting if we never drew the menu in the first place.
  - Remove some verbose messages printed before reading the configuration
    file.
  - Suppress progress messages as the kernel and initrd load for
    non-recovery kernel menu entries.
  - Change prepare_grub_to_access_device to handle filesystems
    loop-mounted on file images.
  - Ignore devices loop-mounted from files in 10_linux.
  - Show the boot menu if the previous boot failed, that is if it failed
    to get to the end of one of the normal runlevels.
  - Don't generate /boot/grub/device.map during grub-install or
    grub-mkconfig by default.
  - Adjust upgrade version checks for Ubuntu.
  - Don't display "GRUB loading" unless Shift is held down.
  - Adjust versions of grub-doc and grub-legacy-doc conflicts to tolerate
    our backport of the grub-doc split.
  - Fix LVM/RAID probing in the absence of /boot/grub/device.map.
  - Look for .mo files in /usr/share/locale-langpack as well, in
    preference.
  - Make sure GRUB_TIMEOUT isn't quoted unnecessarily.
  - Probe all devices in 'grub-probe --target=drive' if
    /boot/grub/device.map is missing.
  - Build-depend on qemu-kvm rather than qemu-system for grub-pc tests.
  - Use qemu rather than qemu-system-i386.
  - Program vesafb on BIOS systems rather than efifb.
  - Add a grub-rescue-efi-amd64 package containing a rescue CD-ROM image
    for EFI-AMD64.
  - On Wubi, don't ask for an install device, but just update wubildr
    using the diverted grub-install.
  - When embedding the core image in a post-MBR gap, check for and avoid
    sectors matching any of a list of known signatures.
  - Disable video_bochs and video_cirrus on PC BIOS systems, as probing
    PCI space seems to break on some systems.
* Downgrade "ACPI shutdown failed" error to a debug message, since it can
  cause spurious test failures.

[ Evan Broder ]
* Enable lua from grub-extras.
* Incorporate the bitop library into lua.
* Add enum_pci function to grub module in lua.
* Switch back to gfxpayload=keep by default, unless the video hardware
  is known to not support it.

[ Mario Limonciello ]
* Built part_msdos and vfat into bootx64.efi (LP: #677758)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  GRUB  --  GRand Unified Bootloader
 
3
 *  Copyright (C) 2000,2001,2002,2003,2004,2005,2007,2008,2009,2010  Free Software Foundation, Inc.
 
4
 *
 
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.
 
9
 *
 
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.
 
14
 *
 
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/>.
 
17
 */
 
18
 
 
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
#include <grub/cpu/io.h>
 
26
#include <grub/extcmd.h>
 
27
#include <grub/i18n.h>
 
28
#include <grub/list.h>
 
29
 
 
30
#define FOR_SERIAL_PORTS(var) FOR_LIST_ELEMENTS((var), (grub_serial_ports))
 
31
 
 
32
/* Argument options.  */
 
33
static const struct grub_arg_option options[] =
 
34
{
 
35
  {"unit",   'u', 0, N_("Set the serial unit."),             0, ARG_TYPE_INT},
 
36
  {"port",   'p', 0, N_("Set the serial port address."),     0, ARG_TYPE_STRING},
 
37
  {"speed",  's', 0, N_("Set the serial port speed."),       0, ARG_TYPE_INT},
 
38
  {"word",   'w', 0, N_("Set the serial port word length."), 0, ARG_TYPE_INT},
 
39
  {"parity", 'r', 0, N_("Set the serial port parity."),      0, ARG_TYPE_STRING},
 
40
  {"stop",   't', 0, N_("Set the serial port stop bits."),   0, ARG_TYPE_INT},
 
41
  {0, 0, 0, 0, 0, 0}
 
42
};
 
43
 
 
44
struct grub_serial_port *grub_serial_ports;
 
45
 
 
46
struct grub_serial_output_state
 
47
{
 
48
  struct grub_terminfo_output_state tinfo;
 
49
  struct grub_serial_port *port;
 
50
};
 
51
 
 
52
struct grub_serial_input_state
 
53
{
 
54
  struct grub_terminfo_input_state tinfo;
 
55
  struct grub_serial_port *port;
 
56
};
 
57
 
 
58
static void 
 
59
serial_put (grub_term_output_t term, const int c)
 
60
{
 
61
  struct grub_serial_output_state *data = term->data;
 
62
  data->port->driver->put (data->port, c);
 
63
}
 
64
 
 
65
static int
 
66
serial_fetch (grub_term_input_t term)
 
67
{
 
68
  struct grub_serial_input_state *data = term->data;
 
69
  return data->port->driver->fetch (data->port);
 
70
}
 
71
 
 
72
const struct grub_serial_input_state grub_serial_terminfo_input_template =
 
73
  {
 
74
    .tinfo =
 
75
    {
 
76
      .readkey = serial_fetch
 
77
    }
 
78
  };
 
79
 
 
80
const struct grub_serial_output_state grub_serial_terminfo_output_template =
 
81
  {
 
82
    .tinfo =
 
83
    {
 
84
      .put = serial_put,
 
85
      .width = 80,
 
86
      .height = 24
 
87
    }
 
88
  };
 
89
 
 
90
struct grub_serial_input_state grub_serial_terminfo_input;
 
91
 
 
92
struct grub_serial_output_state grub_serial_terminfo_output;
 
93
 
 
94
int registered = 0;
 
95
 
 
96
static struct grub_term_input grub_serial_term_input =
 
97
{
 
98
  .name = "serial",
 
99
  .init = grub_terminfo_input_init,
 
100
  .getkey = grub_terminfo_getkey,
 
101
  .data = &grub_serial_terminfo_input
 
102
};
 
103
 
 
104
static struct grub_term_output grub_serial_term_output =
 
105
{
 
106
  .name = "serial",
 
107
  .putchar = grub_terminfo_putchar,
 
108
  .getwh = grub_terminfo_getwh,
 
109
  .getxy = grub_terminfo_getxy,
 
110
  .gotoxy = grub_terminfo_gotoxy,
 
111
  .cls = grub_terminfo_cls,
 
112
  .setcolorstate = grub_terminfo_setcolorstate,
 
113
  .setcursor = grub_terminfo_setcursor,
 
114
  .flags = GRUB_TERM_CODE_TYPE_ASCII,
 
115
  .data = &grub_serial_terminfo_output,
 
116
  .normal_color = GRUB_TERM_DEFAULT_NORMAL_COLOR,
 
117
  .highlight_color = GRUB_TERM_DEFAULT_HIGHLIGHT_COLOR,
 
118
};
 
119
 
 
120
 
 
121
 
 
122
static struct grub_serial_port *
 
123
grub_serial_find (char *name)
 
124
{
 
125
  struct grub_serial_port *port;
 
126
 
 
127
  FOR_SERIAL_PORTS (port)
 
128
    if (grub_strcmp (port->name, name) == 0)
 
129
      break;
 
130
 
 
131
#ifndef GRUB_MACHINE_EMU
 
132
  if (!port && grub_memcmp (name, "port", sizeof ("port") - 1) == 0
 
133
      && grub_isdigit (name [sizeof ("port") - 1]))
 
134
    {
 
135
      name = grub_serial_ns8250_add_port (grub_strtoul (&name[sizeof ("port") - 1],
 
136
                                                        0, 16));
 
137
      if (!name)
 
138
        return NULL;
 
139
 
 
140
      FOR_SERIAL_PORTS (port)
 
141
        if (grub_strcmp (port->name, name) == 0)
 
142
          break;
 
143
    }
 
144
#endif
 
145
 
 
146
  return port;
 
147
}
 
148
 
 
149
static grub_err_t
 
150
grub_cmd_serial (grub_extcmd_context_t ctxt, int argc, char **args)
 
151
{
 
152
  struct grub_arg_list *state = ctxt->state;
 
153
  char pname[40];
 
154
  char *name = NULL;
 
155
  struct grub_serial_port *port;
 
156
  struct grub_serial_config config;
 
157
  grub_err_t err;
 
158
 
 
159
  if (state[0].set)
 
160
    {
 
161
      grub_snprintf (pname, sizeof (pname), "com%ld",
 
162
                     grub_strtoul (state[0].arg, 0, 0));
 
163
      name = pname;
 
164
    }
 
165
 
 
166
  if (state[1].set)
 
167
    {
 
168
      grub_snprintf (pname, sizeof (pname), "port%lx",
 
169
                     grub_strtoul (state[1].arg, 0, 0));
 
170
      name = pname;
 
171
    }
 
172
 
 
173
  if (argc >= 1)
 
174
    name = args[0];
 
175
 
 
176
  if (!name)
 
177
    name = "com0";
 
178
 
 
179
  port = grub_serial_find (name);
 
180
  if (!port)
 
181
    return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown serial port");
 
182
 
 
183
  config = port->config;
 
184
 
 
185
  if (state[2].set)
 
186
    config.speed = grub_strtoul (state[2].arg, 0, 0);
 
187
 
 
188
  if (state[3].set)
 
189
    config.word_len = grub_strtoul (state[3].arg, 0, 0);
 
190
 
 
191
  if (state[4].set)
 
192
    {
 
193
      if (! grub_strcmp (state[4].arg, "no"))
 
194
        config.parity = GRUB_SERIAL_PARITY_NONE;
 
195
      else if (! grub_strcmp (state[4].arg, "odd"))
 
196
        config.parity = GRUB_SERIAL_PARITY_ODD;
 
197
      else if (! grub_strcmp (state[4].arg, "even"))
 
198
        config.parity = GRUB_SERIAL_PARITY_EVEN;
 
199
      else
 
200
        return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad parity");
 
201
    }
 
202
 
 
203
  if (state[5].set)
 
204
    {
 
205
      if (! grub_strcmp (state[5].arg, "1"))
 
206
        config.stop_bits = GRUB_SERIAL_STOP_BITS_1;
 
207
      else if (! grub_strcmp (state[5].arg, "2"))
 
208
        config.stop_bits = GRUB_SERIAL_STOP_BITS_2;
 
209
      else
 
210
        return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad number of stop bits");
 
211
    }
 
212
 
 
213
  /* Initialize with new settings.  */
 
214
  err = port->driver->configure (port, &config);
 
215
  if (err)
 
216
    return err;
 
217
#ifndef GRUB_MACHINE_EMU
 
218
  /* Compatibility kludge.  */
 
219
  if (port->driver == &grub_ns8250_driver)
 
220
    {
 
221
      if (!registered)
 
222
        {
 
223
          grub_terminfo_output_register (&grub_serial_term_output, "vt100");
 
224
 
 
225
          grub_term_register_input ("serial", &grub_serial_term_input);
 
226
          grub_term_register_output ("serial", &grub_serial_term_output);
 
227
        }
 
228
      grub_serial_terminfo_output.port = port;
 
229
      grub_serial_terminfo_input.port = port;
 
230
      registered = 1;
 
231
    }
 
232
#endif
 
233
  return GRUB_ERR_NONE;
 
234
}
 
235
 
 
236
grub_err_t
 
237
grub_serial_register (struct grub_serial_port *port)
 
238
{
 
239
  struct grub_term_input *in;
 
240
  struct grub_term_output *out;
 
241
  struct grub_serial_input_state *indata;
 
242
  struct grub_serial_output_state *outdata;
 
243
 
 
244
  in = grub_malloc (sizeof (*in));
 
245
  if (!in)
 
246
    return grub_errno;
 
247
 
 
248
  indata = grub_malloc (sizeof (*indata));
 
249
  if (!indata)
 
250
    {
 
251
      grub_free (in);
 
252
      return grub_errno;
 
253
    }
 
254
 
 
255
  grub_memcpy (in, &grub_serial_term_input, sizeof (*in));
 
256
  in->data = indata;
 
257
  in->name = grub_xasprintf ("serial_%s", port->name);
 
258
  grub_memcpy (indata, &grub_serial_terminfo_input, sizeof (*indata));
 
259
 
 
260
  if (!in->name)
 
261
    {
 
262
      grub_free (in);
 
263
      grub_free (indata);
 
264
      return grub_errno;
 
265
    }
 
266
  
 
267
  out = grub_malloc (sizeof (*out));
 
268
  if (!out)
 
269
    {
 
270
      grub_free (in);
 
271
      grub_free (indata);
 
272
      grub_free ((char *) in->name);
 
273
      return grub_errno;
 
274
    }
 
275
 
 
276
  outdata = grub_malloc (sizeof (*outdata));
 
277
  if (!outdata)
 
278
    {
 
279
      grub_free (in);
 
280
      grub_free (indata);
 
281
      grub_free ((char *) in->name);
 
282
      grub_free (out);
 
283
      return grub_errno;
 
284
    }
 
285
 
 
286
  grub_memcpy (out, &grub_serial_term_output, sizeof (*out));
 
287
  out->data = outdata;
 
288
  out->name = in->name;
 
289
  grub_memcpy (outdata, &grub_serial_terminfo_output, sizeof (*outdata));
 
290
 
 
291
  grub_list_push (GRUB_AS_LIST_P (&grub_serial_ports), GRUB_AS_LIST (port));
 
292
  ((struct grub_serial_input_state *) in->data)->port = port;
 
293
  ((struct grub_serial_output_state *) out->data)->port = port;
 
294
  port->term_in = in;
 
295
  port->term_out = out;
 
296
  grub_terminfo_output_register (out, "vt100");
 
297
#ifdef GRUB_MACHINE_MIPS_YEELOONG
 
298
  if (grub_strcmp (port->name, "com0") == 0)
 
299
    {
 
300
      grub_term_register_input_active ("serial_*", in);
 
301
      grub_term_register_output_active ("serial_*", out);
 
302
    }
 
303
  else
 
304
#endif
 
305
    {
 
306
      grub_term_register_input ("serial_*", in);
 
307
      grub_term_register_output ("serial_*", out);
 
308
    }
 
309
 
 
310
  return GRUB_ERR_NONE;
 
311
}
 
312
 
 
313
void
 
314
grub_serial_unregister (struct grub_serial_port *port)
 
315
{
 
316
  if (port->driver->fini)
 
317
    port->driver->fini (port);
 
318
  
 
319
  if (port->term_in)
 
320
    grub_term_unregister_input (port->term_in);
 
321
  if (port->term_out)
 
322
    grub_term_unregister_output (port->term_out);
 
323
 
 
324
  grub_list_remove (GRUB_AS_LIST_P (&grub_serial_ports), GRUB_AS_LIST (port));
 
325
}
 
326
 
 
327
void
 
328
grub_serial_unregister_driver (struct grub_serial_driver *driver)
 
329
{
 
330
  struct grub_serial_port *port, *next;
 
331
  for (port = grub_serial_ports; port; port = next)
 
332
    {
 
333
      next = port->next;
 
334
      if (port->driver == driver)
 
335
        grub_serial_unregister (port);
 
336
    }
 
337
}
 
338
 
 
339
static grub_extcmd_t cmd;
 
340
 
 
341
GRUB_MOD_INIT(serial)
 
342
{
 
343
  cmd = grub_register_extcmd ("serial", grub_cmd_serial, 0,
 
344
                              N_("[OPTIONS...]"),
 
345
                              N_("Configure serial port."), options);
 
346
  grub_memcpy (&grub_serial_terminfo_output,
 
347
               &grub_serial_terminfo_output_template,
 
348
               sizeof (grub_serial_terminfo_output));
 
349
 
 
350
  grub_memcpy (&grub_serial_terminfo_input,
 
351
               &grub_serial_terminfo_input_template,
 
352
               sizeof (grub_serial_terminfo_input));
 
353
               
 
354
#ifndef GRUB_MACHINE_EMU
 
355
  grub_ns8250_init ();
 
356
#endif
 
357
}
 
358
 
 
359
GRUB_MOD_FINI(serial)
 
360
{
 
361
  while (grub_serial_ports)
 
362
    grub_serial_unregister (grub_serial_ports);
 
363
  if (registered)
 
364
    {
 
365
      grub_term_unregister_input (&grub_serial_term_input);
 
366
      grub_term_unregister_output (&grub_serial_term_output);
 
367
    }
 
368
  grub_unregister_extcmd (cmd);
 
369
}