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>
28 #include <grub/misc.h>
29 #include <grub/normal.h>
30 #include <grub/font.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. */
46 unsigned char fg_color
;
47 unsigned char bg_color
;
49 /* The width of this character minus one. */
52 /* The column index of this character. */
56 struct grub_virtual_screen
58 /* Dimensions of the virtual screen. */
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
;
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
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
=
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;
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
));
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
));
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
;
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
)
157 /* Check existence of vbe_mode environment variable. */
158 modevar
= grub_env_get ("vbe_mode");
164 value
= grub_strtoul (modevar
, 0, 0);
165 if (grub_errno
== GRUB_ERR_NONE
)
169 /* Store initial video mode. */
170 if (grub_vbe_get_video_mode (&old_mode
) != GRUB_ERR_NONE
)
173 /* Setup desired graphics mode. */
174 if (grub_vbe_set_video_mode (use_mode
, &mode_info
) != GRUB_ERR_NONE
)
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
;
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);
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
;
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
;
212 grub_virtual_screen_get_glyph (grub_uint32_t code
,
213 unsigned char bitmap
[32],
218 /* Map some unicode characters to the VGA font, if possible. */
221 case 0x2190: /* left arrow */
224 case 0x2191: /* up arrow */
227 case 0x2192: /* right arrow */
230 case 0x2193: /* down arrow */
233 case 0x2501: /* horizontal line */
236 case 0x2503: /* vertical line */
239 case 0x250F: /* upper-left corner */
242 case 0x2513: /* upper-right corner */
245 case 0x2517: /* lower-left corner */
248 case 0x251B: /* lower-right corner */
253 return grub_font_get_glyph_any (code
, bitmap
, width
);
257 /* TODO This is wrong for the new font module. Should it be fixed? */
260 vga_font
+ code
* virtual_screen
.char_height
,
261 virtual_screen
.char_height
);
267 grub_virtual_screen_invalidate_char (struct grub_colored_char
*p
)
273 struct grub_colored_char
*q
;
275 for (q
= p
+ 1; q
<= p
+ p
->width
; q
++)
289 struct grub_colored_char
*p
;
290 unsigned char bitmap
[32];
295 p
= (virtual_screen
.text_buffer
296 + virtual_screen
.cursor_x
297 + (virtual_screen
.cursor_y
* virtual_screen
.columns
));
301 if (! grub_virtual_screen_get_glyph (p
->code
, bitmap
, &width
))
303 grub_virtual_screen_invalidate_char (p
);
307 for (y
= 0, offset
= 0;
308 y
< virtual_screen
.char_height
;
314 (i
< width
* virtual_screen
.char_width
) && (offset
< 32);
319 if (bitmap
[offset
] & (1 << (8-i
)))
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
),
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;
347 for (x
= virtual_screen
.cursor_x
* virtual_screen
.char_width
;
348 x
< (virtual_screen
.cursor_x
+ 1) * virtual_screen
.char_width
;
351 grub_vbe_set_pixel_index(x
, y
, 10);
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
;
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
,
383 + bytes_per_scan_line
* virtual_screen
.char_height
,
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
);
396 grub_vesafb_putchar (grub_uint32_t c
)
402 if (c
== '\b' || c
== '\n' || c
== '\r')
404 /* Erase current cursor, if any. */
405 if (virtual_screen
.cursor_state
)
411 if (virtual_screen
.cursor_x
> 0)
412 virtual_screen
.cursor_x
--;
416 if (virtual_screen
.cursor_y
>= virtual_screen
.rows
- 1)
419 virtual_screen
.cursor_y
++;
423 virtual_screen
.cursor_x
= 0;
427 if (virtual_screen
.cursor_state
)
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
)
440 p
= (virtual_screen
.text_buffer
+
441 virtual_screen
.cursor_x
+
442 virtual_screen
.cursor_y
* virtual_screen
.columns
);
444 p
->fg_color
= virtual_screen
.fg_color
;
445 p
->bg_color
= virtual_screen
.bg_color
;
446 p
->width
= width
- 1;
453 for (i
= 1; i
< width
; i
++)
456 p
[i
].width
= width
- 1;
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)
471 virtual_screen
.cursor_y
++;
474 if (virtual_screen
.cursor_state
)
480 grub_vesafb_getcharwidth (grub_uint32_t c
)
484 if (! grub_virtual_screen_get_glyph (c
, 0, &width
))
491 grub_virtual_screen_getwh (void)
493 return (virtual_screen
.columns
<< 8) | virtual_screen
.rows
;
497 grub_virtual_screen_getxy (void)
499 return ((virtual_screen
.cursor_x
<< 8) | virtual_screen
.cursor_y
);
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
);
512 if (virtual_screen
.cursor_state
)
515 virtual_screen
.cursor_x
= x
;
516 virtual_screen
.cursor_y
= y
;
518 if (virtual_screen
.cursor_state
)
523 grub_virtual_screen_cls (void)
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;
540 grub_vesafb_cls (void)
542 grub_virtual_screen_cls ();
544 grub_memset (framebuffer
,
546 mode_info
.y_resolution
* bytes_per_scan_line
);
550 grub_virtual_screen_setcolorstate (grub_term_color_state 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
;
559 case GRUB_TERM_COLOR_HIGHLIGHT
:
560 virtual_screen
.fg_color
= DEFAULT_BG_COLOR
;
561 virtual_screen
.bg_color
= DEFAULT_FG_COLOR
;
569 grub_vesafb_setcursor (int on
)
571 if (virtual_screen
.cursor_state
!= on
)
573 if (virtual_screen
.cursor_state
)
578 virtual_screen
.cursor_state
= on
;
582 static struct grub_term_output grub_vesafb_term
=
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
,
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
);