diff options
Diffstat (limited to 'graphics.patch')
-rw-r--r-- | graphics.patch | 2310 |
1 files changed, 2310 insertions, 0 deletions
diff --git a/graphics.patch b/graphics.patch new file mode 100644 index 000000000000..e9dbc15e9717 --- /dev/null +++ b/graphics.patch @@ -0,0 +1,2310 @@ +Index: b/configure.ac +=================================================================== +--- a/configure.ac ++++ b/configure.ac +@@ -606,6 +606,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]) +Index: b/stage2/asm.S +=================================================================== +--- a/stage2/asm.S ++++ b/stage2/asm.S +@@ -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), +Index: b/stage2/builtins.c +=================================================================== +--- a/stage2/builtins.c ++++ b/stage2/builtins.c +@@ -28,6 +28,10 @@ + #include <filesys.h> + #include <term.h> + ++#ifdef SUPPORT_GRAPHICS ++# include <graphics.h> ++#endif ++ + #ifdef SUPPORT_NETBOOT + # define GRUB 1 + # include <etherboot.h> +@@ -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 + }; +Index: b/stage2/char_io.c +=================================================================== +--- a/stage2/char_io.c ++++ b/stage2/char_io.c +@@ -29,12 +29,17 @@ + # include <serial.h> + #endif + ++#ifdef SUPPORT_GRAPHICS ++# include <graphics.h> ++#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) + { +Index: b/stage2/cmdline.c +=================================================================== +--- a/stage2/cmdline.c ++++ b/stage2/cmdline.c +@@ -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 +Index: b/stage2/graphics.c +=================================================================== +--- /dev/null ++++ b/stage2/graphics.c +@@ -0,0 +1,585 @@ ++/* ++ * graphics.c - graphics mode support for GRUB ++ * Implemented as a terminal type by Jeremy Katz <katzj@redhat.com> based ++ * on a patch by Paulo César Pereira de Andrade <pcpa@conectiva.com.br> ++ * Options and enhancements made by Herton Ronaldo Krzesinski ++ * <herton@mandriva.com> ++ * ++ * 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 <term.h> ++#include <shared.h> ++#include <graphics.h> ++ ++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 */ +Index: b/stage2/graphics.h +=================================================================== +--- /dev/null ++++ b/stage2/graphics.h +@@ -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 */ +Index: b/stage2/Makefile.am +=================================================================== +--- a/stage2/Makefile.am ++++ b/stage2/Makefile.am +@@ -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 <stage1.h>. +@@ -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) +Index: b/stage2/shared.h +=================================================================== +--- a/stage2/shared.h ++++ b/stage2/shared.h +@@ -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 +880,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); +Index: b/stage2/stage2.c +=================================================================== +--- a/stage2/stage2.c ++++ b/stage2/stage2.c +@@ -20,6 +20,12 @@ + #include <shared.h> + #include <term.h> + ++#ifdef SUPPORT_GRAPHICS ++# include <graphics.h> ++#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 +740,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 +Index: b/stage2/term.h +=================================================================== +--- a/stage2/term.h ++++ b/stage2/term.h +@@ -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 */ |