This patch provides the splashimage feature for GRUB. The patch was taken from the debian grub-0.97-29 release, which was originally from Mandriva and improved by debian. It also includes the xpmjunk.patch from fedora and the splashimage help from graphics-chainboot_info.patch from Mandriva All were re-diffed for application after previous patches by Gilbert Ashley diff -Naur grub-0.97.orig/configure.ac grub-0.97/configure.ac --- grub-0.97.orig/configure.ac 2005-05-07 23:36:03.000000000 -0300 +++ grub-0.97/configure.ac 2005-06-12 20:56:49.000000000 -0300 @@ -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.97.orig/stage2/asm.S grub-0.97/stage2/asm.S --- grub-0.97.orig/stage2/asm.S 2004-06-19 13:55:22.000000000 -0300 +++ grub-0.97/stage2/asm.S 2005-06-13 14:05:31.000000000 -0300 @@ -2216,7 +2216,304 @@ 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 + + +/* + * set_int1c_handler(void) + */ +ENTRY(set_int1c_handler) + pushl %edi + + /* save the original int1c handler */ + movl $0x70, %edi + movw (%edi), %ax + movw %ax, ABS(int1c_offset) + movw 2(%edi), %ax + movw %ax, ABS(int1c_segment) + + /* save the new int1c handler */ + movw $ABS(int1c_handler), %ax + movw %ax, (%edi) + xorw %ax, %ax + movw %ax, 2(%edi) + + popl %edi + ret + + +/* + * unset_int1c_handler(void) + */ +ENTRY(unset_int1c_handler) + pushl %edi + + /* check if int1c_handler is set */ + movl $0x70, %edi + movw $ABS(int1c_handler), %ax + cmpw %ax, (%edi) + jne int1c_1 + xorw %ax, %ax + cmpw %ax, 2(%edi) + jne int1c_1 + + /* restore the original */ + movw ABS(int1c_offset), %ax + movw %ax, (%edi) + movw ABS(int1c_segment), %ax + movw %ax, 2(%edi) + +int1c_1: + popl %edi + ret + + +/* + * blinks graphics cursor + */ + .code16 +write_data: + movw $0, %ax + movw %ax, %ds + + mov $0xA000, %ax /* video in es:di */ + mov %ax, %es + mov $80, %ax + movw $ABS(cursorY), %si + mov %ds:(%si), %bx + mul %bx + movw $ABS(cursorX), %si + mov %ds:(%si), %bx + shr $3, %bx /* %bx /= 8 */ + add %bx, %ax + mov %ax, %di + + movw $ABS(cursorBuf), %si /* fontBuf in ds:si */ + + /* prepare for data moving */ + mov $16, %dx /* altura da fonte */ + mov $80, %bx /* bytes por linha */ + +write_loop: + movb %ds:(%si), %al + xorb $0xff, %al + movb %al, %ds:(%si) /* invert cursorBuf */ + movb %al, %es:(%di) /* write to video */ + add %bx, %di + inc %si + dec %dx + jg write_loop + ret + +int1c_handler: + pusha + mov $0, %ax + mov %ax, %ds + mov $ABS(cursorCount), %si + mov %ds:(%si), %ax + inc %ax + mov %ax, %ds:(%si) + cmp $9, %ax + jne int1c_done + + mov $0, %ax + mov %ax, %ds:(%si) + call write_data + +int1c_done: + popa + iret + /* call previous int1c handler */ + /* ljmp */ + .byte 0xea +int1c_offset: .word 0 +int1c_segment: .word 0 + .code32 + + +/* + * unsigned char set_videomode(unsigned char mode) + * BIOS call "INT 10H Function 0h" to set video mode + * Call with %ah = 0x0 + * %al = video mode + * Returns old videomode. + */ +ENTRY(set_videomode) + pushl %ebp + movl %esp,%ebp + pushl %ebx + pushl %ecx + + movb 8(%ebp), %cl + + call EXT_C(prot_to_real) + .code16 + + xorb %al, %al + 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 + + xorl %eax, %eax + movb %ch, %al + + popl %ecx + popl %ebx + popl %ebp + ret + + +/* + * int get_videomode() + * BIOS call "INT 10H Function 0Fh" to get current video mode + * Call with %al = 0x0 + * %ah = 0xF + * Returns current videomode. + */ +ENTRY(get_videomode) + pushl %ebp + movl %esp,%ebp + pushl %ebx + pushl %ecx + + call EXT_C(prot_to_real) + .code16 + + xorb %al, %al + movb $0xF, %ah + int $0x10 /* Get Current Video mode */ + movb %al, %cl /* For now we only want display mode */ + + DATA32 call EXT_C(real_to_prot) + .code32 + + xorl %eax, %eax + movb %cl, %al + + popl %ecx + popl %ebx + popl %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() * if a seconds value can be read, read it and return it (BCD), diff -Naur grub-0.97.orig/stage2/builtins.c grub-0.97/stage2/builtins.c --- grub-0.97.orig/stage2/builtins.c 2005-02-15 19:58:23.000000000 -0200 +++ grub-0.97/stage2/builtins.c 2005-06-13 18:44:03.000000000 -0300 @@ -28,6 +28,10 @@ #include #include +#ifdef SUPPORT_GRAPHICS +# include +#endif + #ifdef SUPPORT_NETBOOT # define GRUB 1 # include @@ -237,12 +241,22 @@ static int boot_func (char *arg, int flags) { + struct term_entry *prev_term = current_term; /* Clear the int15 handler if we can boot the kernel successfully. This assumes that the boot code never fails only if KERNEL_TYPE is not KERNEL_TYPE_NONE. Is this assumption is bad? */ if (kernel_type != KERNEL_TYPE_NONE) unset_int15_handler (); + /* 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 */ + if (current_term->shutdown) + { + current_term->shutdown(); + current_term = term_table; /* assumption: console is first */ + } + #ifdef SUPPORT_NETBOOT /* Shut down the networking. */ cleanup_net (); @@ -306,6 +320,13 @@ return 1; } + /* 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 */ return 0; } @@ -852,6 +873,251 @@ }; #endif /* SUPPORT_NETBOOT */ +#ifdef SUPPORT_GRAPHICS + +static int splashimage_func(char *arg, int flags) { + int i; + + /* filename can only be 256 characters due to our buffer size */ + if (grub_strlen(arg) > 256) { + grub_printf("Splash image filename too large\n"); + grub_printf("Press any key to continue..."); + getkey(); + return 1; + } + + /* 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(arg); + + if (flags == BUILTIN_CMDLINE && graphics_inited) { + graphics_end(); + if (graphics_init() == 0) { + /* Fallback to default term */ + current_term = term_table; + max_lines = current_term->max_lines; + if (current_term->cls) + current_term->cls(); + grub_printf("Failed to set splash image and/or graphics mode\n"); + return 1; + } + graphics_cls(); + } + + if (flags == BUILTIN_MENU) + current_term = term_table + i; + + 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." +}; + + +/* shade */ +static int +shade_func(char *arg, int flags) +{ + int new_shade; + + if (!arg || safe_parse_maxint(&arg, &new_shade) == 0) + return (1); + + if (shade != new_shade) { + shade = new_shade; + if (flags == BUILTIN_CMDLINE && graphics_inited) { + graphics_end(); + graphics_init(); + graphics_cls(); + } + } + + return 0; +} + +static struct builtin builtin_shade = +{ + "shade", + shade_func, + BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, + "shade INTEGER", + "If set to 0, disables the use of shaded text, else enables it." +}; + + +/* 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." +}; + + +/* border */ +static int +border_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; + + window_border = (r << 16) | (g << 8) | b; + if (graphics_inited) + graphics_set_palette(0x11, r, g, b); + + return 0; + } + + return 1; +} + +static struct builtin builtin_border = +{ + "border", + border_func, + BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, + "border RRGGBB", + "Sets the border video color when in graphics mode." + "RR is red, GG is green, and BB blue. Numbers must be in hexadecimal." +}; + + +/* viewport */ +static int +viewport_func (char *arg, int flags) +{ + int i; + int x0 = 0, y0 = 0, x1 = 80, y1 = 30; + int *pos[4] = { &x0, &y0, &x1, &y1 }; + + if (!arg) + return (1); + for (i = 0; i < 4; i++) { + if (!*arg) + return (1); + while (*arg && (*arg == ' ' || *arg == '\t')) + ++arg; + if (!safe_parse_maxint(&arg, pos[i])) + return (1); + while (*arg && (*arg != ' ' && *arg != '\t')) + ++arg; + } + + /* minimum size is 65 colums and 16 rows */ + if (x0 > x1 - 66 || y0 > y1 - 16 || x0 < 0 || y0 < 0 || x1 > 80 || y1 > 30) + return 1; + + view_x0 = x0; + view_y0 = y0; + view_x1 = x1; + view_y1 = y1; + + if (flags == BUILTIN_CMDLINE && graphics_inited) { + graphics_end(); + graphics_init(); + graphics_cls(); + } + + return 0; +} + +static struct builtin builtin_viewport = +{ + "viewport", + viewport_func, + BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, + "viewport x0 y0 x1 y1", + "Changes grub internals to output text in the window defined by" + " four parameters. The x and y parameters are 0 based. This option" + " only works with the graphics interface." +}; + +#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 @@ -1454,14 +1720,20 @@ /* help */ -#define MAX_SHORT_DOC_LEN 39 -#define MAX_LONG_DOC_LEN 66 - static int help_func (char *arg, int flags) { - int all = 0; - + int all = 0, max_short_doc_len, max_long_doc_len; + max_short_doc_len = 39; + max_long_doc_len = 66; +#ifdef SUPPORT_GRAPHICS + if (grub_memcmp (current_term->name, "graphics", sizeof ("graphics") - 1) == 0) + { + max_short_doc_len = (view_x1 - view_x0 + 1) / 2 - 1; + max_long_doc_len = (view_x1 - view_x0) - 14; + } +#endif + if (grub_memcmp (arg, "--all", sizeof ("--all") - 1) == 0) { all = 1; @@ -1491,13 +1763,13 @@ len = grub_strlen ((*builtin)->short_doc); /* If the length of SHORT_DOC is too long, truncate it. */ - if (len > MAX_SHORT_DOC_LEN - 1) - len = MAX_SHORT_DOC_LEN - 1; + if (len > max_short_doc_len - 1) + len = max_short_doc_len - 1; for (i = 0; i < len; i++) grub_putchar ((*builtin)->short_doc[i]); - for (; i < MAX_SHORT_DOC_LEN; i++) + for (; i < max_short_doc_len; i++) grub_putchar (' '); if (! left) @@ -1546,10 +1818,10 @@ int i; /* If LEN is too long, fold DOC. */ - if (len > MAX_LONG_DOC_LEN) + if (len > max_long_doc_len) { /* Fold this line at the position of a space. */ - for (len = MAX_LONG_DOC_LEN; len > 0; len--) + for (len = max_long_doc_len; len > 0; len--) if (doc[len - 1] == ' ') break; } @@ -4085,7 +4357,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) @@ -4244,17 +4516,29 @@ 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) { + /* If startup fails, return to previous term */ + if (current_term->startup() == 0) { + current_term = prev_term; + max_lines = current_term->max_lines; + if (current_term->cls) { + current_term->cls(); + } + } + } grub_longjmp (restart_cmdline_env, 0); + } return 0; } @@ -4264,7 +4548,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" @@ -4276,7 +4560,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 @@ -4795,13 +5079,20 @@ /* 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 &builtin_bootp, #endif /* SUPPORT_NETBOOT */ +#ifdef SUPPORT_GRAPHICS + &builtin_border, +#endif &builtin_cat, &builtin_chainloader, + &builtin_clear, &builtin_cmp, &builtin_color, &builtin_configfile, @@ -4821,6 +5112,9 @@ &builtin_embed, &builtin_fallback, &builtin_find, +#ifdef SUPPORT_GRAPHICS + &builtin_foreground, +#endif &builtin_fstest, &builtin_geometry, &builtin_halt, @@ -4864,9 +5158,13 @@ #endif /* SUPPORT_SERIAL */ &builtin_setkey, &builtin_setup, -#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) +#ifdef SUPPORT_GRAPHICS + &builtin_shade, + &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 */ @@ -4880,5 +5178,8 @@ &builtin_unhide, &builtin_uppermem, &builtin_vbeprobe, +#ifdef SUPPORT_GRAPHICS + &builtin_viewport, +#endif 0 }; diff -Naur grub-0.97.orig/stage2/char_io.c grub-0.97/stage2/char_io.c --- grub-0.97.orig/stage2/char_io.c 2005-02-01 18:51:23.000000000 -0200 +++ grub-0.97/stage2/char_io.c 2005-06-12 20:56:49.000000000 -0300 @@ -29,12 +29,17 @@ # include #endif +#ifdef SUPPORT_GRAPHICS +# include +#endif + #ifndef STAGE1_5 struct term_entry term_table[] = { { "console", 0, + 24, console_putchar, console_checkkey, console_getkey, @@ -43,13 +48,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 +66,8 @@ serial_cls, serial_setcolorstate, 0, + 0, + 0, 0 }, #endif /* SUPPORT_SERIAL */ @@ -65,6 +75,7 @@ { "hercules", 0, + 24, hercules_putchar, console_checkkey, console_getkey, @@ -73,11 +84,30 @@ 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 } + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; /* This must be console. */ @@ -305,9 +335,10 @@ /* XXX: These should be defined in shared.h, but I leave these here, until this code is freezed. */ -#define CMDLINE_WIDTH 78 #define CMDLINE_MARGIN 10 - + + /* command-line limits */ + int cmdline_width = 78, col_start = 0; int xpos, lpos, c, section; /* The length of PROMPT. */ int plen; @@ -338,7 +369,7 @@ /* If the cursor is in the first section, display the first section instead of the second. */ - if (section == 1 && plen + lpos < CMDLINE_WIDTH) + if (section == 1 && plen + lpos < cmdline_width) cl_refresh (1, 0); else if (xpos - count < 1) cl_refresh (1, 0); @@ -354,7 +385,7 @@ grub_putchar ('\b'); } else - gotoxy (xpos, getxy () & 0xFF); + gotoxy (xpos + col_start, getxy () & 0xFF); } } @@ -364,7 +395,7 @@ lpos += count; /* If the cursor goes outside, scroll the screen to the right. */ - if (xpos + count >= CMDLINE_WIDTH) + if (xpos + count >= cmdline_width) cl_refresh (1, 0); else { @@ -383,7 +414,7 @@ } } else - gotoxy (xpos, getxy () & 0xFF); + gotoxy (xpos + col_start, getxy () & 0xFF); } } @@ -398,14 +429,14 @@ if (full) { /* Recompute the section number. */ - if (lpos + plen < CMDLINE_WIDTH) + if (lpos + plen < cmdline_width) section = 0; else - section = ((lpos + plen - CMDLINE_WIDTH) - / (CMDLINE_WIDTH - 1 - CMDLINE_MARGIN) + 1); + section = ((lpos + plen - cmdline_width) + / (cmdline_width - 1 - CMDLINE_MARGIN) + 1); /* From the start to the end. */ - len = CMDLINE_WIDTH; + len = cmdline_width; pos = 0; grub_putchar ('\r'); @@ -445,8 +476,8 @@ if (! full) offset = xpos - 1; - start = ((section - 1) * (CMDLINE_WIDTH - 1 - CMDLINE_MARGIN) - + CMDLINE_WIDTH - plen - CMDLINE_MARGIN); + start = ((section - 1) * (cmdline_width - 1 - CMDLINE_MARGIN) + + cmdline_width - plen - CMDLINE_MARGIN); xpos = lpos + 1 - start; start += offset; } @@ -471,7 +502,7 @@ /* If the cursor is at the last position, put `>' or a space, depending on if there are more characters in BUF. */ - if (pos == CMDLINE_WIDTH) + if (pos == cmdline_width) { if (start + len < llen) grub_putchar ('>'); @@ -488,7 +519,7 @@ grub_putchar ('\b'); } else - gotoxy (xpos, getxy () & 0xFF); + gotoxy (xpos + col_start, getxy () & 0xFF); } /* Initialize the command-line. */ @@ -518,10 +549,10 @@ llen += l; lpos += l; - if (xpos + l >= CMDLINE_WIDTH) + if (xpos + l >= cmdline_width) cl_refresh (1, 0); - else if (xpos + l + llen - lpos > CMDLINE_WIDTH) - cl_refresh (0, CMDLINE_WIDTH - xpos); + else if (xpos + l + llen - lpos > cmdline_width) + cl_refresh (0, cmdline_width - xpos); else cl_refresh (0, l + llen - lpos); } @@ -533,12 +564,22 @@ grub_memmove (buf + lpos, buf + lpos + count, llen - count + 1); llen -= count; - if (xpos + llen + count - lpos > CMDLINE_WIDTH) - cl_refresh (0, CMDLINE_WIDTH - xpos); + if (xpos + llen + count - lpos > cmdline_width) + cl_refresh (0, cmdline_width - xpos); else cl_refresh (0, llen + count - lpos); } + max_lines = current_term->max_lines; +#ifdef SUPPORT_GRAPHICS + if (grub_memcmp (current_term->name, "graphics", sizeof ("graphics") - 1) == 0) + { + cmdline_width = (view_x1 - view_x0) - 2; + col_start = view_x0; + max_lines = view_y1 - view_y0; + } +#endif + plen = grub_strlen (prompt); llen = grub_strlen (cmdline); @@ -1006,6 +1047,48 @@ } #endif /* ! STAGE1_5 */ +#ifndef STAGE1_5 +/* Internal pager. */ +int +do_more (void) +{ + if (count_lines >= 0) + { + count_lines++; + if (count_lines >= max_lines - 2) + { + int tmp; + + /* It's important to disable the feature temporarily, because + 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 ("[Hit return to continue]"); + + if (current_term->setcolorstate) + current_term->setcolorstate (COLOR_STATE_NORMAL); + + + do + { + tmp = ASCII_CHAR (getkey ()); + } + while (tmp != '\n' && tmp != '\r'); + grub_printf ("\r \r"); + + /* Restart to count lines. */ + count_lines = 0; + return 1; + } + } + return 0; +} +#endif + /* Display an ASCII character. */ void grub_putchar (int c) @@ -1034,38 +1117,11 @@ if (c == '\n') { + int flag; /* Internal `more'-like feature. */ - if (count_lines >= 0) - { - count_lines++; - if (count_lines >= max_lines - 2) - { - int tmp; - - /* It's important to disable the feature temporarily, because - the following grub_printf call will print newlines. */ - count_lines = -1; - - if (current_term->setcolorstate) - current_term->setcolorstate (COLOR_STATE_HIGHLIGHT); - - grub_printf ("\n[Hit return to continue]"); - - if (current_term->setcolorstate) - current_term->setcolorstate (COLOR_STATE_NORMAL); - - do - { - tmp = ASCII_CHAR (getkey ()); - } - while (tmp != '\n' && tmp != '\r'); - grub_printf ("\r \r"); - - /* Restart to count lines. */ - count_lines = 0; - return; - } - } + flag = do_more (); + if (flag) + return; } current_term->putchar (c); @@ -1090,7 +1146,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 (); @@ -1217,6 +1273,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.97.orig/stage2/cmdline.c grub-0.97/stage2/cmdline.c --- grub-0.97.orig/stage2/cmdline.c 2004-08-16 20:23:01.000000000 -0300 +++ grub-0.97/stage2/cmdline.c 2005-06-12 20:56:49.000000000 -0300 @@ -50,10 +50,11 @@ void print_cmdline_message (int forever) { - printf (" [ Minimal BASH-like line editing is supported. For the first word, TAB\n" - " lists possible command completions. Anywhere else TAB lists the possible\n" - " completions of a device/filename.%s ]\n", - (forever ? "" : " ESC at any time exits.")); + grub_printf(" [ Minimal BASH-like line editing is supported. For\n" + " the first word, TAB lists possible command\n" + " completions. Anywhere else TAB lists the possible\n" + " completions of a device/filename.%s ]\n", + (forever ? "" : " ESC at any time\n exits.")); } /* Find the builtin whose command name is COMMAND and return the diff -Naur grub-0.97.orig/stage2/graphics.c grub-0.97/stage2/graphics.c --- grub-0.97.orig/stage2/graphics.c 1969-12-31 21:00:00.000000000 -0300 +++ grub-0.97/stage2/graphics.c 2005-06-13 19:13:31.000000000 -0300 @@ -0,0 +1,585 @@ +/* + * 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 + * Options and enhancements made by Herton Ronaldo Krzesinski + * + * + * 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[256]; + +int shade = 1, no_cursor = 0; + +#define VSHADOW VSHADOW1 +unsigned char VSHADOW1[38400]; +unsigned char VSHADOW2[38400]; +unsigned char VSHADOW4[38400]; +unsigned char VSHADOW8[38400]; + +/* define the default viewable area */ +int view_x0 = 0; +int view_y0 = 0; +int view_x1 = 80; +int view_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]; + +/* graphics options */ +int foreground = (63 << 16) | (63 << 8) | (63), background = 0, window_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; + +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); +} + +/* move the graphics cursor location to col, row */ +static void graphics_setxy(int col, int row) { + if (col >= view_x0 && col < view_x1) { + fontx = col; + cursorX = col << 3; + } + if (row >= view_y0 && row < view_y1) { + fonty = row; + cursorY = row << 4; + } +} + +/* scroll the screen */ +static void graphics_scroll() { + int i, j, k; + + /* we don't want to scroll recursively... that would be bad */ + if (no_scroll) + return; + no_scroll = 1; + + /* disable pager temporarily */ + k = count_lines; + count_lines = -1; + + /* move everything up a line */ + for (j = view_y0 + 1; j < view_y1; j++) { + graphics_gotoxy(view_x0, j - 1); + for (i = view_x0; i < view_x1; i++) { + graphics_putchar(text[j * 80 + i]); + } + } + + /* last line should be blank */ + graphics_gotoxy(view_x0, view_y1 - 1); + for (i = view_x0; i < view_x1; i++) + graphics_putchar(' '); + graphics_setxy(view_x0, view_y1 - 1); + + count_lines = k; + + no_scroll = 0; +} + +/* 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. The mode initiated is 12h. From "Ralf Brown's Interrupt List": + * text/ text pixel pixel colors disply scrn system + * grph resol box resolution pages addr + * 12h G 80x30 8x16 640x480 16/256K . A000 VGA,ATI VIP + * G 80x30 8x16 640x480 16/64 . A000 ATI EGA Wonder + * G . . 640x480 16 . . UltraVision+256K EGA + */ +int graphics_init() +{ + if (!graphics_inited) { + saved_videomode = set_videomode(0x12); + if (get_videomode() != 0x12) { + set_videomode(saved_videomode); + return 0; + } + graphics_inited = 1; + } + else + return 1; + + font8x16 = (unsigned char*)graphics_get_font(); + + /* make sure that the highlight color is set correctly */ + graphics_highlight_color = ((graphics_normal_color >> 4) | + ((graphics_normal_color & 0xf) << 4)); + + graphics_cls(); + + if (!read_image(splashimage)) { + grub_printf("Failed to read splash image (%s)\n", splashimage); + grub_printf("Press any key to continue..."); + getkey(); + set_videomode(saved_videomode); + graphics_inited = 0; + return 0; + } + + set_int1c_handler(); + + return 1; +} + +/* Leave graphics mode */ +void graphics_end(void) +{ + if (graphics_inited) { + unset_int1c_handler(); + set_videomode(saved_videomode); + graphics_inited = 0; + no_cursor = 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 < view_y1) + graphics_setxy(fontx, fonty + 1); + else + graphics_scroll(); + graphics_cursor(1); + return; + } else if (ch == '\r') { + graphics_setxy(view_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) >= view_x1) { + graphics_setxy(view_x0, fonty); + if (fonty + 1 < view_y1) + graphics_setxy(view_x0, fonty + 1); + else + graphics_scroll(); + graphics_cursor(1); + do_more (); + graphics_cursor(0); + } 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(view_x0, view_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); + + /* plane 1 */ + MapMask(1); + grub_memcpy(mem, s1, 38400); + + /* plane 2 */ + MapMask(2); + grub_memcpy(mem, s2, 38400); + + /* plane 3 */ + MapMask(4); + grub_memcpy(mem, s4, 38400); + + /* plane 4 */ + MapMask(8); + grub_memcpy(mem, s8, 38400); + + MapMask(15); + + if (no_cursor) { + no_cursor = 0; + set_int1c_handler(); + } +} + +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); +} + +int graphics_setcursor (int on) { + if (!no_cursor && !on) { + no_cursor = 1; + unset_int1c_handler(); + graphics_cursor(0); + } + else if(no_cursor && on) { + no_cursor = 0; + set_int1c_handler(); + graphics_cursor(1); + } + return 0; +} + +/* 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], c; + unsigned char 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, (window_border >> 16), (window_border >> 8) & 63, + window_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'); +} + +void graphics_cursor(int set) { + unsigned char *pat, *mem, *ptr, chr[16 << 2]; + int i, ch, invert, offset; + + if (set && (no_cursor || 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]; + + if (shade) { + 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.97.orig/stage2/graphics.h grub-0.97/stage2/graphics.h --- grub-0.97.orig/stage2/graphics.h 1969-12-31 21:00:00.000000000 -0300 +++ grub-0.97/stage2/graphics.h 2005-06-12 20:56:49.000000000 -0300 @@ -0,0 +1,44 @@ +/* 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]; +extern int shade; +extern int view_x0, view_y0, view_x1, view_y1; + +#endif /* GRAPHICS_H */ diff -Naur grub-0.97.orig/stage2/Makefile.am grub-0.97/stage2/Makefile.am --- grub-0.97.orig/stage2/Makefile.am 2005-02-02 18:37:35.000000000 -0200 +++ grub-0.97/stage2/Makefile.am 2005-06-12 20:56:49.000000000 -0300 @@ -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 \ @@ -79,8 +79,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 @@ -90,7 +96,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.97.orig/stage2/shared.h grub-0.97/stage2/shared.h --- grub-0.97.orig/stage2/shared.h 2004-06-19 13:40:09.000000000 -0300 +++ grub-0.97/stage2/shared.h 2005-06-12 20:56:49.000000000 -0300 @@ -796,6 +796,11 @@ /* Set the cursor position. */ void gotoxy (int x, int y); +/* Internal pager + Returns 1 = if pager was used + 0 = if pager wasn't used */ +int do_more (void); + /* Displays an ASCII character. IBM displays will translate some characters to special graphical ones (see the DISP_* constants). */ void grub_putchar (int c); @@ -875,6 +881,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.97.orig/stage2/stage2.c grub-0.97/stage2/stage2.c --- grub-0.97.orig/stage2/stage2.c 2005-03-19 14:51:57.000000000 -0300 +++ grub-0.97/stage2/stage2.c 2005-06-13 22:38:08.000000000 -0300 @@ -20,6 +20,12 @@ #include #include +#ifdef SUPPORT_GRAPHICS +# include +#endif + +int col_start, col_end, row_start, box_size; + grub_jmp_buf restart_env; #if defined(PRESET_MENU_STRING) || defined(SUPPORT_DISKLESS) @@ -105,13 +111,13 @@ if (highlight && current_term->setcolorstate) current_term->setcolorstate (COLOR_STATE_HIGHLIGHT); - gotoxy (2, y); + gotoxy (2 + col_start, y); grub_putchar (' '); - for (x = 3; x < 75; x++) + for (x = 3 + col_start; x < (col_end - 5); x++) { - if (*entry && x <= 72) + if (*entry && x <= (col_end - 8)) { - if (x == 72) + if (x == (col_end - 8)) grub_putchar (DISP_RIGHT); else grub_putchar (*entry++); @@ -119,7 +125,7 @@ else grub_putchar (' '); } - gotoxy (74, y); + gotoxy ((col_end - 6), y); if (current_term->setcolorstate) current_term->setcolorstate (COLOR_STATE_STANDARD); @@ -131,7 +137,7 @@ { int i; - gotoxy (77, y + 1); + gotoxy ((col_end - 3), y + 1); if (first) grub_putchar (DISP_UP); @@ -151,14 +157,14 @@ menu_entries++; } - gotoxy (77, y + size); + gotoxy ((col_end - 3), y + size); if (*menu_entries) grub_putchar (DISP_DOWN); else grub_putchar (' '); - gotoxy (74, y + entryno + 1); + gotoxy ((col_end - 6), y + entryno + 1); } static void @@ -196,30 +202,30 @@ if (current_term->setcolorstate) current_term->setcolorstate (COLOR_STATE_NORMAL); - gotoxy (1, y); + gotoxy (1 + col_start, y); grub_putchar (DISP_UL); - for (i = 0; i < 73; i++) + for (i = col_start; i < (col_end - 7); i++) grub_putchar (DISP_HORIZ); grub_putchar (DISP_UR); i = 1; while (1) { - gotoxy (1, y + i); + gotoxy (1 + col_start, y + i); if (i > size) break; grub_putchar (DISP_VERT); - gotoxy (75, y + i); + gotoxy ((col_end - 5), y + i); grub_putchar (DISP_VERT); i++; } grub_putchar (DISP_LL); - for (i = 0; i < 73; i++) + for (i = col_start; i < (col_end - 7); i++) grub_putchar (DISP_HORIZ); grub_putchar (DISP_LR); @@ -233,6 +239,7 @@ { int c, time1, time2 = -1, first_entry = 0; char *cur_entry = 0; + struct term_entry *prev_term = NULL; /* * Main loop for menu UI. @@ -250,6 +257,22 @@ } } + col_start = 0; + col_end = 80; + row_start = 0; + box_size = 12; + /* if we're using viewport we need to make sure to setup + coordinates correctly. */ +#ifdef SUPPORT_GRAPHICS + if (grub_memcmp (current_term->name, "graphics", sizeof ("graphics") - 1) == 0) + { + col_start = view_x0; + col_end = view_x1; + row_start = view_y0; + box_size = (view_y1 - view_y0) - 13; + } +#endif + /* If the timeout was expired or wasn't set, force to show the menu interface. */ if (grub_timeout < 0) @@ -302,36 +325,36 @@ if (current_term->flags & TERM_DUMB) print_entries_raw (num_entries, first_entry, menu_entries); else - print_border (3, 12); + print_border (3 + row_start, box_size); grub_printf ("\n\ - Use the %c and %c keys to select which entry is highlighted.\n", + Use the %c and %c keys to select which entry is highlighted.\n", DISP_UP, DISP_DOWN); if (! auth && password) { printf ("\ - Press enter to boot the selected OS or \'p\' to enter a\n\ - password to unlock the next set of features."); + Press enter to boot the selected OS or \'p\' to enter a\n\ + password to unlock the next set of features."); } else { if (config_entries) printf ("\ - Press enter to boot the selected OS, \'e\' to edit the\n\ - commands before booting, or \'c\' for a command-line."); + Press enter to boot the selected OS, \'e\' to edit the\n\ + commands before booting, or \'c\' for a command-line."); else printf ("\ - Press \'b\' to boot, \'e\' to edit the selected command in the\n\ - boot sequence, \'c\' for a command-line, \'o\' to open a new line\n\ - after (\'O\' for before) the selected line, \'d\' to remove the\n\ - selected line, or escape to go back to the main menu."); + Press \'b\' to boot, \'e\' to edit the selected command in the\n\ + boot sequence, \'c\' for a command-line, \'o\' to open a new line\n\ + after (\'O\' for before) the selected line, \'d\' to remove the\n\ + selected line, or escape to go back to the main menu."); } if (current_term->flags & TERM_DUMB) grub_printf ("\n\nThe selected entry is %d ", entryno); else - print_entries (3, 12, first_entry, entryno, menu_entries); + print_entries (3 + row_start, box_size, first_entry, entryno, menu_entries); } /* XX using RT clock now, need to initialize value */ @@ -358,10 +381,10 @@ entryno, grub_timeout); else { - gotoxy (3, 22); - grub_printf ("The highlighted entry will be booted automatically in %d seconds. ", + gotoxy (3 + col_start, 10 + box_size + row_start); + grub_printf (" The highlighted entry will be booted automatically in %d seconds. ", grub_timeout); - gotoxy (74, 4 + entryno); + gotoxy ((col_end - 6), 4 + entryno + row_start); } grub_timeout--; @@ -387,12 +410,12 @@ if (current_term->flags & TERM_DUMB) grub_putchar ('\r'); else - gotoxy (3, 22); + gotoxy (3 + col_start, 10 + box_size + row_start); printf (" "); grub_timeout = -1; fallback_entryno = -1; if (! (current_term->flags & TERM_DUMB)) - gotoxy (74, 4 + entryno); + gotoxy ((col_end - 6), 4 + entryno + row_start); } /* We told them above (at least in SUPPORT_SERIAL) to use @@ -408,12 +431,12 @@ { if (entryno > 0) { - print_entry (4 + entryno, 0, + print_entry (4 + entryno + row_start, 0, get_entry (menu_entries, first_entry + entryno, 0)); entryno--; - print_entry (4 + entryno, 1, + print_entry (4 + entryno + row_start, 1, get_entry (menu_entries, first_entry + entryno, 0)); @@ -421,7 +444,7 @@ else if (first_entry > 0) { first_entry--; - print_entries (3, 12, first_entry, entryno, + print_entries (3 + row_start, box_size, first_entry, entryno, menu_entries); } } @@ -433,29 +456,29 @@ entryno++; else { - if (entryno < 11) + if (entryno < (box_size - 1)) { - print_entry (4 + entryno, 0, + print_entry (4 + entryno + row_start, 0, get_entry (menu_entries, first_entry + entryno, 0)); entryno++; - print_entry (4 + entryno, 1, + print_entry (4 + entryno + row_start, 1, get_entry (menu_entries, first_entry + entryno, 0)); } - else if (num_entries > 12 + first_entry) + else if (num_entries > box_size + first_entry) { first_entry++; - print_entries (3, 12, first_entry, entryno, menu_entries); + print_entries (3 + row_start, box_size, first_entry, entryno, menu_entries); } } } else if (c == 7) { /* Page Up */ - first_entry -= 12; + first_entry -= box_size; if (first_entry < 0) { entryno += first_entry; @@ -463,20 +486,20 @@ if (entryno < 0) entryno = 0; } - print_entries (3, 12, first_entry, entryno, menu_entries); + print_entries (3 + row_start, box_size, first_entry, entryno, menu_entries); } else if (c == 3) { /* Page Down */ - first_entry += 12; + first_entry += box_size; if (first_entry + entryno + 1 >= num_entries) { - first_entry = num_entries - 12; + first_entry = num_entries - box_size; if (first_entry < 0) first_entry = 0; entryno = num_entries - first_entry - 1; } - print_entries (3, 12, first_entry, entryno, menu_entries); + print_entries (3 + row_start, box_size, first_entry, entryno, menu_entries); } if (config_entries) @@ -489,7 +512,7 @@ if ((c == 'd') || (c == 'o') || (c == 'O')) { if (! (current_term->flags & TERM_DUMB)) - print_entry (4 + entryno, 0, + print_entry (4 + entryno + row_start, 0, get_entry (menu_entries, first_entry + entryno, 0)); @@ -537,7 +560,7 @@ if (entryno >= num_entries) entryno--; - if (first_entry && num_entries < 12 + first_entry) + if (first_entry && num_entries < box_size + first_entry) first_entry--; } @@ -549,7 +572,7 @@ grub_printf ("\n"); } else - print_entries (3, 12, first_entry, entryno, menu_entries); + print_entries (3 + row_start, box_size, first_entry, entryno, menu_entries); } cur_entry = menu_entries; @@ -570,7 +593,7 @@ if (current_term->flags & TERM_DUMB) grub_printf ("\r "); else - gotoxy (1, 21); + gotoxy (1 + col_start, 9 + box_size + row_start); /* Wipe out the previously entered password */ grub_memset (entered, 0, sizeof (entered)); @@ -717,6 +743,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) { @@ -752,6 +784,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; } @@ -1054,6 +1093,16 @@ while (is_preset); } + /* go ahead and make sure the terminal is setup */ + if (current_term->startup) + { + /* If initialization fails, go back to default terminal */ + if (current_term->startup() == 0) + { + current_term = term_table; + } + } + if (! num_entries) { /* If no acceptable config file, goto command-line, starting diff -Naur grub-0.97.orig/stage2/term.h grub-0.97/stage2/term.h --- grub-0.97.orig/stage2/term.h 2003-07-09 08:45:53.000000000 -0300 +++ grub-0.97/stage2/term.h 2005-06-13 14:07:40.000000000 -0300 @@ -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,10 @@ 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 +130,24 @@ int hercules_setcursor (int on); #endif +#ifdef SUPPORT_GRAPHICS +extern int foreground, background, window_border, graphics_inited, saved_videomode; + +void graphics_set_splash(char *splashfile); +int set_videomode(int mode); +int get_videomode(void); +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); +int 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 */ --- ./docs/grub.texi.graph_tex 2007-10-10 09:06:46.000000000 +0200 +++ ./docs/grub.texi 2007-10-10 09:08:09.000000000 +0200 @@ -2186,10 +2186,13 @@ Commands usable anywhere in the menu and in the command-line. @menu +* background:: Sets background color in graphics mode * bootp:: Initialize a network device via BOOTP +* border:: Sets border color in graphics mode * color:: Color the menu interface * device:: Specify a file as a drive * dhcp:: Initialize a network device via DHCP +* foreground:: Sets foreground color in graphics mode * hide:: Hide a partition * ifconfig:: Configure a network device manually * pager:: Change the state of the internal pager @@ -2199,13 +2202,25 @@ * rarp:: Initialize a network device via RARP * serial:: Set up a serial device * setkey:: Configure the key map +* shade:: Enables shaded letters in graphics mode +* splashimage:: Use a splash image * terminal:: Choose a terminal * terminfo:: Define escape sequences for a terminal * tftpserver:: Specify a TFTP server * unhide:: Unhide a partition +* viewport:: Changes text output limits in graphics mode @end menu +@node background +@subsection background + +@deffn Command background RRGGBB +Sets the background color when in graphics mode. RR is red, GG is +green, and BB blue. Numbers must be in hexadecimal. +@end deffn + + @node bootp @subsection bootp @@ -2220,6 +2235,15 @@ @end deffn +@node border +@subsection border + +@deffn Command border RRGGBB +Sets the border video color when in graphics mode. RR is red, GG is +green, and BB blue. Numbers must be in hexadecimal. +@end deffn + + @node color @subsection color @@ -2341,6 +2365,15 @@ @end deffn +@node foreground +@subsection foreground + +@deffn Command foreground RRGGBB +Sets the foreground color when in graphics mode. RR is red, GG is +green, and BB blue. Numbers must be in hexadecimal. +@end deffn + + @node hide @subsection hide @@ -2578,6 +2611,24 @@ @end deffn +@node shade +@subsection shade + +@deffn Command shade integer +If set to 0, disables the use of shaded text, else enables it. +@end deffn + + +@node splashimage +@subsection splashimage + +@deffn Command splashimage file +Select an image to use as the background image. This should be +specified using normal GRUB device naming syntax. The format of the +file is a gzipped xpm which is 640x480 with a 14 color palette. +@end deffn + + @node terminal @subsection terminal @@ -2650,6 +2701,16 @@ @end deffn +@node viewport +@subsection viewport + +@deffn Command viewport x0 y0 x1 y1 +Changes grub internals to output text in the window defined by four +parameters. The x and y parameters are 0 based. This option only works +with the graphics interface. +@end deffn + + @node Command-line and menu entry commands @section The list of command-line and menu entry commands