remove all trailing whitespace
[grub2/phcoder/solaris.git] / term / i386 / pc / vesafb.c
blob52694ed104027149c332bca14fe836542a29ab72
1 /*
2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2005,2007,2009 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 // TODO: Deprecated and broken. Scheduled for removal as there is VBE driver in Video subsystem.
21 #include <grub/machine/memory.h>
22 #include <grub/machine/vga.h>
23 #include <grub/machine/vbe.h>
24 #include <grub/machine/console.h>
25 #include <grub/term.h>
26 #include <grub/types.h>
27 #include <grub/dl.h>
28 #include <grub/misc.h>
29 #include <grub/normal.h>
30 #include <grub/font.h>
31 #include <grub/mm.h>
32 #include <grub/env.h>
34 #define DEFAULT_CHAR_WIDTH 8
35 #define DEFAULT_CHAR_HEIGHT 16
37 #define DEFAULT_FG_COLOR 0xa
38 #define DEFAULT_BG_COLOR 0x0
40 struct grub_colored_char
42 /* An Unicode codepoint. */
43 grub_uint32_t code;
45 /* Color indexes. */
46 unsigned char fg_color;
47 unsigned char bg_color;
49 /* The width of this character minus one. */
50 unsigned char width;
52 /* The column index of this character. */
53 unsigned char index;
56 struct grub_virtual_screen
58 /* Dimensions of the virtual screen. */
59 grub_uint32_t width;
60 grub_uint32_t height;
62 /* Offset in the display. */
63 grub_uint32_t offset_x;
64 grub_uint32_t offset_y;
66 /* TTY Character sizes. */
67 grub_uint32_t char_width;
68 grub_uint32_t char_height;
70 /* Virtual screen TTY size. */
71 grub_uint32_t columns;
72 grub_uint32_t rows;
74 /* Current cursor details. */
75 grub_uint32_t cursor_x;
76 grub_uint32_t cursor_y;
77 grub_uint8_t cursor_state;
78 grub_uint8_t fg_color;
79 grub_uint8_t bg_color;
81 /* Text buffer for virtual screen. Contains (columns * rows) number
82 of entries. */
83 struct grub_colored_char *text_buffer;
86 /* Make sure text buffer is not marked as allocated. */
87 static struct grub_virtual_screen virtual_screen =
89 .text_buffer = 0
92 static unsigned char *vga_font = 0;
93 static grub_uint32_t old_mode = 0;
95 static struct grub_vbe_mode_info_block mode_info;
96 static grub_uint8_t *framebuffer = 0;
97 static grub_uint32_t bytes_per_scan_line = 0;
99 static void
100 grub_virtual_screen_free (void)
102 /* If virtual screen has been allocated, free it. */
103 if (virtual_screen.text_buffer != 0)
104 grub_free (virtual_screen.text_buffer);
106 /* Reset virtual screen data. */
107 grub_memset (&virtual_screen, 0, sizeof (virtual_screen));
110 static grub_err_t
111 grub_virtual_screen_setup (grub_uint32_t width,
112 grub_uint32_t height)
114 /* Free old virtual screen. */
115 grub_virtual_screen_free ();
117 /* Initialize with default data. */
118 virtual_screen.width = width;
119 virtual_screen.height = height;
120 virtual_screen.offset_x = 0;
121 virtual_screen.offset_y = 0;
122 virtual_screen.char_width = DEFAULT_CHAR_WIDTH;
123 virtual_screen.char_height = DEFAULT_CHAR_HEIGHT;
124 virtual_screen.cursor_x = 0;
125 virtual_screen.cursor_y = 0;
126 virtual_screen.cursor_state = 1;
127 virtual_screen.fg_color = DEFAULT_FG_COLOR;
128 virtual_screen.bg_color = DEFAULT_BG_COLOR;
130 /* Calculate size of text buffer. */
131 virtual_screen.columns = virtual_screen.width / virtual_screen.char_width;
132 virtual_screen.rows = virtual_screen.height / virtual_screen.char_height;
134 /* Allocate memory for text buffer. */
135 virtual_screen.text_buffer =
136 (struct grub_colored_char *) grub_malloc (virtual_screen.columns
137 * virtual_screen.rows
138 * sizeof (*virtual_screen.text_buffer));
140 return grub_errno;
143 static grub_err_t
144 grub_vesafb_mod_init (void)
146 grub_uint32_t use_mode = GRUB_VBE_DEFAULT_VIDEO_MODE;
147 struct grub_vbe_info_block controller_info;
148 char *modevar;
150 /* Use fonts from VGA bios. */
151 vga_font = grub_vga_get_font ();
153 /* Check if we have VESA BIOS installed. */
154 if (grub_vbe_probe (&controller_info) != GRUB_ERR_NONE)
155 return grub_errno;
157 /* Check existence of vbe_mode environment variable. */
158 modevar = grub_env_get ("vbe_mode");
160 if (modevar != 0)
162 unsigned long value;
164 value = grub_strtoul (modevar, 0, 0);
165 if (grub_errno == GRUB_ERR_NONE)
166 use_mode = value;
169 /* Store initial video mode. */
170 if (grub_vbe_get_video_mode (&old_mode) != GRUB_ERR_NONE)
171 return grub_errno;
173 /* Setup desired graphics mode. */
174 if (grub_vbe_set_video_mode (use_mode, &mode_info) != GRUB_ERR_NONE)
175 return grub_errno;
177 /* Determine framebuffer and bytes per scan line. */
178 framebuffer = (grub_uint8_t *) mode_info.phys_base_addr;
180 if (controller_info.version >= 0x300)
181 bytes_per_scan_line = mode_info.lin_bytes_per_scan_line;
182 else
183 bytes_per_scan_line = mode_info.bytes_per_scan_line;
185 /* Create virtual screen. */
186 if (grub_virtual_screen_setup (mode_info.x_resolution,
187 mode_info.y_resolution) != GRUB_ERR_NONE)
189 grub_vbe_set_video_mode (old_mode, 0);
190 return grub_errno;
193 /* Make sure frame buffer is black. */
194 grub_memset (framebuffer,
196 bytes_per_scan_line * mode_info.y_resolution);
198 return GRUB_ERR_NONE;
201 static grub_err_t
202 grub_vesafb_mod_fini (void)
204 grub_virtual_screen_free ();
206 grub_vbe_set_video_mode (old_mode, 0);
208 return GRUB_ERR_NONE;
211 static int
212 grub_virtual_screen_get_glyph (grub_uint32_t code,
213 unsigned char bitmap[32],
214 unsigned *width)
216 if (code > 0x7f)
218 /* Map some unicode characters to the VGA font, if possible. */
219 switch (code)
221 case 0x2190: /* left arrow */
222 code = 0x1b;
223 break;
224 case 0x2191: /* up arrow */
225 code = 0x18;
226 break;
227 case 0x2192: /* right arrow */
228 code = 0x1a;
229 break;
230 case 0x2193: /* down arrow */
231 code = 0x19;
232 break;
233 case 0x2501: /* horizontal line */
234 code = 0xc4;
235 break;
236 case 0x2503: /* vertical line */
237 code = 0xb3;
238 break;
239 case 0x250F: /* upper-left corner */
240 code = 0xda;
241 break;
242 case 0x2513: /* upper-right corner */
243 code = 0xbf;
244 break;
245 case 0x2517: /* lower-left corner */
246 code = 0xc0;
247 break;
248 case 0x251B: /* lower-right corner */
249 code = 0xd9;
250 break;
252 default:
253 return grub_font_get_glyph_any (code, bitmap, width);
257 /* TODO This is wrong for the new font module. Should it be fixed? */
258 if (bitmap)
259 grub_memcpy (bitmap,
260 vga_font + code * virtual_screen.char_height,
261 virtual_screen.char_height);
262 *width = 1;
263 return 1;
266 static void
267 grub_virtual_screen_invalidate_char (struct grub_colored_char *p)
269 p->code = 0xFFFF;
271 if (p->width)
273 struct grub_colored_char *q;
275 for (q = p + 1; q <= p + p->width; q++)
277 q->code = 0xFFFF;
278 q->width = 0;
279 q->index = 0;
283 p->width = 0;
286 static void
287 write_char (void)
289 struct grub_colored_char *p;
290 unsigned char bitmap[32];
291 unsigned width;
292 unsigned y;
293 unsigned offset;
295 p = (virtual_screen.text_buffer
296 + virtual_screen.cursor_x
297 + (virtual_screen.cursor_y * virtual_screen.columns));
299 p -= p->index;
301 if (! grub_virtual_screen_get_glyph (p->code, bitmap, &width))
303 grub_virtual_screen_invalidate_char (p);
304 width = 0;
307 for (y = 0, offset = 0;
308 y < virtual_screen.char_height;
309 y++, offset++)
311 unsigned i;
313 for (i = 0;
314 (i < width * virtual_screen.char_width) && (offset < 32);
315 i++)
317 unsigned char color;
319 if (bitmap[offset] & (1 << (8-i)))
321 color = p->fg_color;
323 else
325 color = p->bg_color;
328 grub_vbe_set_pixel_index(i + (virtual_screen.cursor_x
329 * virtual_screen.char_width),
330 y + (virtual_screen.cursor_y
331 * virtual_screen.char_height),
332 color);
337 static void
338 write_cursor (void)
340 grub_uint32_t x;
341 grub_uint32_t y;
343 for (y = ((virtual_screen.cursor_y + 1) * virtual_screen.char_height) - 3;
344 y < ((virtual_screen.cursor_y + 1) * virtual_screen.char_height) - 1;
345 y++)
347 for (x = virtual_screen.cursor_x * virtual_screen.char_width;
348 x < (virtual_screen.cursor_x + 1) * virtual_screen.char_width;
349 x++)
351 grub_vbe_set_pixel_index(x, y, 10);
356 static void
357 scroll_up (void)
359 grub_uint32_t i;
361 /* Scroll text buffer with one line to up. */
362 grub_memmove (virtual_screen.text_buffer,
363 virtual_screen.text_buffer + virtual_screen.columns,
364 sizeof (*virtual_screen.text_buffer)
365 * virtual_screen.columns
366 * (virtual_screen.rows - 1));
368 /* Clear last line in text buffer. */
369 for (i = virtual_screen.columns * (virtual_screen.rows - 1);
370 i < virtual_screen.columns * virtual_screen.rows;
371 i++)
373 virtual_screen.text_buffer[i].code = ' ';
374 virtual_screen.text_buffer[i].fg_color = 0;
375 virtual_screen.text_buffer[i].bg_color = 0;
376 virtual_screen.text_buffer[i].width = 0;
377 virtual_screen.text_buffer[i].index = 0;
380 /* Scroll framebuffer with one line to up. */
381 grub_memmove (framebuffer,
382 framebuffer
383 + bytes_per_scan_line * virtual_screen.char_height,
384 bytes_per_scan_line
385 * (mode_info.y_resolution - virtual_screen.char_height));
387 /* Clear last line in framebuffer. */
388 grub_memset (framebuffer
389 + (bytes_per_scan_line
390 * (mode_info.y_resolution - virtual_screen.char_height)),
392 bytes_per_scan_line * virtual_screen.char_height);
395 static void
396 grub_vesafb_putchar (grub_uint32_t c)
398 if (c == '\a')
399 /* FIXME */
400 return;
402 if (c == '\b' || c == '\n' || c == '\r')
404 /* Erase current cursor, if any. */
405 if (virtual_screen.cursor_state)
406 write_char ();
408 switch (c)
410 case '\b':
411 if (virtual_screen.cursor_x > 0)
412 virtual_screen.cursor_x--;
413 break;
415 case '\n':
416 if (virtual_screen.cursor_y >= virtual_screen.rows - 1)
417 scroll_up ();
418 else
419 virtual_screen.cursor_y++;
420 break;
422 case '\r':
423 virtual_screen.cursor_x = 0;
424 break;
427 if (virtual_screen.cursor_state)
428 write_cursor ();
430 else
432 unsigned width;
433 struct grub_colored_char *p;
435 grub_virtual_screen_get_glyph (c, 0, &width);
437 if (virtual_screen.cursor_x + width > virtual_screen.columns)
438 grub_putchar ('\n');
440 p = (virtual_screen.text_buffer +
441 virtual_screen.cursor_x +
442 virtual_screen.cursor_y * virtual_screen.columns);
443 p->code = c;
444 p->fg_color = virtual_screen.fg_color;
445 p->bg_color = virtual_screen.bg_color;
446 p->width = width - 1;
447 p->index = 0;
449 if (width > 1)
451 unsigned i;
453 for (i = 1; i < width; i++)
455 p[i].code = ' ';
456 p[i].width = width - 1;
457 p[i].index = i;
461 write_char ();
463 virtual_screen.cursor_x += width;
464 if (virtual_screen.cursor_x >= virtual_screen.columns)
466 virtual_screen.cursor_x = 0;
468 if (virtual_screen.cursor_y >= virtual_screen.rows - 1)
469 scroll_up ();
470 else
471 virtual_screen.cursor_y++;
474 if (virtual_screen.cursor_state)
475 write_cursor ();
479 static grub_ssize_t
480 grub_vesafb_getcharwidth (grub_uint32_t c)
482 unsigned width;
484 if (! grub_virtual_screen_get_glyph (c, 0, &width))
485 return 0;
487 return width;
490 static grub_uint16_t
491 grub_virtual_screen_getwh (void)
493 return (virtual_screen.columns << 8) | virtual_screen.rows;
496 static grub_uint16_t
497 grub_virtual_screen_getxy (void)
499 return ((virtual_screen.cursor_x << 8) | virtual_screen.cursor_y);
502 static void
503 grub_vesafb_gotoxy (grub_uint8_t x, grub_uint8_t y)
505 if (x >= virtual_screen.columns || y >= virtual_screen.rows)
507 grub_error (GRUB_ERR_OUT_OF_RANGE, "invalid point (%u,%u)",
508 (unsigned) x, (unsigned) y);
509 return;
512 if (virtual_screen.cursor_state)
513 write_char ();
515 virtual_screen.cursor_x = x;
516 virtual_screen.cursor_y = y;
518 if (virtual_screen.cursor_state)
519 write_cursor ();
522 static void
523 grub_virtual_screen_cls (void)
525 grub_uint32_t i;
527 for (i = 0; i < virtual_screen.columns * virtual_screen.rows; i++)
529 virtual_screen.text_buffer[i].code = ' ';
530 virtual_screen.text_buffer[i].fg_color = 0;
531 virtual_screen.text_buffer[i].bg_color = 0;
532 virtual_screen.text_buffer[i].width = 0;
533 virtual_screen.text_buffer[i].index = 0;
536 virtual_screen.cursor_x = virtual_screen.cursor_y = 0;
539 static void
540 grub_vesafb_cls (void)
542 grub_virtual_screen_cls ();
544 grub_memset (framebuffer,
546 mode_info.y_resolution * bytes_per_scan_line);
549 static void
550 grub_virtual_screen_setcolorstate (grub_term_color_state state)
552 switch (state)
554 case GRUB_TERM_COLOR_STANDARD:
555 case GRUB_TERM_COLOR_NORMAL:
556 virtual_screen.fg_color = DEFAULT_FG_COLOR;
557 virtual_screen.bg_color = DEFAULT_BG_COLOR;
558 break;
559 case GRUB_TERM_COLOR_HIGHLIGHT:
560 virtual_screen.fg_color = DEFAULT_BG_COLOR;
561 virtual_screen.bg_color = DEFAULT_FG_COLOR;
562 break;
563 default:
564 break;
568 static void
569 grub_vesafb_setcursor (int on)
571 if (virtual_screen.cursor_state != on)
573 if (virtual_screen.cursor_state)
574 write_char ();
575 else
576 write_cursor ();
578 virtual_screen.cursor_state = on;
582 static struct grub_term_output grub_vesafb_term =
584 .name = "vesafb",
585 .init = grub_vesafb_mod_init,
586 .fini = grub_vesafb_mod_fini,
587 .putchar = grub_vesafb_putchar,
588 .getcharwidth = grub_vesafb_getcharwidth,
589 .getwh = grub_virtual_screen_getwh,
590 .getxy = grub_virtual_screen_getxy,
591 .gotoxy = grub_vesafb_gotoxy,
592 .cls = grub_vesafb_cls,
593 .setcolorstate = grub_virtual_screen_setcolorstate,
594 .setcursor = grub_vesafb_setcursor,
595 .flags = 0,
598 GRUB_MOD_INIT(vesafb)
600 grub_term_register_output ("vesafb", &grub_vesafb_term);
603 GRUB_MOD_FINI(vesafb)
605 grub_term_unregister_output (&grub_vesafb_term);