1 /* ofconsole.c -- Open Firmware console for GRUB. */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2003,2004,2005,2007,2008,2009 Free Software Foundation, Inc.
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.
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.
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/>.
20 #include <grub/term.h>
21 #include <grub/types.h>
22 #include <grub/misc.h>
24 #include <grub/time.h>
25 #include <grub/machine/console.h>
26 #include <grub/ieee1275/ieee1275.h>
28 static grub_ieee1275_ihandle_t stdout_ihandle
;
29 static grub_ieee1275_ihandle_t stdin_ihandle
;
31 static grub_uint8_t grub_ofconsole_width
;
32 static grub_uint8_t grub_ofconsole_height
;
34 static int grub_curr_x
;
35 static int grub_curr_y
;
37 static int grub_keybuf
;
38 static int grub_buflen
;
47 static struct color colors
[] =
51 {0x00, 0x00, 0xA8}, // 1 = blue
52 {0x00, 0xA8, 0x00}, // 2 = green
53 {0x00, 0xA8, 0xA8}, // 3 = cyan
54 {0xA8, 0x00, 0x00}, // 4 = red
55 {0xA8, 0x00, 0xA8}, // 5 = magenta
56 {0xFE, 0xFE, 0x54}, // 6 = yellow
57 {0xFE, 0xFE, 0xFE} // 7 = white
60 static grub_uint8_t grub_ofconsole_normal_color
= 0x7;
61 static grub_uint8_t grub_ofconsole_highlight_color
= 0x70;
63 /* Write control characters to the console. */
65 grub_ofconsole_writeesc (const char *str
)
67 if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_ANSI
))
73 grub_ieee1275_write (stdout_ihandle
, &chr
, 1, 0);
79 grub_ofconsole_putchar (grub_uint32_t c
)
85 /* Better than nothing. */
88 case GRUB_TERM_DISP_LEFT
:
92 case GRUB_TERM_DISP_UP
:
96 case GRUB_TERM_DISP_RIGHT
:
100 case GRUB_TERM_DISP_DOWN
:
104 case GRUB_TERM_DISP_HLINE
:
108 case GRUB_TERM_DISP_VLINE
:
112 case GRUB_TERM_DISP_UL
:
113 case GRUB_TERM_DISP_UR
:
114 case GRUB_TERM_DISP_LL
:
115 case GRUB_TERM_DISP_LR
:
139 if (grub_curr_x
>= grub_ofconsole_width
)
141 grub_ofconsole_putchar ('\n');
142 grub_ofconsole_putchar ('\r');
146 grub_ieee1275_write (stdout_ihandle
, &chr
, 1, 0);
150 grub_ofconsole_getcharwidth (grub_uint32_t c
__attribute__((unused
)))
156 grub_ofconsole_setcolorstate (grub_term_color_state state
)
164 case GRUB_TERM_COLOR_STANDARD
:
165 case GRUB_TERM_COLOR_NORMAL
:
166 fg
= grub_ofconsole_normal_color
& 0x0f;
167 bg
= grub_ofconsole_normal_color
>> 4;
169 case GRUB_TERM_COLOR_HIGHLIGHT
:
170 fg
= grub_ofconsole_highlight_color
& 0x0f;
171 bg
= grub_ofconsole_highlight_color
>> 4;
177 grub_snprintf (setcol
, sizeof (setcol
), "\e[3%dm\e[4%dm", fg
, bg
);
178 grub_ofconsole_writeesc (setcol
);
182 grub_ofconsole_setcolor (grub_uint8_t normal_color
,
183 grub_uint8_t highlight_color
)
185 /* Discard bright bit. */
186 grub_ofconsole_normal_color
= normal_color
& 0x77;
187 grub_ofconsole_highlight_color
= highlight_color
& 0x77;
191 grub_ofconsole_getcolor (grub_uint8_t
*normal_color
, grub_uint8_t
*highlight_color
)
193 *normal_color
= grub_ofconsole_normal_color
;
194 *highlight_color
= grub_ofconsole_highlight_color
;
198 grub_ofconsole_readkey (int *key
)
201 grub_ssize_t actual
= 0;
203 grub_ieee1275_read (stdin_ihandle
, &c
, 1, &actual
);
209 /* Backspace: Ctrl-h. */
215 grub_ieee1275_read (stdin_ihandle
, &c
, 1, &actual
);
217 /* On 9600 we have to wait up to 12 milliseconds. */
218 start
= grub_get_time_ms ();
219 while (actual
<= 0 && grub_get_time_ms () - start
< 12)
220 grub_ieee1275_read (stdin_ihandle
, &c
, 1, &actual
);
231 grub_ieee1275_read (stdin_ihandle
, &c
, 1, &actual
);
233 /* On 9600 we have to wait up to 12 milliseconds. */
234 start
= grub_get_time_ms ();
235 while (actual
<= 0 && grub_get_time_ms () - start
< 12)
236 grub_ieee1275_read (stdin_ihandle
, &c
, 1, &actual
);
260 grub_ieee1275_read (stdin_ihandle
, &c
, 1, &actual
);
261 /* On 9600 we have to wait up to 12 milliseconds. */
262 start
= grub_get_time_ms ();
263 while (actual
<= 0 && grub_get_time_ms () - start
< 12)
264 grub_ieee1275_read (stdin_ihandle
, &c
, 1, &actual
);
269 /* Delete: Ctrl-d. */
286 grub_ofconsole_checkkey (void)
294 read
= grub_ofconsole_readkey (&key
);
306 grub_ofconsole_getkey (void)
316 while (! grub_ofconsole_readkey (&key
));
322 grub_ofconsole_getxy (void)
324 return ((grub_curr_x
- 1) << 8) | grub_curr_y
;
328 grub_ofconsole_dimensions (void)
330 grub_ieee1275_ihandle_t options
;
333 if (! grub_ieee1275_finddevice ("/options", &options
)
334 && options
!= (grub_ieee1275_ihandle_t
) -1)
336 if (! grub_ieee1275_get_property_length (options
, "screen-#columns",
338 && lval
>= 0 && lval
< 1024)
342 if (! grub_ieee1275_get_property (options
, "screen-#columns",
344 grub_ofconsole_width
= (grub_uint8_t
) grub_strtoul (val
, 0, 10);
346 if (! grub_ieee1275_get_property_length (options
, "screen-#rows", &lval
)
347 && lval
>= 0 && lval
< 1024)
350 if (! grub_ieee1275_get_property (options
, "screen-#rows",
352 grub_ofconsole_height
= (grub_uint8_t
) grub_strtoul (val
, 0, 10);
356 /* Use a small console by default. */
357 if (! grub_ofconsole_width
)
358 grub_ofconsole_width
= 80;
359 if (! grub_ofconsole_height
)
360 grub_ofconsole_height
= 24;
364 grub_ofconsole_getwh (void)
366 return (grub_ofconsole_width
<< 8) | grub_ofconsole_height
;
370 grub_ofconsole_gotoxy (grub_uint8_t x
, grub_uint8_t y
)
372 if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_ANSI
))
378 grub_snprintf (s
, sizeof (s
), "\e[%d;%dH", y
+ 1, x
+ 1);
379 grub_ofconsole_writeesc (s
);
383 if ((y
== grub_curr_y
) && (x
== grub_curr_x
- 1))
388 grub_ieee1275_write (stdout_ihandle
, &chr
, 1, 0);
397 grub_ofconsole_cls (void)
399 /* Clear the screen. Using serial console, screen(1) only recognizes the
400 * ANSI escape sequence. Using video console, Apple Open Firmware (version
401 * 3.1.1) only recognizes the literal ^L. So use both. */
402 grub_ofconsole_writeesc ("\f\e[2J");
403 grub_ofconsole_gotoxy (0, 0);
407 grub_ofconsole_setcursor (int on
)
409 /* Understood by the Open Firmware flavour in OLPC. */
411 grub_ieee1275_interpret ("cursor-on", 0);
413 grub_ieee1275_interpret ("cursor-off", 0);
417 grub_ofconsole_refresh (void)
419 /* Do nothing, the current console state is ok. */
423 grub_ofconsole_init_input (void)
427 if (grub_ieee1275_get_integer_property (grub_ieee1275_chosen
, "stdin", &stdin_ihandle
,
428 sizeof stdin_ihandle
, &actual
)
429 || actual
!= sizeof stdin_ihandle
)
430 return grub_error (GRUB_ERR_UNKNOWN_DEVICE
, "cannot find stdin");
436 grub_ofconsole_init_output (void)
440 /* The latest PowerMacs don't actually initialize the screen for us, so we
441 * use this trick to re-open the output device (but we avoid doing this on
442 * platforms where it's known to be broken). */
443 if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_BROKEN_OUTPUT
))
444 grub_ieee1275_interpret ("output-device output", 0);
446 if (grub_ieee1275_get_integer_property (grub_ieee1275_chosen
, "stdout", &stdout_ihandle
,
447 sizeof stdout_ihandle
, &actual
)
448 || actual
!= sizeof stdout_ihandle
)
449 return grub_error (GRUB_ERR_UNKNOWN_DEVICE
, "cannot find stdout");
451 /* Initialize colors. */
452 if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CANNOT_SET_COLORS
))
455 for (col
= 0; col
< ARRAY_SIZE (colors
); col
++)
456 grub_ieee1275_set_color (stdout_ihandle
, col
, colors
[col
].red
,
457 colors
[col
].green
, colors
[col
].blue
);
459 /* Set the right fg and bg colors. */
460 grub_ofconsole_setcolorstate (GRUB_TERM_COLOR_NORMAL
);
463 grub_ofconsole_dimensions ();
469 grub_ofconsole_fini (void)
476 static struct grub_term_input grub_ofconsole_term_input
=
479 .init
= grub_ofconsole_init_input
,
480 .fini
= grub_ofconsole_fini
,
481 .checkkey
= grub_ofconsole_checkkey
,
482 .getkey
= grub_ofconsole_getkey
,
485 static struct grub_term_output grub_ofconsole_term_output
=
488 .init
= grub_ofconsole_init_output
,
489 .fini
= grub_ofconsole_fini
,
490 .putchar
= grub_ofconsole_putchar
,
491 .getcharwidth
= grub_ofconsole_getcharwidth
,
492 .getxy
= grub_ofconsole_getxy
,
493 .getwh
= grub_ofconsole_getwh
,
494 .gotoxy
= grub_ofconsole_gotoxy
,
495 .cls
= grub_ofconsole_cls
,
496 .setcolorstate
= grub_ofconsole_setcolorstate
,
497 .setcolor
= grub_ofconsole_setcolor
,
498 .getcolor
= grub_ofconsole_getcolor
,
499 .setcursor
= grub_ofconsole_setcursor
,
500 .refresh
= grub_ofconsole_refresh
504 grub_console_init (void)
506 grub_term_register_input ("ofconsole", &grub_ofconsole_term_input
);
507 grub_term_register_output ("ofconsole", &grub_ofconsole_term_output
);
511 grub_console_fini (void)
513 grub_term_unregister_input (&grub_ofconsole_term_input
);
514 grub_term_unregister_output (&grub_ofconsole_term_output
);