+++ /dev/null
-/*
- * GRUB -- GRand Unified Bootloader
- * Copyright (C) 2005,2007,2009 Free Software Foundation, Inc.
- *
- * GRUB is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * GRUB is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
- */
-
-// TODO: Deprecated and broken. Scheduled for removal as there is VBE driver in Video subsystem.
-
-#include <grub/machine/memory.h>
-#include <grub/machine/vga.h>
-#include <grub/machine/vbe.h>
-#include <grub/machine/console.h>
-#include <grub/term.h>
-#include <grub/types.h>
-#include <grub/dl.h>
-#include <grub/misc.h>
-#include <grub/normal.h>
-#include <grub/font.h>
-#include <grub/mm.h>
-#include <grub/env.h>
-
-#define DEFAULT_CHAR_WIDTH 8
-#define DEFAULT_CHAR_HEIGHT 16
-
-#define DEFAULT_FG_COLOR 0xa
-#define DEFAULT_BG_COLOR 0x0
-
-struct grub_colored_char
-{
- /* An Unicode codepoint. */
- grub_uint32_t code;
-
- /* Color indexes. */
- unsigned char fg_color;
- unsigned char bg_color;
-
- /* The width of this character minus one. */
- unsigned char width;
-
- /* The column index of this character. */
- unsigned char index;
-};
-
-struct grub_virtual_screen
-{
- /* Dimensions of the virtual screen. */
- grub_uint32_t width;
- grub_uint32_t height;
-
- /* Offset in the display. */
- grub_uint32_t offset_x;
- grub_uint32_t offset_y;
-
- /* TTY Character sizes. */
- grub_uint32_t char_width;
- grub_uint32_t char_height;
-
- /* Virtual screen TTY size. */
- grub_uint32_t columns;
- grub_uint32_t rows;
-
- /* Current cursor details. */
- grub_uint32_t cursor_x;
- grub_uint32_t cursor_y;
- grub_uint8_t cursor_state;
- grub_uint8_t fg_color;
- grub_uint8_t bg_color;
-
- /* Text buffer for virtual screen. Contains (columns * rows) number
- of entries. */
- struct grub_colored_char *text_buffer;
-};
-
-/* Make sure text buffer is not marked as allocated. */
-static struct grub_virtual_screen virtual_screen =
- {
- .text_buffer = 0
- };
-
-static unsigned char *vga_font = 0;
-static grub_uint32_t old_mode = 0;
-
-static struct grub_vbe_mode_info_block mode_info;
-static grub_uint8_t *framebuffer = 0;
-static grub_uint32_t bytes_per_scan_line = 0;
-
-static void
-grub_virtual_screen_free (void)
-{
- /* If virtual screen has been allocated, free it. */
- if (virtual_screen.text_buffer != 0)
- grub_free (virtual_screen.text_buffer);
-
- /* Reset virtual screen data. */
- grub_memset (&virtual_screen, 0, sizeof (virtual_screen));
-}
-
-static grub_err_t
-grub_virtual_screen_setup (grub_uint32_t width,
- grub_uint32_t height)
-{
- /* Free old virtual screen. */
- grub_virtual_screen_free ();
-
- /* Initialize with default data. */
- virtual_screen.width = width;
- virtual_screen.height = height;
- virtual_screen.offset_x = 0;
- virtual_screen.offset_y = 0;
- virtual_screen.char_width = DEFAULT_CHAR_WIDTH;
- virtual_screen.char_height = DEFAULT_CHAR_HEIGHT;
- virtual_screen.cursor_x = 0;
- virtual_screen.cursor_y = 0;
- virtual_screen.cursor_state = 1;
- virtual_screen.fg_color = DEFAULT_FG_COLOR;
- virtual_screen.bg_color = DEFAULT_BG_COLOR;
-
- /* Calculate size of text buffer. */
- virtual_screen.columns = virtual_screen.width / virtual_screen.char_width;
- virtual_screen.rows = virtual_screen.height / virtual_screen.char_height;
-
- /* Allocate memory for text buffer. */
- virtual_screen.text_buffer =
- (struct grub_colored_char *) grub_malloc (virtual_screen.columns
- * virtual_screen.rows
- * sizeof (*virtual_screen.text_buffer));
-
- return grub_errno;
-}
-
-static grub_err_t
-grub_vesafb_mod_init (void)
-{
- grub_uint32_t use_mode = GRUB_VBE_DEFAULT_VIDEO_MODE;
- struct grub_vbe_info_block controller_info;
- char *modevar;
-
- /* Use fonts from VGA bios. */
- vga_font = grub_vga_get_font ();
-
- /* Check if we have VESA BIOS installed. */
- if (grub_vbe_probe (&controller_info) != GRUB_ERR_NONE)
- return grub_errno;
-
- /* Check existence of vbe_mode environment variable. */
- modevar = grub_env_get ("vbe_mode");
-
- if (modevar != 0)
- {
- unsigned long value;
-
- value = grub_strtoul (modevar, 0, 0);
- if (grub_errno == GRUB_ERR_NONE)
- use_mode = value;
- }
-
- /* Store initial video mode. */
- if (grub_vbe_get_video_mode (&old_mode) != GRUB_ERR_NONE)
- return grub_errno;
-
- /* Setup desired graphics mode. */
- if (grub_vbe_set_video_mode (use_mode, &mode_info) != GRUB_ERR_NONE)
- return grub_errno;
-
- /* Determine framebuffer and bytes per scan line. */
- framebuffer = (grub_uint8_t *) mode_info.phys_base_addr;
-
- if (controller_info.version >= 0x300)
- bytes_per_scan_line = mode_info.lin_bytes_per_scan_line;
- else
- bytes_per_scan_line = mode_info.bytes_per_scan_line;
-
- /* Create virtual screen. */
- if (grub_virtual_screen_setup (mode_info.x_resolution,
- mode_info.y_resolution) != GRUB_ERR_NONE)
- {
- grub_vbe_set_video_mode (old_mode, 0);
- return grub_errno;
- }
-
- /* Make sure frame buffer is black. */
- grub_memset (framebuffer,
- 0,
- bytes_per_scan_line * mode_info.y_resolution);
-
- return GRUB_ERR_NONE;
-}
-
-static grub_err_t
-grub_vesafb_mod_fini (void)
-{
- grub_virtual_screen_free ();
-
- grub_vbe_set_video_mode (old_mode, 0);
-
- return GRUB_ERR_NONE;
-}
-
-static int
-grub_virtual_screen_get_glyph (grub_uint32_t code,
- unsigned char bitmap[32],
- unsigned *width)
-{
- if (code > 0x7f)
- {
- /* Map some unicode characters to the VGA font, if possible. */
- switch (code)
- {
- case 0x2190: /* left arrow */
- code = 0x1b;
- break;
- case 0x2191: /* up arrow */
- code = 0x18;
- break;
- case 0x2192: /* right arrow */
- code = 0x1a;
- break;
- case 0x2193: /* down arrow */
- code = 0x19;
- break;
- case 0x2501: /* horizontal line */
- code = 0xc4;
- break;
- case 0x2503: /* vertical line */
- code = 0xb3;
- break;
- case 0x250F: /* upper-left corner */
- code = 0xda;
- break;
- case 0x2513: /* upper-right corner */
- code = 0xbf;
- break;
- case 0x2517: /* lower-left corner */
- code = 0xc0;
- break;
- case 0x251B: /* lower-right corner */
- code = 0xd9;
- break;
-
- default:
- return grub_font_get_glyph_any (code, bitmap, width);
- }
- }
-
- /* TODO This is wrong for the new font module. Should it be fixed? */
- if (bitmap)
- grub_memcpy (bitmap,
- vga_font + code * virtual_screen.char_height,
- virtual_screen.char_height);
- *width = 1;
- return 1;
-}
-
-static void
-grub_virtual_screen_invalidate_char (struct grub_colored_char *p)
-{
- p->code = 0xFFFF;
-
- if (p->width)
- {
- struct grub_colored_char *q;
-
- for (q = p + 1; q <= p + p->width; q++)
- {
- q->code = 0xFFFF;
- q->width = 0;
- q->index = 0;
- }
- }
-
- p->width = 0;
-}
-
-static void
-write_char (void)
-{
- struct grub_colored_char *p;
- unsigned char bitmap[32];
- unsigned width;
- unsigned y;
- unsigned offset;
-
- p = (virtual_screen.text_buffer
- + virtual_screen.cursor_x
- + (virtual_screen.cursor_y * virtual_screen.columns));
-
- p -= p->index;
-
- if (! grub_virtual_screen_get_glyph (p->code, bitmap, &width))
- {
- grub_virtual_screen_invalidate_char (p);
- width = 0;
- }
-
- for (y = 0, offset = 0;
- y < virtual_screen.char_height;
- y++, offset++)
- {
- unsigned i;
-
- for (i = 0;
- (i < width * virtual_screen.char_width) && (offset < 32);
- i++)
- {
- unsigned char color;
-
- if (bitmap[offset] & (1 << (8-i)))
- {
- color = p->fg_color;
- }
- else
- {
- color = p->bg_color;
- }
-
- grub_vbe_set_pixel_index(i + (virtual_screen.cursor_x
- * virtual_screen.char_width),
- y + (virtual_screen.cursor_y
- * virtual_screen.char_height),
- color);
- }
- }
-}
-
-static void
-write_cursor (void)
-{
- grub_uint32_t x;
- grub_uint32_t y;
-
- for (y = ((virtual_screen.cursor_y + 1) * virtual_screen.char_height) - 3;
- y < ((virtual_screen.cursor_y + 1) * virtual_screen.char_height) - 1;
- y++)
- {
- for (x = virtual_screen.cursor_x * virtual_screen.char_width;
- x < (virtual_screen.cursor_x + 1) * virtual_screen.char_width;
- x++)
- {
- grub_vbe_set_pixel_index(x, y, 10);
- }
- }
-}
-
-static void
-scroll_up (void)
-{
- grub_uint32_t i;
-
- /* Scroll text buffer with one line to up. */
- grub_memmove (virtual_screen.text_buffer,
- virtual_screen.text_buffer + virtual_screen.columns,
- sizeof (*virtual_screen.text_buffer)
- * virtual_screen.columns
- * (virtual_screen.rows - 1));
-
- /* Clear last line in text buffer. */
- for (i = virtual_screen.columns * (virtual_screen.rows - 1);
- i < virtual_screen.columns * virtual_screen.rows;
- i++)
- {
- virtual_screen.text_buffer[i].code = ' ';
- virtual_screen.text_buffer[i].fg_color = 0;
- virtual_screen.text_buffer[i].bg_color = 0;
- virtual_screen.text_buffer[i].width = 0;
- virtual_screen.text_buffer[i].index = 0;
- }
-
- /* Scroll framebuffer with one line to up. */
- grub_memmove (framebuffer,
- framebuffer
- + bytes_per_scan_line * virtual_screen.char_height,
- bytes_per_scan_line
- * (mode_info.y_resolution - virtual_screen.char_height));
-
- /* Clear last line in framebuffer. */
- grub_memset (framebuffer
- + (bytes_per_scan_line
- * (mode_info.y_resolution - virtual_screen.char_height)),
- 0,
- bytes_per_scan_line * virtual_screen.char_height);
-}
-
-static void
-grub_vesafb_putchar (grub_uint32_t c)
-{
- if (c == '\a')
- /* FIXME */
- return;
-
- if (c == '\b' || c == '\n' || c == '\r')
- {
- /* Erase current cursor, if any. */
- if (virtual_screen.cursor_state)
- write_char ();
-
- switch (c)
- {
- case '\b':
- if (virtual_screen.cursor_x > 0)
- virtual_screen.cursor_x--;
- break;
-
- case '\n':
- if (virtual_screen.cursor_y >= virtual_screen.rows - 1)
- scroll_up ();
- else
- virtual_screen.cursor_y++;
- break;
-
- case '\r':
- virtual_screen.cursor_x = 0;
- break;
- }
-
- if (virtual_screen.cursor_state)
- write_cursor ();
- }
- else
- {
- unsigned width;
- struct grub_colored_char *p;
-
- grub_virtual_screen_get_glyph (c, 0, &width);
-
- if (virtual_screen.cursor_x + width > virtual_screen.columns)
- grub_putchar ('\n');
-
- p = (virtual_screen.text_buffer +
- virtual_screen.cursor_x +
- virtual_screen.cursor_y * virtual_screen.columns);
- p->code = c;
- p->fg_color = virtual_screen.fg_color;
- p->bg_color = virtual_screen.bg_color;
- p->width = width - 1;
- p->index = 0;
-
- if (width > 1)
- {
- unsigned i;
-
- for (i = 1; i < width; i++)
- {
- p[i].code = ' ';
- p[i].width = width - 1;
- p[i].index = i;
- }
- }
-
- write_char ();
-
- virtual_screen.cursor_x += width;
- if (virtual_screen.cursor_x >= virtual_screen.columns)
- {
- virtual_screen.cursor_x = 0;
-
- if (virtual_screen.cursor_y >= virtual_screen.rows - 1)
- scroll_up ();
- else
- virtual_screen.cursor_y++;
- }
-
- if (virtual_screen.cursor_state)
- write_cursor ();
- }
-}
-
-static grub_ssize_t
-grub_vesafb_getcharwidth (grub_uint32_t c)
-{
- unsigned width;
-
- if (! grub_virtual_screen_get_glyph (c, 0, &width))
- return 0;
-
- return width;
-}
-
-static grub_uint16_t
-grub_virtual_screen_getwh (void)
-{
- return (virtual_screen.columns << 8) | virtual_screen.rows;
-}
-
-static grub_uint16_t
-grub_virtual_screen_getxy (void)
-{
- return ((virtual_screen.cursor_x << 8) | virtual_screen.cursor_y);
-}
-
-static void
-grub_vesafb_gotoxy (grub_uint8_t x, grub_uint8_t y)
-{
- if (x >= virtual_screen.columns || y >= virtual_screen.rows)
- {
- grub_error (GRUB_ERR_OUT_OF_RANGE, "invalid point (%u,%u)",
- (unsigned) x, (unsigned) y);
- return;
- }
-
- if (virtual_screen.cursor_state)
- write_char ();
-
- virtual_screen.cursor_x = x;
- virtual_screen.cursor_y = y;
-
- if (virtual_screen.cursor_state)
- write_cursor ();
-}
-
-static void
-grub_virtual_screen_cls (void)
-{
- grub_uint32_t i;
-
- for (i = 0; i < virtual_screen.columns * virtual_screen.rows; i++)
- {
- virtual_screen.text_buffer[i].code = ' ';
- virtual_screen.text_buffer[i].fg_color = 0;
- virtual_screen.text_buffer[i].bg_color = 0;
- virtual_screen.text_buffer[i].width = 0;
- virtual_screen.text_buffer[i].index = 0;
- }
-
- virtual_screen.cursor_x = virtual_screen.cursor_y = 0;
-}
-
-static void
-grub_vesafb_cls (void)
-{
- grub_virtual_screen_cls ();
-
- grub_memset (framebuffer,
- 0,
- mode_info.y_resolution * bytes_per_scan_line);
-}
-
-static void
-grub_virtual_screen_setcolorstate (grub_term_color_state state)
-{
- switch (state)
- {
- case GRUB_TERM_COLOR_STANDARD:
- case GRUB_TERM_COLOR_NORMAL:
- virtual_screen.fg_color = DEFAULT_FG_COLOR;
- virtual_screen.bg_color = DEFAULT_BG_COLOR;
- break;
- case GRUB_TERM_COLOR_HIGHLIGHT:
- virtual_screen.fg_color = DEFAULT_BG_COLOR;
- virtual_screen.bg_color = DEFAULT_FG_COLOR;
- break;
- default:
- break;
- }
-}
-
-static void
-grub_vesafb_setcursor (int on)
-{
- if (virtual_screen.cursor_state != on)
- {
- if (virtual_screen.cursor_state)
- write_char ();
- else
- write_cursor ();
-
- virtual_screen.cursor_state = on;
- }
-}
-
-static struct grub_term_output grub_vesafb_term =
- {
- .name = "vesafb",
- .init = grub_vesafb_mod_init,
- .fini = grub_vesafb_mod_fini,
- .putchar = grub_vesafb_putchar,
- .getcharwidth = grub_vesafb_getcharwidth,
- .getwh = grub_virtual_screen_getwh,
- .getxy = grub_virtual_screen_getxy,
- .gotoxy = grub_vesafb_gotoxy,
- .cls = grub_vesafb_cls,
- .setcolorstate = grub_virtual_screen_setcolorstate,
- .setcursor = grub_vesafb_setcursor,
- .flags = 0,
- };
-
-GRUB_MOD_INIT(vesafb)
-{
- grub_term_register_output ("vesafb", &grub_vesafb_term);
-}
-
-GRUB_MOD_FINI(vesafb)
-{
- grub_term_unregister_output (&grub_vesafb_term);
-}