GRUB-1.98 changes
[grub2/jjazz.git] / term / ieee1275 / ofconsole.c
blobc0f895a15d130dfde3e9061f93e4fa0bea312040
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.
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>
23 #include <grub/mm.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;
40 struct color
42 int red;
43 int green;
44 int blue;
47 static struct color colors[] =
49 // {R, G, B}
50 {0x00, 0x00, 0x00},
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. */
64 static void
65 grub_ofconsole_writeesc (const char *str)
67 if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_ANSI))
68 return;
70 while (*str)
72 char chr = *(str++);
73 grub_ieee1275_write (stdout_ihandle, &chr, 1, 0);
78 static void
79 grub_ofconsole_putchar (grub_uint32_t c)
81 char chr;
83 if (c > 0x7F)
85 /* Better than nothing. */
86 switch (c)
88 case GRUB_TERM_DISP_LEFT:
89 c = '<';
90 break;
92 case GRUB_TERM_DISP_UP:
93 c = '^';
94 break;
96 case GRUB_TERM_DISP_RIGHT:
97 c = '>';
98 break;
100 case GRUB_TERM_DISP_DOWN:
101 c = 'v';
102 break;
104 case GRUB_TERM_DISP_HLINE:
105 c = '-';
106 break;
108 case GRUB_TERM_DISP_VLINE:
109 c = '|';
110 break;
112 case GRUB_TERM_DISP_UL:
113 case GRUB_TERM_DISP_UR:
114 case GRUB_TERM_DISP_LL:
115 case GRUB_TERM_DISP_LR:
116 c = '+';
117 break;
119 default:
120 c = '?';
121 break;
125 chr = c;
127 if (c == '\n')
129 grub_curr_y++;
130 grub_curr_x = 0;
132 else if (c == '\r')
134 grub_curr_x = 0;
136 else
138 grub_curr_x++;
139 if (grub_curr_x >= grub_ofconsole_width)
141 grub_ofconsole_putchar ('\n');
142 grub_ofconsole_putchar ('\r');
143 grub_curr_x++;
146 grub_ieee1275_write (stdout_ihandle, &chr, 1, 0);
149 static grub_ssize_t
150 grub_ofconsole_getcharwidth (grub_uint32_t c __attribute__((unused)))
152 return 1;
155 static void
156 grub_ofconsole_setcolorstate (grub_term_color_state state)
158 char setcol[256];
159 int fg;
160 int bg;
162 switch (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;
168 break;
169 case GRUB_TERM_COLOR_HIGHLIGHT:
170 fg = grub_ofconsole_highlight_color & 0x0f;
171 bg = grub_ofconsole_highlight_color >> 4;
172 break;
173 default:
174 return;
177 grub_snprintf (setcol, sizeof (setcol), "\e[3%dm\e[4%dm", fg, bg);
178 grub_ofconsole_writeesc (setcol);
181 static void
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;
190 static void
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;
197 static int
198 grub_ofconsole_readkey (int *key)
200 char c;
201 grub_ssize_t actual = 0;
203 grub_ieee1275_read (stdin_ihandle, &c, 1, &actual);
205 if (actual > 0)
206 switch(c)
208 case 0x7f:
209 /* Backspace: Ctrl-h. */
210 c = '\b';
211 break;
212 case '\e':
214 grub_uint64_t start;
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);
222 if (actual <= 0)
224 *key = '\e';
225 return 1;
228 if (c != '[')
229 return 0;
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);
237 if (actual <= 0)
238 return 0;
240 switch (c)
242 case 'A':
243 /* Up: Ctrl-p. */
244 c = GRUB_TERM_UP;
245 break;
246 case 'B':
247 /* Down: Ctrl-n. */
248 c = GRUB_TERM_DOWN;
249 break;
250 case 'C':
251 /* Right: Ctrl-f. */
252 c = GRUB_TERM_RIGHT;
253 break;
254 case 'D':
255 /* Left: Ctrl-b. */
256 c = GRUB_TERM_LEFT;
257 break;
258 case '3':
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);
266 if (actual <= 0)
267 return 0;
269 /* Delete: Ctrl-d. */
270 if (c == '~')
271 c = GRUB_TERM_DC;
272 else
273 return 0;
274 break;
276 break;
281 *key = c;
282 return actual > 0;
285 static int
286 grub_ofconsole_checkkey (void)
288 int key;
289 int read;
291 if (grub_buflen)
292 return 1;
294 read = grub_ofconsole_readkey (&key);
295 if (read)
297 grub_keybuf = key;
298 grub_buflen = 1;
299 return 1;
302 return -1;
305 static int
306 grub_ofconsole_getkey (void)
308 int key;
310 if (grub_buflen)
312 grub_buflen =0;
313 return grub_keybuf;
316 while (! grub_ofconsole_readkey (&key));
318 return key;
321 static grub_uint16_t
322 grub_ofconsole_getxy (void)
324 return ((grub_curr_x - 1) << 8) | grub_curr_y;
327 static void
328 grub_ofconsole_dimensions (void)
330 grub_ieee1275_ihandle_t options;
331 grub_ssize_t lval;
333 if (! grub_ieee1275_finddevice ("/options", &options)
334 && options != (grub_ieee1275_ihandle_t) -1)
336 if (! grub_ieee1275_get_property_length (options, "screen-#columns",
337 &lval)
338 && lval >= 0 && lval < 1024)
340 char val[lval];
342 if (! grub_ieee1275_get_property (options, "screen-#columns",
343 val, lval, 0))
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)
349 char val[lval];
350 if (! grub_ieee1275_get_property (options, "screen-#rows",
351 val, lval, 0))
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;
363 static grub_uint16_t
364 grub_ofconsole_getwh (void)
366 return (grub_ofconsole_width << 8) | grub_ofconsole_height;
369 static void
370 grub_ofconsole_gotoxy (grub_uint8_t x, grub_uint8_t y)
372 if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_ANSI))
374 char s[256];
375 grub_curr_x = x;
376 grub_curr_y = y;
378 grub_snprintf (s, sizeof (s), "\e[%d;%dH", y + 1, x + 1);
379 grub_ofconsole_writeesc (s);
381 else
383 if ((y == grub_curr_y) && (x == grub_curr_x - 1))
385 char chr;
387 chr = '\b';
388 grub_ieee1275_write (stdout_ihandle, &chr, 1, 0);
391 grub_curr_x = x;
392 grub_curr_y = y;
396 static void
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);
406 static void
407 grub_ofconsole_setcursor (int on)
409 /* Understood by the Open Firmware flavour in OLPC. */
410 if (on)
411 grub_ieee1275_interpret ("cursor-on", 0);
412 else
413 grub_ieee1275_interpret ("cursor-off", 0);
416 static void
417 grub_ofconsole_refresh (void)
419 /* Do nothing, the current console state is ok. */
422 static grub_err_t
423 grub_ofconsole_init_input (void)
425 grub_ssize_t actual;
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");
432 return 0;
435 static grub_err_t
436 grub_ofconsole_init_output (void)
438 grub_ssize_t actual;
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))
454 unsigned col;
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 ();
465 return 0;
468 static grub_err_t
469 grub_ofconsole_fini (void)
471 return 0;
476 static struct grub_term_input grub_ofconsole_term_input =
478 .name = "ofconsole",
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 =
487 .name = "ofconsole",
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
503 void
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);
510 void
511 grub_console_fini (void)
513 grub_term_unregister_input (&grub_ofconsole_term_input);
514 grub_term_unregister_output (&grub_ofconsole_term_output);