~ubuntu-branches/ubuntu/trusty/grub2/trusty-updates

« back to all changes in this revision

Viewing changes to term/ieee1275/ofconsole.c

Tags: upstream-1.99~20101122
ImportĀ upstreamĀ versionĀ 1.99~20101122

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*  ofconsole.c -- Open Firmware console for GRUB.  */
2
 
/*
3
 
 *  GRUB  --  GRand Unified Bootloader
4
 
 *  Copyright (C) 2003,2004,2005,2007,2008,2009  Free Software Foundation, Inc.
5
 
 *
6
 
 *  GRUB is free software: you can redistribute it and/or modify
7
 
 *  it under the terms of the GNU General Public License as published by
8
 
 *  the Free Software Foundation, either version 3 of the License, or
9
 
 *  (at your option) any later version.
10
 
 *
11
 
 *  GRUB is distributed in the hope that it will be useful,
12
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
 *  GNU General Public License for more details.
15
 
 *
16
 
 *  You should have received a copy of the GNU General Public License
17
 
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
18
 
 */
19
 
 
20
 
#include <grub/term.h>
21
 
#include <grub/types.h>
22
 
#include <grub/misc.h>
23
 
#include <grub/mm.h>
24
 
#include <grub/machine/console.h>
25
 
#include <grub/ieee1275/ieee1275.h>
26
 
 
27
 
static grub_ieee1275_ihandle_t stdout_ihandle;
28
 
static grub_ieee1275_ihandle_t stdin_ihandle;
29
 
 
30
 
static grub_uint8_t grub_ofconsole_width;
31
 
static grub_uint8_t grub_ofconsole_height;
32
 
 
33
 
static int grub_curr_x;
34
 
static int grub_curr_y;
35
 
 
36
 
static int grub_keybuf;
37
 
static int grub_buflen;
38
 
 
39
 
struct color
40
 
{
41
 
  int red;
42
 
  int green;
43
 
  int blue;
44
 
};
45
 
 
46
 
static struct color colors[] =
47
 
  {
48
 
    // {R, G, B}
49
 
    {0x00, 0x00, 0x00},
50
 
    {0x00, 0x00, 0xA8}, // 1 = blue
51
 
    {0x00, 0xA8, 0x00}, // 2 = green
52
 
    {0x00, 0xA8, 0xA8}, // 3 = cyan
53
 
    {0xA8, 0x00, 0x00}, // 4 = red
54
 
    {0xA8, 0x00, 0xA8}, // 5 = magenta
55
 
    {0xFE, 0xFE, 0x54}, // 6 = yellow
56
 
    {0xFE, 0xFE, 0xFE}  // 7 = white
57
 
  };
58
 
 
59
 
static grub_uint8_t grub_ofconsole_normal_color = 0x7;
60
 
static grub_uint8_t grub_ofconsole_highlight_color = 0x70;
61
 
 
62
 
/* Write control characters to the console.  */
63
 
static void
64
 
grub_ofconsole_writeesc (const char *str)
65
 
{
66
 
  if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_ANSI))
67
 
    return;
68
 
 
69
 
  while (*str)
70
 
    {
71
 
      char chr = *(str++);
72
 
      grub_ieee1275_write (stdout_ihandle, &chr, 1, 0);
73
 
    }
74
 
 
75
 
}
76
 
 
77
 
static void
78
 
grub_ofconsole_putchar (grub_uint32_t c)
79
 
{
80
 
  char chr = c;
81
 
  if (c == '\n')
82
 
    {
83
 
      grub_curr_y++;
84
 
      grub_curr_x = 0;
85
 
    }
86
 
  else
87
 
    {
88
 
      grub_curr_x++;
89
 
      if (grub_curr_x > grub_ofconsole_width)
90
 
        {
91
 
          grub_ofconsole_putchar ('\n');
92
 
          grub_curr_x++;
93
 
        }
94
 
    }
95
 
  grub_ieee1275_write (stdout_ihandle, &chr, 1, 0);
96
 
}
97
 
 
98
 
static grub_ssize_t
99
 
grub_ofconsole_getcharwidth (grub_uint32_t c __attribute__((unused)))
100
 
{
101
 
  return 1;
102
 
}
103
 
 
104
 
static void
105
 
grub_ofconsole_setcolorstate (grub_term_color_state state)
106
 
{
107
 
  char *setcol;
108
 
  int fg;
109
 
  int bg;
110
 
 
111
 
  switch (state)
112
 
    {
113
 
    case GRUB_TERM_COLOR_STANDARD:
114
 
    case GRUB_TERM_COLOR_NORMAL:
115
 
      fg = grub_ofconsole_normal_color & 0x0f;
116
 
      bg = grub_ofconsole_normal_color >> 4;
117
 
      break;
118
 
    case GRUB_TERM_COLOR_HIGHLIGHT:
119
 
      fg = grub_ofconsole_highlight_color & 0x0f;
120
 
      bg = grub_ofconsole_highlight_color >> 4;
121
 
      break;
122
 
    default:
123
 
      return;
124
 
    }
125
 
 
126
 
  setcol = grub_asprintf ("\e[3%dm\e[4%dm", fg, bg);
127
 
  if (setcol)
128
 
    grub_ofconsole_writeesc (setcol);
129
 
  grub_free (setcol);
130
 
}
131
 
 
132
 
static void
133
 
grub_ofconsole_setcolor (grub_uint8_t normal_color,
134
 
                         grub_uint8_t highlight_color)
135
 
{
136
 
  /* Discard bright bit.  */
137
 
  grub_ofconsole_normal_color = normal_color & 0x77;
138
 
  grub_ofconsole_highlight_color = highlight_color & 0x77;
139
 
}
140
 
 
141
 
static void
142
 
grub_ofconsole_getcolor (grub_uint8_t *normal_color, grub_uint8_t *highlight_color)
143
 
{
144
 
  *normal_color = grub_ofconsole_normal_color;
145
 
  *highlight_color = grub_ofconsole_highlight_color;
146
 
}
147
 
 
148
 
static int
149
 
grub_ofconsole_readkey (int *key)
150
 
{
151
 
  char c;
152
 
  grub_ssize_t actual = 0;
153
 
 
154
 
  grub_ieee1275_read (stdin_ihandle, &c, 1, &actual);
155
 
 
156
 
  if (actual > 0 && c == '\e')
157
 
    {
158
 
      grub_ieee1275_read (stdin_ihandle, &c, 1, &actual);
159
 
      if (actual <= 0)
160
 
        {
161
 
          *key = '\e';
162
 
          return 1;
163
 
        }
164
 
 
165
 
      if (c != 91)
166
 
        return 0;
167
 
 
168
 
      grub_ieee1275_read (stdin_ihandle, &c, 1, &actual);
169
 
      if (actual <= 0)
170
 
        return 0;
171
 
 
172
 
      switch (c)
173
 
        {
174
 
        case 65:
175
 
          /* Up: Ctrl-p.  */
176
 
          c = 16;
177
 
          break;
178
 
        case 66:
179
 
          /* Down: Ctrl-n.  */
180
 
          c = 14;
181
 
          break;
182
 
        case 67:
183
 
          /* Right: Ctrl-f.  */
184
 
          c = 6;
185
 
          break;
186
 
        case 68:
187
 
          /* Left: Ctrl-b.  */
188
 
          c = 2;
189
 
          break;
190
 
        }
191
 
    }
192
 
 
193
 
  *key = c;
194
 
  return actual > 0;
195
 
}
196
 
 
197
 
static int
198
 
grub_ofconsole_checkkey (void)
199
 
{
200
 
  int key;
201
 
  int read;
202
 
 
203
 
  if (grub_buflen)
204
 
    return 1;
205
 
 
206
 
  read = grub_ofconsole_readkey (&key);
207
 
  if (read)
208
 
    {
209
 
      grub_keybuf = key;
210
 
      grub_buflen = 1;
211
 
      return 1;
212
 
    }
213
 
 
214
 
  return -1;
215
 
}
216
 
 
217
 
static int
218
 
grub_ofconsole_getkey (void)
219
 
{
220
 
  int key;
221
 
 
222
 
  if (grub_buflen)
223
 
    {
224
 
      grub_buflen  =0;
225
 
      return grub_keybuf;
226
 
    }
227
 
 
228
 
  while (! grub_ofconsole_readkey (&key));
229
 
 
230
 
  return key;
231
 
}
232
 
 
233
 
static grub_uint16_t
234
 
grub_ofconsole_getxy (void)
235
 
{
236
 
  return ((grub_curr_x - 1) << 8) | grub_curr_y;
237
 
}
238
 
 
239
 
static grub_uint16_t
240
 
grub_ofconsole_getwh (void)
241
 
{
242
 
  grub_ieee1275_ihandle_t options;
243
 
  char *val;
244
 
  grub_ssize_t lval;
245
 
 
246
 
  if (grub_ofconsole_width && grub_ofconsole_height)
247
 
    return (grub_ofconsole_width << 8) | grub_ofconsole_height;
248
 
 
249
 
  if (! grub_ieee1275_finddevice ("/options", &options)
250
 
      && options != (grub_ieee1275_ihandle_t) -1)
251
 
    {
252
 
      if (! grub_ieee1275_get_property_length (options, "screen-#columns",
253
 
                                               &lval) && lval != -1)
254
 
        {
255
 
          val = grub_malloc (lval);
256
 
          if (val)
257
 
            {
258
 
              if (! grub_ieee1275_get_property (options, "screen-#columns",
259
 
                                                val, lval, 0))
260
 
                grub_ofconsole_width = (grub_uint8_t) grub_strtoul (val, 0, 10);
261
 
 
262
 
              grub_free (val);
263
 
            }
264
 
        }
265
 
      if (! grub_ieee1275_get_property_length (options, "screen-#rows",
266
 
                                               &lval) && lval != -1)
267
 
        {
268
 
          val = grub_malloc (lval);
269
 
          if (val)
270
 
            {
271
 
              if (! grub_ieee1275_get_property (options, "screen-#rows",
272
 
                                                val, lval, 0))
273
 
                grub_ofconsole_height = (grub_uint8_t) grub_strtoul (val, 0, 10);
274
 
 
275
 
              grub_free (val);
276
 
            }
277
 
        }
278
 
    }
279
 
 
280
 
  /* Use a small console by default.  */
281
 
  if (! grub_ofconsole_width)
282
 
    grub_ofconsole_width = 80;
283
 
  if (! grub_ofconsole_height)
284
 
    grub_ofconsole_height = 24;
285
 
 
286
 
  return (grub_ofconsole_width << 8) | grub_ofconsole_height;
287
 
}
288
 
 
289
 
static void
290
 
grub_ofconsole_gotoxy (grub_uint8_t x, grub_uint8_t y)
291
 
{
292
 
  if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_ANSI))
293
 
    {
294
 
      char *s;
295
 
      grub_curr_x = x;
296
 
      grub_curr_y = y;
297
 
 
298
 
      s = grub_asprintf ("\e[%d;%dH", y + 1, x + 1);
299
 
      if (s)
300
 
        grub_ofconsole_writeesc (s);
301
 
      grub_free (s);
302
 
    }
303
 
  else
304
 
    {
305
 
      if ((y == grub_curr_y) && (x == grub_curr_x - 1))
306
 
        {
307
 
          char chr;
308
 
 
309
 
          chr = '\b';
310
 
          grub_ieee1275_write (stdout_ihandle, &chr, 1, 0);
311
 
        }
312
 
 
313
 
      grub_curr_x = x;
314
 
      grub_curr_y = y;
315
 
    }
316
 
}
317
 
 
318
 
static void
319
 
grub_ofconsole_cls (void)
320
 
{
321
 
  /* Clear the screen.  Using serial console, screen(1) only recognizes the
322
 
   * ANSI escape sequence.  Using video console, Apple Open Firmware (version
323
 
   * 3.1.1) only recognizes the literal ^L.  So use both.  */
324
 
  grub_ofconsole_writeesc (" \e[2J");
325
 
  grub_ofconsole_gotoxy (0, 0);
326
 
}
327
 
 
328
 
static void
329
 
grub_ofconsole_setcursor (int on)
330
 
{
331
 
  /* Understood by the Open Firmware flavour in OLPC.  */
332
 
  if (on)
333
 
    grub_ieee1275_interpret ("cursor-on", 0);
334
 
  else
335
 
    grub_ieee1275_interpret ("cursor-off", 0);
336
 
}
337
 
 
338
 
static void
339
 
grub_ofconsole_refresh (void)
340
 
{
341
 
  /* Do nothing, the current console state is ok.  */
342
 
}
343
 
 
344
 
static grub_err_t
345
 
grub_ofconsole_init_input (void)
346
 
{
347
 
  grub_ssize_t actual;
348
 
 
349
 
  if (grub_ieee1275_get_integer_property (grub_ieee1275_chosen, "stdin", &stdin_ihandle,
350
 
                                          sizeof stdin_ihandle, &actual)
351
 
      || actual != sizeof stdin_ihandle)
352
 
    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "cannot find stdin");
353
 
 
354
 
  return 0;
355
 
}
356
 
 
357
 
static grub_err_t
358
 
grub_ofconsole_init_output (void)
359
 
{
360
 
  grub_ssize_t actual;
361
 
 
362
 
  /* The latest PowerMacs don't actually initialize the screen for us, so we
363
 
   * use this trick to re-open the output device (but we avoid doing this on
364
 
   * platforms where it's known to be broken). */
365
 
  if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_BROKEN_OUTPUT))
366
 
    grub_ieee1275_interpret ("output-device output", 0);
367
 
 
368
 
  if (grub_ieee1275_get_integer_property (grub_ieee1275_chosen, "stdout", &stdout_ihandle,
369
 
                                          sizeof stdout_ihandle, &actual)
370
 
      || actual != sizeof stdout_ihandle)
371
 
    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "cannot find stdout");
372
 
 
373
 
  /* Initialize colors.  */
374
 
  if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CANNOT_SET_COLORS))
375
 
    {
376
 
      unsigned col;
377
 
      for (col = 0; col < ARRAY_SIZE (colors); col++)
378
 
        grub_ieee1275_set_color (stdout_ihandle, col, colors[col].red,
379
 
                                 colors[col].green, colors[col].blue);
380
 
 
381
 
    /* Set the right fg and bg colors.  */
382
 
      grub_ofconsole_setcolorstate (GRUB_TERM_COLOR_NORMAL);
383
 
    }
384
 
 
385
 
  return 0;
386
 
}
387
 
 
388
 
static grub_err_t
389
 
grub_ofconsole_fini (void)
390
 
{
391
 
  return 0;
392
 
}
393
 
 
394
 
 
395
 
 
396
 
static struct grub_term_input grub_ofconsole_term_input =
397
 
  {
398
 
    .name = "ofconsole",
399
 
    .init = grub_ofconsole_init_input,
400
 
    .fini = grub_ofconsole_fini,
401
 
    .checkkey = grub_ofconsole_checkkey,
402
 
    .getkey = grub_ofconsole_getkey,
403
 
  };
404
 
 
405
 
static struct grub_term_output grub_ofconsole_term_output =
406
 
  {
407
 
    .name = "ofconsole",
408
 
    .init = grub_ofconsole_init_output,
409
 
    .fini = grub_ofconsole_fini,
410
 
    .putchar = grub_ofconsole_putchar,
411
 
    .getcharwidth = grub_ofconsole_getcharwidth,
412
 
    .getxy = grub_ofconsole_getxy,
413
 
    .getwh = grub_ofconsole_getwh,
414
 
    .gotoxy = grub_ofconsole_gotoxy,
415
 
    .cls = grub_ofconsole_cls,
416
 
    .setcolorstate = grub_ofconsole_setcolorstate,
417
 
    .setcolor = grub_ofconsole_setcolor,
418
 
    .getcolor = grub_ofconsole_getcolor,
419
 
    .setcursor = grub_ofconsole_setcursor,
420
 
    .refresh = grub_ofconsole_refresh
421
 
  };
422
 
 
423
 
void
424
 
grub_console_init (void)
425
 
{
426
 
  grub_term_register_input ("ofconsole", &grub_ofconsole_term_input);
427
 
  grub_term_register_output ("ofconsole", &grub_ofconsole_term_output);
428
 
}
429
 
 
430
 
void
431
 
grub_console_fini (void)
432
 
{
433
 
  grub_term_unregister_input (&grub_ofconsole_term_input);
434
 
  grub_term_unregister_output (&grub_ofconsole_term_output);
435
 
}