diff -Naur grub-0.95-orig/configure.ac grub-0.95/configure.ac --- grub-0.95-orig/configure.ac 2003-10-19 19:25:30.000000000 +0200 +++ grub-0.95/configure.ac 2004-02-15 11:20:57.681027504 +0100 @@ -595,6 +595,11 @@ [ --enable-diskless enable diskless support]) AM_CONDITIONAL(DISKLESS_SUPPORT, test "x$enable_diskless" = xyes) +dnl Graphical splashscreen support +AC_ARG_ENABLE(graphics, + [ --disable-graphics disable graphics terminal support]) +AM_CONDITIONAL(GRAPHICS_SUPPORT, test "x$enable_graphics" != xno) + dnl Hercules terminal AC_ARG_ENABLE(hercules, [ --disable-hercules disable hercules terminal support]) diff -Naur grub-0.95-orig/stage2/asm.S grub-0.95/stage2/asm.S --- grub-0.95-orig/stage2/asm.S 2004-01-11 10:39:22.000000000 +0100 +++ grub-0.95/stage2/asm.S 2004-02-15 11:20:57.706023704 +0100 @@ -2216,6 +2216,156 @@ pop %ebx pop %ebp ret + +/* graphics mode functions */ +#ifdef SUPPORT_GRAPHICS +VARIABLE(cursorX) +.word 0 +VARIABLE(cursorY) +.word 0 +VARIABLE(cursorCount) +.word 0 +VARIABLE(cursorBuf) +.byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + + +/* + * int set_videomode(mode) + * BIOS call "INT 10H Function 0h" to set video mode + * Call with %ah = 0x0 + * %al = video mode + * Returns old videomode. + */ +ENTRY(set_videomode) + push %ebp + push %ebx + push %ecx + + movb 0x10(%esp), %cl + + call EXT_C(prot_to_real) + .code16 + + xorw %bx, %bx + movb $0xf, %ah + int $0x10 /* Get Current Video mode */ + movb %al, %ch + xorb %ah, %ah + movb %cl, %al + int $0x10 /* Set Video mode */ + + DATA32 call EXT_C(real_to_prot) + .code32 + + xorb %ah, %ah + movb %ch, %al + + pop %ecx + pop %ebx + pop %ebp + ret + + +/* + * unsigned char * graphics_get_font() + * BIOS call "INT 10H Function 11h" to set font + * Call with %ah = 0x11 + */ +ENTRY(graphics_get_font) + push %ebp + push %ebx + push %ecx + push %edx + + call EXT_C(prot_to_real) + .code16 + + movw $0x1130, %ax + movb $6, %bh /* font 8x16 */ + int $0x10 + movw %bp, %dx + movw %es, %cx + + DATA32 call EXT_C(real_to_prot) + .code32 + + xorl %eax, %eax + movw %cx, %ax + shll $4, %eax + movw %dx, %ax + + pop %edx + pop %ecx + pop %ebx + pop %ebp + ret + + + +/* + * graphics_set_palette(index, red, green, blue) + * BIOS call "INT 10H Function 10h" to set individual dac register + * Call with %ah = 0x10 + * %bx = register number + * %ch = new value for green (0-63) + * %cl = new value for blue (0-63) + * %dh = new value for red (0-63) + */ + +ENTRY(graphics_set_palette) + push %ebp + push %eax + push %ebx + push %ecx + push %edx + + movw $0x3c8, %bx /* address write mode register */ + + /* wait vertical retrace */ + + movw $0x3da, %dx +l1b: inb %dx, %al /* wait vertical active display */ + test $8, %al + jnz l1b + +l2b: inb %dx, %al /* wait vertical retrace */ + test $8, %al + jnz l2b + + mov %bx, %dx + movb 0x18(%esp), %al /* index */ + outb %al, %dx + inc %dx + + movb 0x1c(%esp), %al /* red */ + outb %al, %dx + + movb 0x20(%esp), %al /* green */ + outb %al, %dx + + movb 0x24(%esp), %al /* blue */ + outb %al, %dx + + movw 0x18(%esp), %bx + + call EXT_C(prot_to_real) + .code16 + + movb %bl, %bh + movw $0x1000, %ax + int $0x10 + + DATA32 call EXT_C(real_to_prot) + .code32 + + pop %edx + pop %ecx + pop %ebx + pop %eax + pop %ebp + ret + +#endif /* SUPPORT_GRAPHICS */ /* * getrtsecs() diff -Naur grub-0.95-orig/stage2/builtins.c grub-0.95/stage2/builtins.c --- grub-0.95-orig/stage2/builtins.c 2004-01-11 10:39:22.000000000 +0100 +++ grub-0.95/stage2/builtins.c 2004-02-15 11:20:57.736019144 +0100 @@ -848,6 +848,138 @@ }; #endif /* SUPPORT_NETBOOT */ +static int terminal_func (char *arg, int flags); + +#ifdef SUPPORT_GRAPHICS + +static int splashimage_func(char *arg, int flags) { + char splashimage[64]; + int i; + + /* filename can only be 64 characters due to our buffer size */ + if (strlen(arg) > 63) + return 1; + if (flags == BUILTIN_CMDLINE) { + if (!grub_open(arg)) + return 1; + grub_close(); + } + + strcpy(splashimage, arg); + + /* get rid of TERM_NEED_INIT from the graphics terminal. */ + for (i = 0; term_table[i].name; i++) { + if (grub_strcmp (term_table[i].name, "graphics") == 0) { + term_table[i].flags &= ~TERM_NEED_INIT; + break; + } + } + + graphics_set_splash(splashimage); + + if (flags == BUILTIN_CMDLINE && graphics_inited) { + graphics_end(); + graphics_init(); + graphics_cls(); + } + + /* FIXME: should we be explicitly switching the terminal as a + * side effect here? */ + terminal_func("graphics", flags); + + return 0; +} + +static struct builtin builtin_splashimage = +{ + "splashimage", + splashimage_func, + BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, + "splashimage FILE", + "Load FILE as the background image when in graphics mode." +}; + + +/* foreground */ +static int +foreground_func(char *arg, int flags) +{ + if (grub_strlen(arg) == 6) { + int r = ((hex(arg[0]) << 4) | hex(arg[1])) >> 2; + int g = ((hex(arg[2]) << 4) | hex(arg[3])) >> 2; + int b = ((hex(arg[4]) << 4) | hex(arg[5])) >> 2; + + foreground = (r << 16) | (g << 8) | b; + if (graphics_inited) + graphics_set_palette(15, r, g, b); + + return (0); + } + + return (1); +} + +static struct builtin builtin_foreground = +{ + "foreground", + foreground_func, + BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, + "foreground RRGGBB", + "Sets the foreground color when in graphics mode." + "RR is red, GG is green, and BB blue. Numbers must be in hexadecimal." +}; + + +/* background */ +static int +background_func(char *arg, int flags) +{ + if (grub_strlen(arg) == 6) { + int r = ((hex(arg[0]) << 4) | hex(arg[1])) >> 2; + int g = ((hex(arg[2]) << 4) | hex(arg[3])) >> 2; + int b = ((hex(arg[4]) << 4) | hex(arg[5])) >> 2; + + background = (r << 16) | (g << 8) | b; + if (graphics_inited) + graphics_set_palette(0, r, g, b); + return (0); + } + + return (1); +} + +static struct builtin builtin_background = +{ + "background", + background_func, + BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, + "background RRGGBB", + "Sets the background color when in graphics mode." + "RR is red, GG is green, and BB blue. Numbers must be in hexadecimal." +}; + +#endif /* SUPPORT_GRAPHICS */ + + +/* clear */ +static int +clear_func() +{ + if (current_term->cls) + current_term->cls(); + + return 0; +} + +static struct builtin builtin_clear = +{ + "clear", + clear_func, + BUILTIN_CMDLINE | BUILTIN_HELP_LIST, + "clear", + "Clear the screen" +}; + /* displayapm */ static int @@ -4073,7 +4205,7 @@ }; -#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) +#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) || defined(SUPPORT_GRAPHICS) /* terminal */ static int terminal_func (char *arg, int flags) @@ -4232,17 +4364,21 @@ end: current_term = term_table + default_term; current_term->flags = term_flags; - + if (lines) max_lines = lines; else - /* 24 would be a good default value. */ - max_lines = 24; - + max_lines = current_term->max_lines; + /* If the interface is currently the command-line, restart it to repaint the screen. */ - if (current_term != prev_term && (flags & BUILTIN_CMDLINE)) + if ((current_term != prev_term) && (flags & BUILTIN_CMDLINE)){ + if (prev_term->shutdown) + prev_term->shutdown(); + if (current_term->startup) + current_term->startup(); grub_longjmp (restart_cmdline_env, 0); + } return 0; } @@ -4252,7 +4388,7 @@ "terminal", terminal_func, BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST, - "terminal [--dumb] [--no-echo] [--no-edit] [--timeout=SECS] [--lines=LINES] [--silent] [console] [serial] [hercules]", + "terminal [--dumb] [--no-echo] [--no-edit] [--timeout=SECS] [--lines=LINES] [--silent] [console] [serial] [hercules] [graphics]", "Select a terminal. When multiple terminals are specified, wait until" " you push any key to continue. If both console and serial are specified," " the terminal to which you input a key first will be selected. If no" @@ -4264,7 +4400,7 @@ " seconds. The option --lines specifies the maximum number of lines." " The option --silent is used to suppress messages." }; -#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES */ +#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES || SUPPORT_GRAPHICS */ #ifdef SUPPORT_SERIAL @@ -4783,6 +4919,9 @@ /* The table of builtin commands. Sorted in dictionary order. */ struct builtin *builtin_table[] = { +#ifdef SUPPORT_GRAPHICS + &builtin_background, +#endif &builtin_blocklist, &builtin_boot, #ifdef SUPPORT_NETBOOT @@ -4790,6 +4929,7 @@ #endif /* SUPPORT_NETBOOT */ &builtin_cat, &builtin_chainloader, + &builtin_clear, &builtin_cmp, &builtin_color, &builtin_configfile, @@ -4809,6 +4949,9 @@ &builtin_embed, &builtin_fallback, &builtin_find, +#ifdef SUPPORT_GRAPHICS + &builtin_foreground, +#endif &builtin_fstest, &builtin_geometry, &builtin_halt, @@ -4852,9 +4995,12 @@ #endif /* SUPPORT_SERIAL */ &builtin_setkey, &builtin_setup, -#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) +#ifdef SUPPORT_GRAPHICS + &builtin_splashimage, +#endif /* SUPPORT_GRAPHICS */ +#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) || defined(SUPPORT_GRAPHICS) &builtin_terminal, -#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES */ +#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES || SUPPORT_GRAPHICS */ #ifdef SUPPORT_SERIAL &builtin_terminfo, #endif /* SUPPORT_SERIAL */ diff -Naur grub-0.95-orig/stage2/char_io.c grub-0.95/stage2/char_io.c --- grub-0.95-orig/stage2/char_io.c 2003-07-09 13:45:52.000000000 +0200 +++ grub-0.95/stage2/char_io.c 2004-02-15 11:20:57.742018232 +0100 @@ -35,6 +35,7 @@ { "console", 0, + 24, console_putchar, console_checkkey, console_getkey, @@ -43,13 +44,16 @@ console_cls, console_setcolorstate, console_setcolor, - console_setcursor + console_setcursor, + 0, + 0 }, #ifdef SUPPORT_SERIAL { "serial", /* A serial device must be initialized. */ TERM_NEED_INIT, + 24, serial_putchar, serial_checkkey, serial_getkey, @@ -58,6 +62,8 @@ serial_cls, serial_setcolorstate, 0, + 0, + 0, 0 }, #endif /* SUPPORT_SERIAL */ @@ -65,6 +71,7 @@ { "hercules", 0, + 24, hercules_putchar, console_checkkey, console_getkey, @@ -73,9 +80,28 @@ hercules_cls, hercules_setcolorstate, hercules_setcolor, - hercules_setcursor + hercules_setcursor, + 0, + 0 }, #endif /* SUPPORT_HERCULES */ +#ifdef SUPPORT_GRAPHICS + { "graphics", + TERM_NEED_INIT, /* flags */ + 30, /* number of lines */ + graphics_putchar, /* putchar */ + console_checkkey, /* checkkey */ + console_getkey, /* getkey */ + graphics_getxy, /* getxy */ + graphics_gotoxy, /* gotoxy */ + graphics_cls, /* cls */ + graphics_setcolorstate, /* setcolorstate */ + graphics_setcolor, /* setcolor */ + graphics_setcursor, /* nocursor */ + graphics_init, /* initialize */ + graphics_end /* shutdown */ + }, +#endif /* SUPPORT_GRAPHICS */ /* This must be the last entry. */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; @@ -1046,13 +1072,15 @@ the following grub_printf call will print newlines. */ count_lines = -1; + grub_printf("\n"); if (current_term->setcolorstate) current_term->setcolorstate (COLOR_STATE_HIGHLIGHT); - grub_printf ("\n[Hit return to continue]"); + grub_printf ("[Hit return to continue]"); if (current_term->setcolorstate) current_term->setcolorstate (COLOR_STATE_NORMAL); + do { @@ -1090,7 +1118,7 @@ cls (void) { /* If the terminal is dumb, there is no way to clean the terminal. */ - if (current_term->flags & TERM_DUMB) + if (current_term->flags & TERM_DUMB) grub_putchar ('\n'); else current_term->cls (); @@ -1214,6 +1242,16 @@ return ! errnum; } +void +grub_memcpy(void *dest, const void *src, int len) +{ + int i; + register char *d = (char*)dest, *s = (char*)src; + + for (i = 0; i < len; i++) + d[i] = s[i]; +} + void * grub_memmove (void *to, const void *from, int len) { diff -Naur grub-0.95-orig/stage2/graphics.c grub-0.95/stage2/graphics.c --- grub-0.95-orig/stage2/graphics.c 1970-01-01 01:00:00.000000000 +0100 +++ grub-0.95/stage2/graphics.c 2004-02-15 11:20:57.744017928 +0100 @@ -0,0 +1,552 @@ +/* graphics.c - graphics mode support for GRUB */ +/* Implemented as a terminal type by Jeremy Katz based + * on a patch by Paulo César Pereira de Andrade + */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2001,2002 Red Hat, Inc. + * Portions copyright (C) 2000 Conectiva, Inc. + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + + +#ifdef SUPPORT_GRAPHICS + +#include +#include +#include + +int saved_videomode; +unsigned char *font8x16; + +int graphics_inited = 0; +static char splashimage[64]; + +#define VSHADOW VSHADOW1 +unsigned char VSHADOW1[38400]; +unsigned char VSHADOW2[38400]; +unsigned char VSHADOW4[38400]; +unsigned char VSHADOW8[38400]; + +/* constants to define the viewable area */ +const int x0 = 0; +const int x1 = 80; +const int y0 = 0; +const int y1 = 30; + +/* text buffer has to be kept around so that we can write things as we + * scroll and the like */ +unsigned short text[80 * 30]; + +/* why do these have to be kept here? */ +int foreground = (63 << 16) | (63 << 8) | (63), background = 0, border = 0; + +/* current position */ +static int fontx = 0; +static int fonty = 0; + +/* global state so that we don't try to recursively scroll or cursor */ +static int no_scroll = 0; + +/* color state */ +static int graphics_standard_color = A_NORMAL; +static int graphics_normal_color = A_NORMAL; +static int graphics_highlight_color = A_REVERSE; +static int graphics_current_color = A_NORMAL; +static color_state graphics_color_state = COLOR_STATE_STANDARD; + + +/* graphics local functions */ +static void graphics_setxy(int col, int row); +static void graphics_scroll(); + +/* FIXME: where do these really belong? */ +static inline void outb(unsigned short port, unsigned char val) +{ + __asm __volatile ("outb %0,%1"::"a" (val), "d" (port)); +} + +static void MapMask(int value) { + outb(0x3c4, 2); + outb(0x3c5, value); +} + +/* bit mask register */ +static void BitMask(int value) { + outb(0x3ce, 8); + outb(0x3cf, value); +} + + + +/* Set the splash image */ +void graphics_set_splash(char *splashfile) { + grub_strcpy(splashimage, splashfile); +} + +/* Get the current splash image */ +char *graphics_get_splash(void) { + return splashimage; +} + +/* Initialize a vga16 graphics display with the palette based off of + * the image in splashimage. If the image doesn't exist, leave graphics + * mode. */ +int graphics_init() +{ + if (!graphics_inited) { + saved_videomode = set_videomode(0x12); + } + + if (!read_image(splashimage)) { + set_videomode(saved_videomode); + grub_printf("failed to read image\n"); + return 0; + } + + font8x16 = (unsigned char*)graphics_get_font(); + + graphics_inited = 1; + + /* make sure that the highlight color is set correctly */ + graphics_highlight_color = ((graphics_normal_color >> 4) | + ((graphics_normal_color & 0xf) << 4)); + + return 1; +} + +/* Leave graphics mode */ +void graphics_end(void) +{ + if (graphics_inited) { + set_videomode(saved_videomode); + graphics_inited = 0; + } +} + +/* Print ch on the screen. Handle any needed scrolling or the like */ +void graphics_putchar(int ch) { + ch &= 0xff; + + graphics_cursor(0); + + if (ch == '\n') { + if (fonty + 1 < y1) + graphics_setxy(fontx, fonty + 1); + else + graphics_scroll(); + graphics_cursor(1); + return; + } else if (ch == '\r') { + graphics_setxy(x0, fonty); + graphics_cursor(1); + return; + } + + graphics_cursor(0); + + text[fonty * 80 + fontx] = ch; + text[fonty * 80 + fontx] &= 0x00ff; + if (graphics_current_color & 0xf0) + text[fonty * 80 + fontx] |= 0x100; + + graphics_cursor(0); + + if ((fontx + 1) >= x1) { + graphics_setxy(x0, fonty); + if (fonty + 1 < y1) + graphics_setxy(x0, fonty + 1); + else + graphics_scroll(); + } else { + graphics_setxy(fontx + 1, fonty); + } + + graphics_cursor(1); +} + +/* get the current location of the cursor */ +int graphics_getxy(void) { + return (fontx << 8) | fonty; +} + +void graphics_gotoxy(int x, int y) { + graphics_cursor(0); + + graphics_setxy(x, y); + + graphics_cursor(1); +} + +void graphics_cls(void) { + int i; + unsigned char *mem, *s1, *s2, *s4, *s8; + + graphics_cursor(0); + graphics_gotoxy(x0, y0); + + mem = (unsigned char*)VIDEOMEM; + s1 = (unsigned char*)VSHADOW1; + s2 = (unsigned char*)VSHADOW2; + s4 = (unsigned char*)VSHADOW4; + s8 = (unsigned char*)VSHADOW8; + + for (i = 0; i < 80 * 30; i++) + text[i] = ' '; + graphics_cursor(1); + + BitMask(0xff); + + /* plano 1 */ + MapMask(1); + grub_memcpy(mem, s1, 38400); + + /* plano 2 */ + MapMask(2); + grub_memcpy(mem, s2, 38400); + + /* plano 3 */ + MapMask(4); + grub_memcpy(mem, s4, 38400); + + /* plano 4 */ + MapMask(8); + grub_memcpy(mem, s8, 38400); + + MapMask(15); + +} + +void graphics_setcolorstate (color_state state) { + switch (state) { + case COLOR_STATE_STANDARD: + graphics_current_color = graphics_standard_color; + break; + case COLOR_STATE_NORMAL: + graphics_current_color = graphics_normal_color; + break; + case COLOR_STATE_HIGHLIGHT: + graphics_current_color = graphics_highlight_color; + break; + default: + graphics_current_color = graphics_standard_color; + break; + } + + graphics_color_state = state; +} + +void graphics_setcolor (int normal_color, int highlight_color) { + graphics_normal_color = normal_color; + graphics_highlight_color = highlight_color; + + graphics_setcolorstate (graphics_color_state); +} + +void graphics_setcursor (int on) { + /* FIXME: we don't have a cursor in graphics */ + return; +} + +/* Read in the splashscreen image and set the palette up appropriately. + * Format of splashscreen is an xpm (can be gzipped) with 16 colors and + * 640x480. */ +int read_image(char *s) +{ + char buf[32], pal[16]; + unsigned char c, base, mask, *s1, *s2, *s4, *s8; + unsigned i, len, idx, colors, x, y, width, height; + + if (!grub_open(s)) + return 0; + + /* read header */ + if (!grub_read((char*)&buf, 10) || grub_memcmp(buf, "/* XPM */\n", 10)) { + grub_close(); + return 0; + } + + /* parse info */ + while (grub_read(&c, 1)) { + if (c == '"') + break; + } + + while (grub_read(&c, 1) && (c == ' ' || c == '\t')) + ; + + i = 0; + width = c - '0'; + while (grub_read(&c, 1)) { + if (c >= '0' && c <= '9') + width = width * 10 + c - '0'; + else + break; + } + while (grub_read(&c, 1) && (c == ' ' || c == '\t')) + ; + + height = c - '0'; + while (grub_read(&c, 1)) { + if (c >= '0' && c <= '9') + height = height * 10 + c - '0'; + else + break; + } + while (grub_read(&c, 1) && (c == ' ' || c == '\t')) + ; + + colors = c - '0'; + while (grub_read(&c, 1)) { + if (c >= '0' && c <= '9') + colors = colors * 10 + c - '0'; + else + break; + } + + base = 0; + while (grub_read(&c, 1) && c != '"') + ; + + /* palette */ + for (i = 0, idx = 1; i < colors; i++) { + len = 0; + + while (grub_read(&c, 1) && c != '"') + ; + grub_read(&c, 1); /* char */ + base = c; + grub_read(buf, 4); /* \t c # */ + + while (grub_read(&c, 1) && c != '"') { + if (len < sizeof(buf)) + buf[len++] = c; + } + + if (len == 6 && idx < 15) { + int r = ((hex(buf[0]) << 4) | hex(buf[1])) >> 2; + int g = ((hex(buf[2]) << 4) | hex(buf[3])) >> 2; + int b = ((hex(buf[4]) << 4) | hex(buf[5])) >> 2; + + pal[idx] = base; + graphics_set_palette(idx, r, g, b); + ++idx; + } + } + + x = y = len = 0; + + s1 = (unsigned char*)VSHADOW1; + s2 = (unsigned char*)VSHADOW2; + s4 = (unsigned char*)VSHADOW4; + s8 = (unsigned char*)VSHADOW8; + + for (i = 0; i < 38400; i++) + s1[i] = s2[i] = s4[i] = s8[i] = 0; + + /* parse xpm data */ + while (y < height) { + while (1) { + if (!grub_read(&c, 1)) { + grub_close(); + return 0; + } + if (c == '"') + break; + } + + while (grub_read(&c, 1) && c != '"') { + for (i = 1; i < 15; i++) + if (pal[i] == c) { + c = i; + break; + } + + mask = 0x80 >> (x & 7); + if (c & 1) + s1[len + (x >> 3)] |= mask; + if (c & 2) + s2[len + (x >> 3)] |= mask; + if (c & 4) + s4[len + (x >> 3)] |= mask; + if (c & 8) + s8[len + (x >> 3)] |= mask; + + if (++x >= 640) { + x = 0; + + if (y < 480) + len += 80; + ++y; + } + } + } + + grub_close(); + + graphics_set_palette(0, (background >> 16), (background >> 8) & 63, + background & 63); + graphics_set_palette(15, (foreground >> 16), (foreground >> 8) & 63, + foreground & 63); + graphics_set_palette(0x11, (border >> 16), (border >> 8) & 63, + border & 63); + + return 1; +} + + +/* Convert a character which is a hex digit to the appropriate integer */ +int hex(int v) +{ + if (v >= 'A' && v <= 'F') + return (v - 'A' + 10); + if (v >= 'a' && v <= 'f') + return (v - 'a' + 10); + return (v - '0'); +} + + +/* move the graphics cursor location to col, row */ +static void graphics_setxy(int col, int row) { + if (col >= x0 && col < x1) { + fontx = col; + cursorX = col << 3; + } + if (row >= y0 && row < y1) { + fonty = row; + cursorY = row << 4; + } +} + +/* scroll the screen */ +static void graphics_scroll() { + int i, j; + + /* we don't want to scroll recursively... that would be bad */ + if (no_scroll) + return; + no_scroll = 1; + + /* move everything up a line */ + for (j = y0 + 1; j < y1; j++) { + graphics_gotoxy(x0, j - 1); + for (i = x0; i < x1; i++) { + graphics_putchar(text[j * 80 + i]); + } + } + + /* last line should be blank */ + graphics_gotoxy(x0, y1 - 1); + for (i = x0; i < x1; i++) + graphics_putchar(' '); + graphics_setxy(x0, y1 - 1); + + no_scroll = 0; +} + + +void graphics_cursor(int set) { + unsigned char *pat, *mem, *ptr, chr[16 << 2]; + int i, ch, invert, offset; + + if (set && no_scroll) + return; + + offset = cursorY * 80 + fontx; + ch = text[fonty * 80 + fontx] & 0xff; + invert = (text[fonty * 80 + fontx] & 0xff00) != 0; + pat = font8x16 + (ch << 4); + + mem = (unsigned char*)VIDEOMEM + offset; + + if (!set) { + for (i = 0; i < 16; i++) { + unsigned char mask = pat[i]; + + if (!invert) { + chr[i ] = ((unsigned char*)VSHADOW1)[offset]; + chr[16 + i] = ((unsigned char*)VSHADOW2)[offset]; + chr[32 + i] = ((unsigned char*)VSHADOW4)[offset]; + chr[48 + i] = ((unsigned char*)VSHADOW8)[offset]; + + /* FIXME: if (shade) */ + if (1) { + if (ch == DISP_VERT || ch == DISP_LL || + ch == DISP_UR || ch == DISP_LR) { + unsigned char pmask = ~(pat[i] >> 1); + + chr[i ] &= pmask; + chr[16 + i] &= pmask; + chr[32 + i] &= pmask; + chr[48 + i] &= pmask; + } + if (i > 0 && ch != DISP_VERT) { + unsigned char pmask = ~(pat[i - 1] >> 1); + + chr[i ] &= pmask; + chr[16 + i] &= pmask; + chr[32 + i] &= pmask; + chr[48 + i] &= pmask; + if (ch == DISP_HORIZ || ch == DISP_UR || ch == DISP_LR) { + pmask = ~pat[i - 1]; + + chr[i ] &= pmask; + chr[16 + i] &= pmask; + chr[32 + i] &= pmask; + chr[48 + i] &= pmask; + } + } + } + chr[i ] |= mask; + chr[16 + i] |= mask; + chr[32 + i] |= mask; + chr[48 + i] |= mask; + + offset += 80; + } + else { + chr[i ] = mask; + chr[16 + i] = mask; + chr[32 + i] = mask; + chr[48 + i] = mask; + } + } + } + else { + MapMask(15); + ptr = mem; + for (i = 0; i < 16; i++, ptr += 80) { + cursorBuf[i] = pat[i]; + *ptr = ~pat[i]; + } + return; + } + + offset = 0; + for (i = 1; i < 16; i <<= 1, offset += 16) { + int j; + + MapMask(i); + ptr = mem; + for (j = 0; j < 16; j++, ptr += 80) + *ptr = chr[j + offset]; + } + + MapMask(15); +} + +#endif /* SUPPORT_GRAPHICS */ diff -Naur grub-0.95-orig/stage2/graphics.h grub-0.95/stage2/graphics.h --- grub-0.95-orig/stage2/graphics.h 1970-01-01 01:00:00.000000000 +0100 +++ grub-0.95/stage2/graphics.h 2004-02-15 11:20:57.746017624 +0100 @@ -0,0 +1,42 @@ +/* graphics.h - graphics console interface */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002 Free Software Foundation, Inc. + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef GRAPHICS_H +#define GRAPHICS_H + +/* magic constant */ +#define VIDEOMEM 0xA0000 + +/* function prototypes */ +char *graphics_get_splash(void); + +int read_image(char *s); +void graphics_cursor(int set); + +/* function prototypes for asm functions */ +void * graphics_get_font(); +void graphics_set_palette(int idx, int red, int green, int blue); +void set_int1c_handler(); +void unset_int1c_handler(); + +extern short cursorX, cursorY; +extern char cursorBuf[16]; + +#endif /* GRAPHICS_H */ diff -Naur grub-0.95-orig/stage2/Makefile.am grub-0.95/stage2/Makefile.am --- grub-0.95-orig/stage2/Makefile.am 2003-10-19 18:45:18.000000000 +0200 +++ grub-0.95/stage2/Makefile.am 2004-02-15 11:20:57.748017320 +0100 @@ -7,7 +7,7 @@ fat.h filesys.h freebsd.h fs.h hercules.h i386-elf.h \ imgact_aout.h iso9660.h jfs.h mb_header.h mb_info.h md5.h \ nbi.h pc_slice.h serial.h shared.h smp-imps.h term.h \ - terminfo.h tparm.h nbi.h ufs2.h vstafs.h xfs.h + terminfo.h tparm.h nbi.h ufs2.h vstafs.h xfs.h graphics.h EXTRA_DIST = setjmp.S apm.S $(noinst_SCRIPTS) # For . @@ -19,7 +19,7 @@ disk_io.c fsys_ext2fs.c fsys_fat.c fsys_ffs.c fsys_iso9660.c \ fsys_jfs.c fsys_minix.c fsys_reiserfs.c fsys_ufs2.c \ fsys_vstafs.c fsys_xfs.c gunzip.c md5.c serial.c stage2.c \ - terminfo.c tparm.c + terminfo.c tparm.c graphics.c libgrub_a_CFLAGS = $(GRUB_CFLAGS) -I$(top_srcdir)/lib \ -DGRUB_UTIL=1 -DFSYS_EXT2FS=1 -DFSYS_FAT=1 -DFSYS_FFS=1 \ -DFSYS_ISO9660=1 -DFSYS_JFS=1 -DFSYS_MINIX=1 -DFSYS_REISERFS=1 \ @@ -80,8 +80,14 @@ HERCULES_FLAGS = endif +if GRAPHICS_SUPPORT +GRAPHICS_FLAGS = -DSUPPORT_GRAPHICS=1 +else +GRAPHICS_FLAGS = +endif + STAGE2_COMPILE = $(STAGE2_CFLAGS) -fno-builtin -nostdinc \ - $(NETBOOT_FLAGS) $(SERIAL_FLAGS) $(HERCULES_FLAGS) + $(NETBOOT_FLAGS) $(SERIAL_FLAGS) $(HERCULES_FLAGS) $(GRAPHICS_FLAGS) STAGE1_5_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,2000 STAGE1_5_COMPILE = $(STAGE2_COMPILE) -DNO_DECOMPRESSION=1 -DSTAGE1_5=1 @@ -91,7 +97,8 @@ cmdline.c common.c console.c disk_io.c fsys_ext2fs.c \ fsys_fat.c fsys_ffs.c fsys_iso9660.c fsys_jfs.c fsys_minix.c \ fsys_reiserfs.c fsys_ufs2.c fsys_vstafs.c fsys_xfs.c gunzip.c \ - hercules.c md5.c serial.c smp-imps.c stage2.c terminfo.c tparm.c + hercules.c md5.c serial.c smp-imps.c stage2.c terminfo.c tparm.c \ + graphics.c pre_stage2_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS) pre_stage2_exec_CCASFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS) pre_stage2_exec_LDFLAGS = $(PRE_STAGE2_LINK) diff -Naur grub-0.95-orig/stage2/shared.h grub-0.95/stage2/shared.h --- grub-0.95-orig/stage2/shared.h 2004-01-11 10:39:22.000000000 +0100 +++ grub-0.95/stage2/shared.h 2004-02-15 11:20:57.760015496 +0100 @@ -871,6 +871,7 @@ int grub_tolower (int c); int grub_isspace (int c); int grub_strncat (char *s1, const char *s2, int n); +void grub_memcpy(void *dest, const void *src, int len); void *grub_memmove (void *to, const void *from, int len); void *grub_memset (void *start, int c, int len); int grub_strncat (char *s1, const char *s2, int n); diff -Naur grub-0.95-orig/stage2/shared.h.orig grub-0.95/stage2/shared.h.orig --- grub-0.95-orig/stage2/shared.h.orig 1970-01-01 01:00:00.000000000 +0100 +++ grub-0.95/stage2/shared.h.orig 2004-01-11 10:39:22.000000000 +0100 @@ -0,0 +1,980 @@ +/* shared.h - definitions used in all GRUB-specific code */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc. + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * Generic defines to use anywhere + */ + +#ifndef GRUB_SHARED_HEADER +#define GRUB_SHARED_HEADER 1 + +#include + +/* Add an underscore to a C symbol in assembler code if needed. */ +#ifdef HAVE_ASM_USCORE +# define EXT_C(sym) _ ## sym +#else +# define EXT_C(sym) sym +#endif + +/* Maybe redirect memory requests through grub_scratch_mem. */ +#ifdef GRUB_UTIL +extern char *grub_scratch_mem; +# define RAW_ADDR(x) ((x) + (int) grub_scratch_mem) +# define RAW_SEG(x) (RAW_ADDR ((x) << 4) >> 4) +#else +# define RAW_ADDR(x) (x) +# define RAW_SEG(x) (x) +#endif + +/* + * Integer sizes + */ + +#define MAXINT 0x7FFFFFFF + +/* Maximum command line size. Before you blindly increase this value, + see the comment in char_io.c (get_cmdline). */ +#define MAX_CMDLINE 1600 +#define NEW_HEAPSIZE 1500 + +/* 512-byte scratch area */ +#define SCRATCHADDR RAW_ADDR (0x77e00) +#define SCRATCHSEG RAW_SEG (0x77e0) + +/* + * This is the location of the raw device buffer. It is 31.5K + * in size. + */ + +#define BUFFERLEN 0x7e00 +#define BUFFERADDR RAW_ADDR (0x70000) +#define BUFFERSEG RAW_SEG (0x7000) + +#define BOOT_PART_TABLE RAW_ADDR (0x07be) + +/* + * BIOS disk defines + */ +#define BIOSDISK_READ 0x0 +#define BIOSDISK_WRITE 0x1 +#define BIOSDISK_ERROR_GEOMETRY 0x100 +#define BIOSDISK_FLAG_LBA_EXTENSION 0x1 + +/* + * This is the filesystem (not raw device) buffer. + * It is 32K in size, do not overrun! + */ + +#define FSYS_BUFLEN 0x8000 +#define FSYS_BUF RAW_ADDR (0x68000) + +/* Command-line buffer for Multiboot kernels and modules. This area + includes the area into which Stage 1.5 and Stage 1 are loaded, but + that's no problem. */ +#define MB_CMDLINE_BUF RAW_ADDR (0x2000) +#define MB_CMDLINE_BUFLEN 0x6000 + +/* The buffer for the password. */ +#define PASSWORD_BUF RAW_ADDR (0x78000) +#define PASSWORD_BUFLEN 0x200 + +/* The buffer for the command-line. */ +#define CMDLINE_BUF (PASSWORD_BUF + PASSWORD_BUFLEN) +#define CMDLINE_BUFLEN MAX_CMDLINE + +/* The kill buffer for the command-line. */ +#define KILL_BUF (CMDLINE_BUF + CMDLINE_BUFLEN) +#define KILL_BUFLEN MAX_CMDLINE + +/* The history buffer for the command-line. */ +#define HISTORY_BUF (KILL_BUF + KILL_BUFLEN) +#define HISTORY_SIZE 5 +#define HISTORY_BUFLEN (MAX_CMDLINE * HISTORY_SIZE) + +/* The buffer for the completion. */ +#define COMPLETION_BUF (HISTORY_BUF + HISTORY_BUFLEN) +#define COMPLETION_BUFLEN MAX_CMDLINE + +/* The buffer for the unique string. */ +#define UNIQUE_BUF (COMPLETION_BUF + COMPLETION_BUFLEN) +#define UNIQUE_BUFLEN MAX_CMDLINE + +/* The buffer for the menu entries. */ +#define MENU_BUF (UNIQUE_BUF + UNIQUE_BUFLEN) +#define MENU_BUFLEN (0x8000 + PASSWORD_BUF - UNIQUE_BUF) + +/* The size of the drive map. */ +#define DRIVE_MAP_SIZE 8 + +/* The size of the key map. */ +#define KEY_MAP_SIZE 128 + +/* The size of the io map. */ +#define IO_MAP_SIZE 128 + +/* + * Linux setup parameters + */ + +#define LINUX_MAGIC_SIGNATURE 0x53726448 /* "HdrS" */ +#define LINUX_DEFAULT_SETUP_SECTS 4 +#define LINUX_FLAG_CAN_USE_HEAP 0x80 +#define LINUX_INITRD_MAX_ADDRESS 0x38000000 +#define LINUX_MAX_SETUP_SECTS 64 +#define LINUX_BOOT_LOADER_TYPE 0x71 +#define LINUX_HEAP_END_OFFSET (0x9000 - 0x200) + +#define LINUX_BZIMAGE_ADDR RAW_ADDR (0x100000) +#define LINUX_ZIMAGE_ADDR RAW_ADDR (0x10000) +#define LINUX_OLD_REAL_MODE_ADDR RAW_ADDR (0x90000) +#define LINUX_SETUP_STACK 0x9000 + +#define LINUX_FLAG_BIG_KERNEL 0x1 + +/* Linux's video mode selection support. Actually I hate it! */ +#define LINUX_VID_MODE_NORMAL 0xFFFF +#define LINUX_VID_MODE_EXTENDED 0xFFFE +#define LINUX_VID_MODE_ASK 0xFFFD + +#define LINUX_CL_OFFSET 0x9000 +#define LINUX_CL_END_OFFSET 0x90FF +#define LINUX_SETUP_MOVE_SIZE 0x9100 +#define LINUX_CL_MAGIC 0xA33F + +/* + * General disk stuff + */ + +#define SECTOR_SIZE 0x200 +#define SECTOR_BITS 9 +#define BIOS_FLAG_FIXED_DISK 0x80 + +#define BOOTSEC_LOCATION RAW_ADDR (0x7C00) +#define BOOTSEC_SIGNATURE 0xAA55 +#define BOOTSEC_BPB_OFFSET 0x3 +#define BOOTSEC_BPB_LENGTH 0x3B +#define BOOTSEC_BPB_SYSTEM_ID 0x3 +#define BOOTSEC_BPB_HIDDEN_SECTORS 0x1C +#define BOOTSEC_PART_OFFSET 0x1BE +#define BOOTSEC_PART_LENGTH 0x40 +#define BOOTSEC_SIG_OFFSET 0x1FE +#define BOOTSEC_LISTSIZE 8 + +/* Not bad, perhaps. */ +#define NETWORK_DRIVE 0x20 + +/* + * GRUB specific information + * (in LSB order) + */ + +#include + +#define STAGE2_VER_MAJ_OFFS 0x6 +#define STAGE2_INSTALLPART 0x8 +#define STAGE2_SAVED_ENTRYNO 0xc +#define STAGE2_STAGE2_ID 0x10 +#define STAGE2_FORCE_LBA 0x11 +#define STAGE2_VER_STR_OFFS 0x12 + +/* Stage 2 identifiers */ +#define STAGE2_ID_STAGE2 0 +#define STAGE2_ID_FFS_STAGE1_5 1 +#define STAGE2_ID_E2FS_STAGE1_5 2 +#define STAGE2_ID_FAT_STAGE1_5 3 +#define STAGE2_ID_MINIX_STAGE1_5 4 +#define STAGE2_ID_REISERFS_STAGE1_5 5 +#define STAGE2_ID_VSTAFS_STAGE1_5 6 +#define STAGE2_ID_JFS_STAGE1_5 7 +#define STAGE2_ID_XFS_STAGE1_5 8 + +#ifndef STAGE1_5 +# define STAGE2_ID STAGE2_ID_STAGE2 +#else +# if defined(FSYS_FFS) +# define STAGE2_ID STAGE2_ID_FFS_STAGE1_5 +# elif defined(FSYS_EXT2FS) +# define STAGE2_ID STAGE2_ID_E2FS_STAGE1_5 +# elif defined(FSYS_FAT) +# define STAGE2_ID STAGE2_ID_FAT_STAGE1_5 +# elif defined(FSYS_MINIX) +# define STAGE2_ID STAGE2_ID_MINIX_STAGE1_5 +# elif defined(FSYS_REISERFS) +# define STAGE2_ID STAGE2_ID_REISERFS_STAGE1_5 +# elif defined(FSYS_VSTAFS) +# define STAGE2_ID STAGE2_ID_VSTAFS_STAGE1_5 +# elif defined(FSYS_JFS) +# define STAGE2_ID STAGE2_ID_JFS_STAGE1_5 +# elif defined(FSYS_XFS) +# define STAGE2_ID STAGE2_ID_XFS_STAGE1_5 +# else +# error "unknown Stage 2" +# endif +#endif + +/* + * defines for use when switching between real and protected mode + */ + +#define CR0_PE_ON 0x1 +#define CR0_PE_OFF 0xfffffffe +#define PROT_MODE_CSEG 0x8 +#define PROT_MODE_DSEG 0x10 +#define PSEUDO_RM_CSEG 0x18 +#define PSEUDO_RM_DSEG 0x20 +#define STACKOFF (0x2000 - 0x10) +#define PROTSTACKINIT (FSYS_BUF - 0x10) + + +/* + * Assembly code defines + * + * "EXT_C" is assumed to be defined in the Makefile by the configure + * command. + */ + +#define ENTRY(x) .globl EXT_C(x) ; EXT_C(x): +#define VARIABLE(x) ENTRY(x) + + +#define K_RDWR 0x60 /* keyboard data & cmds (read/write) */ +#define K_STATUS 0x64 /* keyboard status */ +#define K_CMD 0x64 /* keybd ctlr command (write-only) */ + +#define K_OBUF_FUL 0x01 /* output buffer full */ +#define K_IBUF_FUL 0x02 /* input buffer full */ + +#define KC_CMD_WIN 0xd0 /* read output port */ +#define KC_CMD_WOUT 0xd1 /* write output port */ +#define KB_OUTPUT_MASK 0xdd /* enable output buffer full interrupt + enable data line + enable clock line */ +#define KB_A20_ENABLE 0x02 + +/* Codes for getchar. */ +#define ASCII_CHAR(x) ((x) & 0xFF) +#if !defined(GRUB_UTIL) || !defined(HAVE_LIBCURSES) +# define KEY_LEFT 0x4B00 +# define KEY_RIGHT 0x4D00 +# define KEY_UP 0x4800 +# define KEY_DOWN 0x5000 +# define KEY_IC 0x5200 /* insert char */ +# define KEY_DC 0x5300 /* delete char */ +# define KEY_BACKSPACE 0x0008 +# define KEY_HOME 0x4700 +# define KEY_END 0x4F00 +# define KEY_NPAGE 0x5100 +# define KEY_PPAGE 0x4900 +# define A_NORMAL 0x7 +# define A_REVERSE 0x70 +#elif defined(HAVE_NCURSES_CURSES_H) +# include +#elif defined(HAVE_NCURSES_H) +# include +#elif defined(HAVE_CURSES_H) +# include +#endif + +/* In old BSD curses, A_NORMAL and A_REVERSE are not defined, so we + define them here if they are undefined. */ +#ifndef A_NORMAL +# define A_NORMAL 0 +#endif /* ! A_NORMAL */ +#ifndef A_REVERSE +# ifdef A_STANDOUT +# define A_REVERSE A_STANDOUT +# else /* ! A_STANDOUT */ +# define A_REVERSE 0 +# endif /* ! A_STANDOUT */ +#endif /* ! A_REVERSE */ + +/* Define ACS_* ourselves, since the definitions are not consistent among + various curses implementations. */ +#undef ACS_ULCORNER +#undef ACS_URCORNER +#undef ACS_LLCORNER +#undef ACS_LRCORNER +#undef ACS_HLINE +#undef ACS_VLINE +#undef ACS_LARROW +#undef ACS_RARROW +#undef ACS_UARROW +#undef ACS_DARROW + +#define ACS_ULCORNER '+' +#define ACS_URCORNER '+' +#define ACS_LLCORNER '+' +#define ACS_LRCORNER '+' +#define ACS_HLINE '-' +#define ACS_VLINE '|' +#define ACS_LARROW '<' +#define ACS_RARROW '>' +#define ACS_UARROW '^' +#define ACS_DARROW 'v' + +/* Special graphics characters for IBM displays. */ +#define DISP_UL 218 +#define DISP_UR 191 +#define DISP_LL 192 +#define DISP_LR 217 +#define DISP_HORIZ 196 +#define DISP_VERT 179 +#define DISP_LEFT 0x1b +#define DISP_RIGHT 0x1a +#define DISP_UP 0x18 +#define DISP_DOWN 0x19 + +/* Remap some libc-API-compatible function names so that we prevent + circularararity. */ +#ifndef WITHOUT_LIBC_STUBS +#define memmove grub_memmove +#define memcpy grub_memmove /* we don't need a separate memcpy */ +#define memset grub_memset +#define isspace grub_isspace +#define printf grub_printf +#define sprintf grub_sprintf +#undef putchar +#define putchar grub_putchar +#define strncat grub_strncat +#define strstr grub_strstr +#define memcmp grub_memcmp +#define strcmp grub_strcmp +#define tolower grub_tolower +#define strlen grub_strlen +#define strcpy grub_strcpy +#endif /* WITHOUT_LIBC_STUBS */ + + +#ifndef ASM_FILE +/* + * Below this should be ONLY defines and other constructs for C code. + */ + +/* multiboot stuff */ + +#include "mb_header.h" +#include "mb_info.h" + +/* For the Linux/i386 boot protocol version 2.03. */ +struct linux_kernel_header +{ + char code1[0x0020]; + unsigned short cl_magic; /* Magic number 0xA33F */ + unsigned short cl_offset; /* The offset of command line */ + char code2[0x01F1 - 0x0020 - 2 - 2]; + unsigned char setup_sects; /* The size of the setup in sectors */ + unsigned short root_flags; /* If the root is mounted readonly */ + unsigned short syssize; /* obsolete */ + unsigned short swap_dev; /* obsolete */ + unsigned short ram_size; /* obsolete */ + unsigned short vid_mode; /* Video mode control */ + unsigned short root_dev; /* Default root device number */ + unsigned short boot_flag; /* 0xAA55 magic number */ + unsigned short jump; /* Jump instruction */ + unsigned long header; /* Magic signature "HdrS" */ + unsigned short version; /* Boot protocol version supported */ + unsigned long realmode_swtch; /* Boot loader hook */ + unsigned long start_sys; /* Points to kernel version string */ + unsigned char type_of_loader; /* Boot loader identifier */ + unsigned char loadflags; /* Boot protocol option flags */ + unsigned short setup_move_size; /* Move to high memory size */ + unsigned long code32_start; /* Boot loader hook */ + unsigned long ramdisk_image; /* initrd load address */ + unsigned long ramdisk_size; /* initrd size */ + unsigned long bootsect_kludge; /* obsolete */ + unsigned short heap_end_ptr; /* Free memory after setup end */ + unsigned short pad1; /* Unused */ + char *cmd_line_ptr; /* Points to the kernel command line */ + unsigned long initrd_addr_max; /* The highest address of initrd */ +} __attribute__ ((packed)); + +/* Memory map address range descriptor used by GET_MMAP_ENTRY. */ +struct mmar_desc +{ + unsigned long desc_len; /* Size of this descriptor. */ + unsigned long long addr; /* Base address. */ + unsigned long long length; /* Length in bytes. */ + unsigned long type; /* Type of address range. */ +} __attribute__ ((packed)); + +/* VBE controller information. */ +struct vbe_controller +{ + unsigned char signature[4]; + unsigned short version; + unsigned long oem_string; + unsigned long capabilities; + unsigned long video_mode; + unsigned short total_memory; + unsigned short oem_software_rev; + unsigned long oem_vendor_name; + unsigned long oem_product_name; + unsigned long oem_product_rev; + unsigned char reserved[222]; + unsigned char oem_data[256]; +} __attribute__ ((packed)); + +/* VBE mode information. */ +struct vbe_mode +{ + unsigned short mode_attributes; + unsigned char win_a_attributes; + unsigned char win_b_attributes; + unsigned short win_granularity; + unsigned short win_size; + unsigned short win_a_segment; + unsigned short win_b_segment; + unsigned long win_func; + unsigned short bytes_per_scanline; + + /* >=1.2 */ + unsigned short x_resolution; + unsigned short y_resolution; + unsigned char x_char_size; + unsigned char y_char_size; + unsigned char number_of_planes; + unsigned char bits_per_pixel; + unsigned char number_of_banks; + unsigned char memory_model; + unsigned char bank_size; + unsigned char number_of_image_pages; + unsigned char reserved0; + + /* direct color */ + unsigned char red_mask_size; + unsigned char red_field_position; + unsigned char green_mask_size; + unsigned char green_field_position; + unsigned char blue_mask_size; + unsigned char blue_field_position; + unsigned char reserved_mask_size; + unsigned char reserved_field_position; + unsigned char direct_color_mode_info; + + /* >=2.0 */ + unsigned long phys_base; + unsigned long reserved1; + unsigned short reversed2; + + /* >=3.0 */ + unsigned short linear_bytes_per_scanline; + unsigned char banked_number_of_image_pages; + unsigned char linear_number_of_image_pages; + unsigned char linear_red_mask_size; + unsigned char linear_red_field_position; + unsigned char linear_green_mask_size; + unsigned char linear_green_field_position; + unsigned char linear_blue_mask_size; + unsigned char linear_blue_field_position; + unsigned char linear_reserved_mask_size; + unsigned char linear_reserved_field_position; + unsigned long max_pixel_clock; + + unsigned char reserved3[189]; +} __attribute__ ((packed)); + + +#undef NULL +#define NULL ((void *) 0) + +/* Error codes (descriptions are in common.c) */ +typedef enum +{ + ERR_NONE = 0, + ERR_BAD_FILENAME, + ERR_BAD_FILETYPE, + ERR_BAD_GZIP_DATA, + ERR_BAD_GZIP_HEADER, + ERR_BAD_PART_TABLE, + ERR_BAD_VERSION, + ERR_BELOW_1MB, + ERR_BOOT_COMMAND, + ERR_BOOT_FAILURE, + ERR_BOOT_FEATURES, + ERR_DEV_FORMAT, + ERR_DEV_VALUES, + ERR_EXEC_FORMAT, + ERR_FILELENGTH, + ERR_FILE_NOT_FOUND, + ERR_FSYS_CORRUPT, + ERR_FSYS_MOUNT, + ERR_GEOM, + ERR_NEED_LX_KERNEL, + ERR_NEED_MB_KERNEL, + ERR_NO_DISK, + ERR_NO_PART, + ERR_NUMBER_PARSING, + ERR_OUTSIDE_PART, + ERR_READ, + ERR_SYMLINK_LOOP, + ERR_UNRECOGNIZED, + ERR_WONT_FIT, + ERR_WRITE, + ERR_BAD_ARGUMENT, + ERR_UNALIGNED, + ERR_PRIVILEGED, + ERR_DEV_NEED_INIT, + ERR_NO_DISK_SPACE, + ERR_NUMBER_OVERFLOW, + + MAX_ERR_NUM +} grub_error_t; + +extern unsigned long install_partition; +extern unsigned long boot_drive; +extern unsigned long install_second_sector; +extern struct apm_info apm_bios_info; +extern unsigned long boot_part_addr; +extern int saved_entryno; +extern unsigned char force_lba; +extern char version_string[]; +extern char config_file[]; +extern unsigned long linux_text_len; +extern char *linux_data_tmp_addr; +extern char *linux_data_real_addr; + +#ifdef GRUB_UTIL +/* If not using config file, this variable is set to zero, + otherwise non-zero. */ +extern int use_config_file; +/* If using the preset menu, this variable is set to non-zero, + otherwise zero. */ +extern int use_preset_menu; +/* If not using curses, this variable is set to zero, otherwise non-zero. */ +extern int use_curses; +/* The flag for verbose messages. */ +extern int verbose; +/* The flag for read-only. */ +extern int read_only; +/* The number of floppies to be probed. */ +extern int floppy_disks; +/* The map between BIOS drives and UNIX device file names. */ +extern char **device_map; +/* The filename which stores the information about a device map. */ +extern char *device_map_file; +/* The array of geometries. */ +extern struct geometry *disks; +/* Assign DRIVE to a device name DEVICE. */ +extern void assign_device_name (int drive, const char *device); +#endif + +#ifndef STAGE1_5 +/* GUI interface variables. */ +extern int fallback_entry; +extern int default_entry; +extern int current_entryno; + +/* The constants for password types. */ +typedef enum +{ + PASSWORD_PLAIN, + PASSWORD_MD5, + PASSWORD_UNSUPPORTED +} +password_t; + +extern char *password; +extern password_t password_type; +extern int auth; +extern char commands[]; + +/* For `more'-like feature. */ +extern int max_lines; +extern int count_lines; +extern int use_pager; +#endif + +#ifndef NO_DECOMPRESSION +extern int no_decompression; +extern int compressed_file; +#endif + +/* instrumentation variables */ +extern void (*disk_read_hook) (int, int, int); +extern void (*disk_read_func) (int, int, int); + +#ifndef STAGE1_5 +/* The flag for debug mode. */ +extern int debug; +#endif /* STAGE1_5 */ + +extern unsigned long current_drive; +extern unsigned long current_partition; + +extern int fsys_type; + +/* The information for a disk geometry. The CHS information is only for + DOS/Partition table compatibility, and the real number of sectors is + stored in TOTAL_SECTORS. */ +struct geometry +{ + /* The number of cylinders */ + unsigned long cylinders; + /* The number of heads */ + unsigned long heads; + /* The number of sectors */ + unsigned long sectors; + /* The total number of sectors */ + unsigned long total_sectors; + /* Flags */ + unsigned long flags; +}; + +extern unsigned long part_start; +extern unsigned long part_length; + +extern int current_slice; + +extern int buf_drive; +extern int buf_track; +extern struct geometry buf_geom; + +/* these are the current file position and maximum file position */ +extern int filepos; +extern int filemax; + +/* + * Common BIOS/boot data. + */ + +extern struct multiboot_info mbi; +extern unsigned long saved_drive; +extern unsigned long saved_partition; +#ifndef STAGE1_5 +extern unsigned long saved_mem_upper; +extern unsigned long extended_memory; +#endif + +/* + * Error variables. + */ + +extern grub_error_t errnum; +extern char *err_list[]; + +/* Simplify declaration of entry_addr. */ +typedef void (*entry_func) (int, int, int, int, int, int) + __attribute__ ((noreturn)); + +extern entry_func entry_addr; + +/* Enter the stage1.5/stage2 C code after the stack is set up. */ +void cmain (void); + +/* Halt the processor (called after an unrecoverable error). */ +void stop (void) __attribute__ ((noreturn)); + +/* Reboot the system. */ +void grub_reboot (void) __attribute__ ((noreturn)); + +/* Halt the system, using APM if possible. If NO_APM is true, don't use + APM even if it is available. */ +void grub_halt (int no_apm) __attribute__ ((noreturn)); + +/* Copy MAP to the drive map and set up int13_handler. */ +void set_int13_handler (unsigned short *map); + +/* Set up int15_handler. */ +void set_int15_handler (void); + +/* Restore the original int15 handler. */ +void unset_int15_handler (void); + +/* Track the int13 handler to probe I/O address space. */ +void track_int13 (int drive); + +/* The key map. */ +extern unsigned short bios_key_map[]; +extern unsigned short ascii_key_map[]; +extern unsigned short io_map[]; + +/* calls for direct boot-loader chaining */ +void chain_stage1 (unsigned long segment, unsigned long offset, + unsigned long part_table_addr) + __attribute__ ((noreturn)); +void chain_stage2 (unsigned long segment, unsigned long offset, + int second_sector) + __attribute__ ((noreturn)); + +/* do some funky stuff, then boot linux */ +void linux_boot (void) __attribute__ ((noreturn)); + +/* do some funky stuff, then boot bzImage linux */ +void big_linux_boot (void) __attribute__ ((noreturn)); + +/* booting a multiboot executable */ +void multi_boot (int start, int mb_info) __attribute__ ((noreturn)); + +/* If LINEAR is nonzero, then set the Intel processor to linear mode. + Otherwise, bit 20 of all memory accesses is always forced to zero, + causing a wraparound effect for bugwards compatibility with the + 8086 CPU. */ +void gateA20 (int linear); + +/* memory probe routines */ +int get_memsize (int type); +int get_eisamemsize (void); + +/* Fetch the next entry in the memory map and return the continuation + value. DESC is a pointer to the descriptor buffer, and CONT is the + previous continuation value (0 to get the first entry in the + map). */ +int get_mmap_entry (struct mmar_desc *desc, int cont); + +/* Get the linear address of a ROM configuration table. Return zero, + if fails. */ +unsigned long get_rom_config_table (void); + +/* Get APM BIOS information. */ +void get_apm_info (void); + +/* Get VBE controller information. */ +int get_vbe_controller_info (struct vbe_controller *controller); + +/* Get VBE mode information. */ +int get_vbe_mode_info (int mode_number, struct vbe_mode *mode); + +/* Set VBE mode. */ +int set_vbe_mode (int mode_number); + +/* Return the data area immediately following our code. */ +int get_code_end (void); + +/* low-level timing info */ +int getrtsecs (void); +int currticks (void); + +/* Clear the screen. */ +void cls (void); + +/* Turn on/off cursor. */ +int setcursor (int on); + +/* Get the current cursor position (where 0,0 is the top left hand + corner of the screen). Returns packed values, (RET >> 8) is x, + (RET & 0xff) is y. */ +int getxy (void); + +/* Set the cursor position. */ +void gotoxy (int x, int y); + +/* Displays an ASCII character. IBM displays will translate some + characters to special graphical ones (see the DISP_* constants). */ +void grub_putchar (int c); + +/* Wait for a keypress, and return its packed BIOS/ASCII key code. + Use ASCII_CHAR(ret) to extract the ASCII code. */ +int getkey (void); + +/* Like GETKEY, but doesn't block, and returns -1 if no keystroke is + available. */ +int checkkey (void); + +/* Low-level disk I/O */ +int get_diskinfo (int drive, struct geometry *geometry); +int biosdisk (int subfunc, int drive, struct geometry *geometry, + int sector, int nsec, int segment); +void stop_floppy (void); + +/* Command-line interface functions. */ +#ifndef STAGE1_5 + +/* The flags for the builtins. */ +#define BUILTIN_CMDLINE 0x1 /* Run in the command-line. */ +#define BUILTIN_MENU 0x2 /* Run in the menu. */ +#define BUILTIN_TITLE 0x4 /* Only for the command title. */ +#define BUILTIN_SCRIPT 0x8 /* Run in the script. */ +#define BUILTIN_NO_ECHO 0x10 /* Don't print command on booting. */ +#define BUILTIN_HELP_LIST 0x20 /* Show help in listing. */ + +/* The table for a builtin. */ +struct builtin +{ + /* The command name. */ + char *name; + /* The callback function. */ + int (*func) (char *, int); + /* The combination of the flags defined above. */ + int flags; + /* The short version of the documentation. */ + char *short_doc; + /* The long version of the documentation. */ + char *long_doc; +}; + +/* All the builtins are registered in this. */ +extern struct builtin *builtin_table[]; + +/* The constants for kernel types. */ +typedef enum +{ + KERNEL_TYPE_NONE, /* None is loaded. */ + KERNEL_TYPE_MULTIBOOT, /* Multiboot. */ + KERNEL_TYPE_LINUX, /* Linux. */ + KERNEL_TYPE_BIG_LINUX, /* Big Linux. */ + KERNEL_TYPE_FREEBSD, /* FreeBSD. */ + KERNEL_TYPE_NETBSD, /* NetBSD. */ + KERNEL_TYPE_CHAINLOADER /* Chainloader. */ +} +kernel_t; + +extern kernel_t kernel_type; +extern int show_menu; +extern int grub_timeout; + +void init_builtins (void); +void init_config (void); +char *skip_to (int after_equal, char *cmdline); +struct builtin *find_command (char *command); +void print_cmdline_message (int forever); +void enter_cmdline (char *heap, int forever); +int run_script (char *script, char *heap); +#endif + +/* C library replacement functions with identical semantics. */ +void grub_printf (const char *format,...); +int grub_sprintf (char *buffer, const char *format, ...); +int grub_tolower (int c); +int grub_isspace (int c); +int grub_strncat (char *s1, const char *s2, int n); +void *grub_memmove (void *to, const void *from, int len); +void *grub_memset (void *start, int c, int len); +int grub_strncat (char *s1, const char *s2, int n); +char *grub_strstr (const char *s1, const char *s2); +int grub_memcmp (const char *s1, const char *s2, int n); +int grub_strcmp (const char *s1, const char *s2); +int grub_strlen (const char *str); +char *grub_strcpy (char *dest, const char *src); + +#ifndef GRUB_UTIL +typedef unsigned long grub_jmp_buf[6]; +#else +/* In the grub shell, use the libc jmp_buf instead. */ +# include +# define grub_jmp_buf jmp_buf +#endif + +#ifdef GRUB_UTIL +# define grub_setjmp setjmp +# define grub_longjmp longjmp +#else /* ! GRUB_UTIL */ +int grub_setjmp (grub_jmp_buf env); +void grub_longjmp (grub_jmp_buf env, int val); +#endif /* ! GRUB_UTIL */ + +/* The environment for restarting Stage 2. */ +extern grub_jmp_buf restart_env; +/* The environment for restarting the command-line interface. */ +extern grub_jmp_buf restart_cmdline_env; + +/* misc */ +void init_page (void); +void print_error (void); +char *convert_to_ascii (char *buf, int c, ...); +int get_cmdline (char *prompt, char *cmdline, int maxlen, + int echo_char, int history); +int substring (const char *s1, const char *s2); +int nul_terminate (char *str); +int get_based_digit (int c, int base); +int safe_parse_maxint (char **str_ptr, int *myint_ptr); +int memcheck (int start, int len); +void grub_putstr (const char *str); + +#ifndef NO_DECOMPRESSION +/* Compression support. */ +int gunzip_test_header (void); +int gunzip_read (char *buf, int len); +#endif /* NO_DECOMPRESSION */ + +int rawread (int drive, int sector, int byte_offset, int byte_len, char *buf); +int devread (int sector, int byte_offset, int byte_len, char *buf); +int rawwrite (int drive, int sector, char *buf); +int devwrite (int sector, int sector_len, char *buf); + +/* Parse a device string and initialize the global parameters. */ +char *set_device (char *device); +int open_device (void); +int real_open_partition (int flags); +int open_partition (void); +int next_partition (unsigned long drive, unsigned long dest, + unsigned long *partition, int *type, + unsigned long *start, unsigned long *len, + unsigned long *offset, int *entry, + unsigned long *ext_offset, char *buf); + +/* Sets device to the one represented by the SAVED_* parameters. */ +int make_saved_active (void); + +/* Set or clear the current root partition's hidden flag. */ +int set_partition_hidden_flag (int hidden); + +/* Open a file or directory on the active device, using GRUB's + internal filesystem support. */ +int grub_open (char *filename); + +/* Read LEN bytes into BUF from the file that was opened with + GRUB_OPEN. If LEN is -1, read all the remaining data in the file. */ +int grub_read (char *buf, int len); + +/* Reposition a file offset. */ +int grub_seek (int offset); + +/* Close a file. */ +void grub_close (void); + +/* List the contents of the directory that was opened with GRUB_OPEN, + printing all completions. */ +int dir (char *dirname); + +int set_bootdev (int hdbias); + +/* Display statistics on the current active device. */ +void print_fsys_type (void); + +/* Display device and filename completions. */ +void print_a_completion (char *filename); +int print_completions (int is_filename, int is_completion); + +/* Copies the current partition data to the desired address. */ +void copy_current_part_entry (char *buf); + +#ifndef STAGE1_5 +void bsd_boot (kernel_t type, int bootdev, char *arg) + __attribute__ ((noreturn)); + +/* Define flags for load_image here. */ +/* Don't pass a Linux's mem option automatically. */ +#define KERNEL_LOAD_NO_MEM_OPTION (1 << 0) + +kernel_t load_image (char *kernel, char *arg, kernel_t suggested_type, + unsigned long load_flags); + +int load_module (char *module, char *arg); +int load_initrd (char *initrd); + +int check_password(char *entered, char* expected, password_t type); +#endif + +void init_bios_info (void); + +#endif /* ASM_FILE */ + +#endif /* ! GRUB_SHARED_HEADER */ diff -Naur grub-0.95-orig/stage2/stage2.c grub-0.95/stage2/stage2.c --- grub-0.95-orig/stage2/stage2.c 2003-07-09 13:45:53.000000000 +0200 +++ grub-0.95/stage2/stage2.c 2004-02-15 11:20:57.763015040 +0100 @@ -233,6 +233,7 @@ { int c, time1, time2 = -1, first_entry = 0; char *cur_entry = 0; + struct term_entry *prev_term = NULL; /* * Main loop for menu UI. @@ -714,6 +715,15 @@ cls (); setcursor (1); + /* if our terminal needed initialization, we should shut it down + * before booting the kernel, but we want to save what it was so + * we can come back if needed */ + prev_term = current_term; + if (current_term->shutdown) + { + (*current_term->shutdown)(); + current_term = term_table; /* assumption: console is first */ + } while (1) { @@ -748,6 +758,13 @@ break; } + /* if we get back here, we should go back to what our term was before */ + current_term = prev_term; + if (current_term->startup) + /* if our terminal fails to initialize, fall back to console since + * it should always work */ + if ((*current_term->startup)() == 0) + current_term = term_table; /* we know that console is first */ show_menu = 1; goto restart; } @@ -1049,6 +1066,10 @@ while (is_preset); } + /* go ahead and make sure the terminal is setup */ + if (current_term->startup) + (*current_term->startup)(); + if (! num_entries) { /* If no acceptable config file, goto command-line, starting diff -Naur grub-0.95-orig/stage2/term.h grub-0.95/stage2/term.h --- grub-0.95-orig/stage2/term.h 2003-07-09 13:45:53.000000000 +0200 +++ grub-0.95/stage2/term.h 2004-02-15 11:20:57.765014736 +0100 @@ -60,6 +60,8 @@ const char *name; /* The feature flags defined above. */ unsigned long flags; + /* Default for maximum number of lines if not specified */ + unsigned short max_lines; /* Put a character. */ void (*putchar) (int c); /* Check if any input character is available. */ @@ -79,6 +81,11 @@ void (*setcolor) (int normal_color, int highlight_color); /* Turn on/off the cursor. */ int (*setcursor) (int on); + + /* function to start a terminal */ + int (*startup) (void); + /* function to use to shutdown a terminal */ + void (*shutdown) (void); }; /* This lists up available terminals. */ @@ -124,4 +131,23 @@ int hercules_setcursor (int on); #endif +#ifdef SUPPORT_GRAPHICS +extern int foreground, background, border, graphics_inited; + +void graphics_set_splash(char *splashfile); +int set_videomode (int mode); +void graphics_putchar (int c); +int graphics_getxy(void); +void graphics_gotoxy(int x, int y); +void graphics_cls(void); +void graphics_setcolorstate (color_state state); +void graphics_setcolor (int normal_color, int highlight_color); +void graphics_setcursor (int on); +int graphics_init(void); +void graphics_end(void); + +int hex(int v); +void graphics_set_palette(int idx, int red, int green, int blue); +#endif /* SUPPORT_GRAPHICS */ + #endif /* ! GRUB_TERM_HEADER */