2
* GRUB -- GRand Unified Bootloader
3
* Copyright (C) 2005 Free Software Foundation, Inc.
5
* This program 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 2 of the License, or
8
* (at your option) any later version.
10
* This program 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 this program; if not, write to the Free Software
17
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
#include <grub/machine/memory.h>
21
#include <grub/machine/vga.h>
22
#include <grub/machine/vbe.h>
23
#include <grub/machine/console.h>
24
#include <grub/term.h>
25
#include <grub/types.h>
27
#include <grub/misc.h>
28
#include <grub/normal.h>
29
#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 virual 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 virual screen. Contains (columns * rows) number
83
struct grub_colored_char *text_buffer;
86
/* Make seure text buffer is not marked as allocated. */
87
static struct grub_virtual_screen virtual_screen =
92
static grub_dl_t my_mod;
93
static unsigned char *vga_font = 0;
94
static grub_uint32_t old_mode = 0;
96
static struct grub_vbe_mode_info_block mode_info;
97
static grub_uint8_t *framebuffer = 0;
98
static grub_uint32_t bytes_per_scan_line = 0;
101
grub_virtual_screen_free (void)
103
/* If virtual screen has been allocated, free it. */
104
if (virtual_screen.text_buffer != 0)
105
grub_free (virtual_screen.text_buffer);
107
/* Reset virtual screen data. */
108
grub_memset (&virtual_screen, 0, sizeof (virtual_screen));
112
grub_virtual_screen_setup (grub_uint32_t width,
113
grub_uint32_t height)
115
/* Free old virtual screen. */
116
grub_virtual_screen_free ();
118
/* Initialize with default data. */
119
virtual_screen.width = width;
120
virtual_screen.height = height;
121
virtual_screen.offset_x = 0;
122
virtual_screen.offset_y = 0;
123
virtual_screen.char_width = DEFAULT_CHAR_WIDTH;
124
virtual_screen.char_height = DEFAULT_CHAR_HEIGHT;
125
virtual_screen.cursor_x = 0;
126
virtual_screen.cursor_y = 0;
127
virtual_screen.cursor_state = 1;
128
virtual_screen.fg_color = DEFAULT_FG_COLOR;
129
virtual_screen.bg_color = DEFAULT_BG_COLOR;
131
/* Calculate size of text buffer. */
132
virtual_screen.columns = virtual_screen.width / virtual_screen.char_width;
133
virtual_screen.rows = virtual_screen.height / virtual_screen.char_height;
135
/* Allocate memory for text buffer. */
136
virtual_screen.text_buffer =
137
(struct grub_colored_char *) grub_malloc (virtual_screen.columns
138
* virtual_screen.rows
139
* sizeof (*virtual_screen.text_buffer));
145
grub_vesafb_mod_init (void)
147
grub_uint32_t use_mode = GRUB_VBE_DEFAULT_VIDEO_MODE;
148
struct grub_vbe_info_block controller_info;
151
/* Use fonts from VGA bios. */
152
vga_font = grub_vga_get_font ();
154
/* Check if we have VESA BIOS installed. */
155
if (grub_vbe_probe (&controller_info) != GRUB_ERR_NONE)
158
/* Check existence of vbe_mode environment variable. */
159
modevar = grub_env_get ("vbe_mode");
165
value = grub_strtoul (modevar, 0, 0);
166
if (grub_errno == GRUB_ERR_NONE)
170
/* Store initial video mode. */
171
if (grub_vbe_get_video_mode (&old_mode) != GRUB_ERR_NONE)
174
/* Setup desired graphics mode. */
175
if (grub_vbe_set_video_mode (use_mode, &mode_info) != GRUB_ERR_NONE)
178
/* Determine framebuffer and bytes per scan line. */
179
framebuffer = (grub_uint8_t *) mode_info.phys_base_addr;
181
if (controller_info.version >= 0x300)
182
bytes_per_scan_line = mode_info.lin_bytes_per_scan_line;
184
bytes_per_scan_line = mode_info.bytes_per_scan_line;
186
/* Create virtual screen. */
187
if (grub_virtual_screen_setup (mode_info.x_resolution,
188
mode_info.y_resolution) != GRUB_ERR_NONE)
190
grub_vbe_set_video_mode (old_mode, 0);
194
/* Make sure frame buffer is black. */
195
grub_memset (framebuffer,
197
bytes_per_scan_line * mode_info.y_resolution);
199
return GRUB_ERR_NONE;
203
grub_vesafb_mod_fini (void)
205
grub_virtual_screen_free ();
207
grub_vbe_set_video_mode (old_mode, 0);
209
return GRUB_ERR_NONE;
213
grub_virtual_screen_get_glyph (grub_uint32_t code,
214
unsigned char bitmap[32],
219
/* Map some unicode characters to the VGA font, if possible. */
222
case 0x2190: /* left arrow */
225
case 0x2191: /* up arrow */
228
case 0x2192: /* right arrow */
231
case 0x2193: /* down arrow */
234
case 0x2501: /* horizontal line */
237
case 0x2503: /* vertical line */
240
case 0x250F: /* upper-left corner */
243
case 0x2513: /* upper-right corner */
246
case 0x2517: /* lower-left corner */
249
case 0x251B: /* lower-right corner */
254
return grub_font_get_glyph (code, bitmap, width);
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 frambuffer 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_virtual_screen_setcolor (grub_uint8_t normal_color __attribute__ ((unused)),
570
grub_uint8_t highlight_color __attribute__ ((unused)))
576
grub_vesafb_setcursor (int on)
578
if (virtual_screen.cursor_state != on)
580
if (virtual_screen.cursor_state)
585
virtual_screen.cursor_state = on;
589
static struct grub_term grub_vesafb_term =
592
.init = grub_vesafb_mod_init,
593
.fini = grub_vesafb_mod_fini,
594
.putchar = grub_vesafb_putchar,
595
.getcharwidth = grub_vesafb_getcharwidth,
596
.checkkey = grub_console_checkkey,
597
.getkey = grub_console_getkey,
598
.getwh = grub_virtual_screen_getwh,
599
.getxy = grub_virtual_screen_getxy,
600
.gotoxy = grub_vesafb_gotoxy,
601
.cls = grub_vesafb_cls,
602
.setcolorstate = grub_virtual_screen_setcolorstate,
603
.setcolor = grub_virtual_screen_setcolor,
604
.setcursor = grub_vesafb_setcursor,
609
GRUB_MOD_INIT(vesafb)
612
grub_term_register (&grub_vesafb_term);
615
GRUB_MOD_FINI(vesafb)
617
grub_term_unregister (&grub_vesafb_term);