--- /dev/null
+diff -ru grub-0.92.orig/configure grub-0.92/configure
+--- grub-0.92.orig/configure 2002-04-28 21:13:07.000000000 -0300
++++ grub-0.92/configure 2002-06-17 21:19:23.000000000 -0300
+@@ -843,6 +843,7 @@
+ --disable-vstafs disable VSTa FS support in Stage 2
+ --disable-jfs disable IBM JFS support in Stage 2
+ --disable-xfs disable SGI XFS support in Stage 2
++ --disable-vga16 disable VGA graphics interface"
+ --disable-gunzip disable decompression in Stage 2
+ --disable-md5-password disable MD5 password support in Stage 2
+ --disable-packet-retransmission
+@@ -4647,6 +4648,16 @@
+ FSYS_CFLAGS="$FSYS_CFLAGS -DNO_DECOMPRESSION=1"
+ fi
+
++# Check whether --enable-vga16 or --disable-vga16 was given.
++if test "${enable_vga16+set}" = set; then
++ enableval="$enable_vga16"
++ :
++fi
++
++if test x"$enable_vga16" != xno; then
++ STAGE2_CFLAGS="$STAGE2_CFLAGS -DVGA16=1"
++fi
++
+ # Check whether --enable-md5-password or --disable-md5-password was given.
+ if test "${enable_md5_password+set}" = set; then
+ enableval="$enable_md5_password"
+diff -ru grub-0.92.orig/lib/device.c grub-0.92/lib/device.c
+--- grub-0.92.orig/lib/device.c 2001-10-13 01:20:05.000000000 -0300
++++ grub-0.92/lib/device.c 2002-06-17 21:19:23.000000000 -0300
+@@ -664,8 +664,14 @@
+ if (strcmp (dev + strlen(dev) - 5, "/disc") == 0)
+ strcpy (dev + strlen(dev) - 5, "/part");
+ }
+- sprintf (dev + strlen(dev), "%d", ((partition >> 16) & 0xFF) + 1);
+-
++
++ sprintf (dev + strlen(dev), "%s%d",
++ /* Compaq smart and others */
++ (strncmp(dev, "/dev/ida/", 9) == 0 ||
++ strncmp(dev, "/dev/cciss/", 11) == 0 ||
++ strncmp(dev, "/dev/rd/", 8) == 0) ? "p" : "",
++ ((partition >> 16) & 0xFF) + 1);
++
+ /* Open the partition. */
+ fd = open (dev, O_RDWR);
+ if (fd < 0)
+diff -ru grub-0.92.orig/stage2/asm.S grub-0.92/stage2/asm.S
+--- grub-0.92.orig/stage2/asm.S 2001-11-12 04:57:29.000000000 -0200
++++ grub-0.92/stage2/asm.S 2002-06-17 21:19:23.000000000 -0300
+@@ -1761,7 +1761,11 @@
+
+ VARIABLE(linux_text_len)
+ .long 0
+-
++VARIABLE(linux_init_seg)
++ .word LINUX_INIT_SEG
++VARIABLE(linux_setup_stack)
++ .word LINUX_SETUP_STACK
++
+ ENTRY(linux_boot)
+ /* don't worry about saving anything, we're committed at this point */
+ cld /* forward copying */
+@@ -1788,9 +1792,9 @@
+
+ /* final setup for linux boot */
+ cli
+- movw $LINUX_INIT_SEG, %ax
++ movw EXT_C(linux_init_seg), %ax
+ movw %ax, %ss
+- movw $LINUX_SETUP_STACK, %sp
++ movw EXT_C(linux_setup_stack), %sp
+
+ movw %ax, %ds
+ movw %ax, %es
+@@ -1801,6 +1805,7 @@
+ /* ljmp */
+ .byte 0xea
+ .word 0
++VARIABLE(linux_setup_seg)
+ .word LINUX_SETUP_SEG
+ .code32
+
+@@ -1865,7 +1870,7 @@
+ * %cl = cursor ending scanline
+ */
+
+-ENTRY(nocursor)
++ENTRY(grub_nocursor)
+ push %ebp
+ push %ebx /* save EBX */
+
+@@ -2009,6 +2014,263 @@
+ pop %ebp
+ ret
+
++#ifdef VGA16
++VARIABLE(cursorX)
++.word 0
++VARIABLE(cursorY)
++.word 0
++VARIABLE(cursorWidth)
++.word 0
++VARIABLE(cursorHeight)
++.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)
++/*
++ movw $0x3c4, %dx
++ movb $0x020f, %ax
++ outw %ax, %dx
++*/
++ call write_data
++
++int1c_done:
++ popa
++ iret
++ /* call previous int1c handler */
++ /* ljmp */
++ .byte 0xea
++int1c_offset: .word 0
++int1c_segment: .word 0
++ .code32
++
++
++ENTRY(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
++
++/*
++ * set_videomode(mode)
++ * BIOS call "INT 10H Function 0h" to set video mode
++ * Call with %ah = 0x0
++ * %al = video mode
++ */
++ENTRY(set_videomode)
++ push %ebp
++ push %ebx
++ push %ecx
++
++ movb 0x10(%esp), %cl
++
++ call EXT_C(prot_to_real)
++ .code16
++
++ xorw %bx, %bx
++ movb $0xf, %ah
++ int $0x10 /* Get Current Video mode */
++ movb %al, %ch
++ xorb %ah, %ah
++ movb %cl, %al
++ int $0x10 /* Set Video mode */
++
++ DATA32 call EXT_C(real_to_prot)
++ .code32
++
++ xorb %ah, %ah
++ movb %ch, %al
++
++ pop %ecx
++ pop %ebx
++ pop %ebp
++ ret
++
++/*
++ * 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(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
+
+ /*
+ * getrtsecs()
+diff -ru grub-0.92.orig/stage2/boot.c grub-0.92/stage2/boot.c
+--- grub-0.92.orig/stage2/boot.c 2002-04-29 15:47:14.000000000 -0300
++++ grub-0.92/stage2/boot.c 2002-06-17 21:19:23.000000000 -0300
+@@ -28,7 +28,26 @@
+ static int cur_addr;
+ entry_func entry_addr;
+ static struct mod_list mll[99];
+-static int linux_mem_size;
++unsigned int kernel_mem = 0;
++#ifndef GRUB_UTIL
++extern short linux_init_seg, linux_setup_seg, linux_setup_stack;
++int linux_setup = LINUX_SETUP;
++int cl_my_location = CL_MY_LOCATION;
++int cl_my_end_addr = CL_MY_END_ADDR;
++int cl_base_addr = CL_BASE_ADDR;
++int linux_heap_end_offset = LINUX_HEAP_END_OFFSET;
++#else
++int linux_setup;
++int cl_my_location;
++int cl_my_end_addr;
++int cl_base_addr;
++int linux_heap_end_offset;
++#endif
++char save_kernel[128];
++char save_args[256];
++unsigned long save_load_flags;
++kernel_t save_suggested_type;
++static int ramdisk_image = 0, ramdisk_size = 0;
+
+ /*
+ * The next two functions, 'load_image' and 'load_module', are the building
+@@ -40,7 +59,7 @@
+ load_image (char *kernel, char *arg, kernel_t suggested_type,
+ unsigned long load_flags)
+ {
+- int len, i, exec_type = 0, align_4k = 1;
++ int len, i, exec_type = 0, align_4k = 1, will_fit = 1;
+ entry_func real_entry_addr = 0;
+ kernel_t type = KERNEL_TYPE_NONE;
+ unsigned long flags = 0, text_len = 0, data_len = 0, bss_len = 0;
+@@ -57,6 +76,14 @@
+ executable header */
+ unsigned char buffer[MULTIBOOT_SEARCH];
+
++#ifdef GRUB_UTIL
++ linux_setup = LINUX_SETUP;
++ cl_my_location = CL_MY_LOCATION;
++ cl_my_end_addr = CL_MY_END_ADDR;
++ cl_base_addr = CL_BASE_ADDR;
++ linux_heap_end_offset = LINUX_HEAP_END_OFFSET;
++#endif
++
+ /* sets the header pointer to point to the beginning of the
+ buffer by default */
+ pu.aout = (struct exec *) buffer;
+@@ -211,32 +238,71 @@
+ int big_linux = 0;
+ int setup_sects = lh->setup_sects;
+
++ if (!(load_flags & KERNEL_REALLY_LOAD))
++ {
++ grub_strcpy(save_kernel, kernel);
++ grub_strcpy(save_args, arg);
++ save_load_flags = load_flags;
++ save_suggested_type = suggested_type;
++ }
++
+ if (lh->header == LINUX_MAGIC_SIGNATURE && lh->version >= 0x0200)
+ {
+ big_linux = (lh->loadflags & LINUX_FLAG_BIG_KERNEL);
+ lh->type_of_loader = LINUX_BOOT_LOADER_TYPE;
+
++#ifndef GRUB_UTIL
++ if (!(load_flags & KERNEL_REALLY_LOAD))
++ {
++ /* FIXME: SETUP_SECTS should be supported up to 63.
++ But do you know there are >640KB conventional memory machines? */
++ if (setup_sects < 60 && mbi.mem_lower < 608 && mbi.mem_lower >= 480)
++ {
++ int base_addr = ((mbi.mem_lower << 10) - 0x10000) & 0xffff00;
++
++ grub_printf("\nLess than 608 Kb of conventional memory available.\n"
++ "This is not enough memory to load linux.\n"
++ "Will try a workaround.\n\n");
++ linux_setup = cl_base_addr = base_addr;
++ cl_my_location = base_addr + 0x7f00;
++ cl_my_end_addr = cl_my_location + 0xff;
++ linux_init_seg = RAW_SEG(linux_setup) >> 4;
++ linux_setup_seg = linux_init_seg + 0x20;
++#if 0
++ linux_setup_stack = RAW_SEG(base_addr - 0x11000) >> 4;
++ linux_heap_end_offset = linux_setup_stack - 0x200;
++#endif
++ }
++ else
++ {
++ will_fit = (setup_sects < 60);
++ if (will_fit)
++ load_flags |= KERNEL_REALLY_LOAD;
++ }
++ }
++#endif
++
+ if (lh->version >= 0x0201)
+ {
+- lh->heap_end_ptr = LINUX_HEAP_END_OFFSET;
++ lh->heap_end_ptr = linux_heap_end_offset;
+ lh->loadflags |= LINUX_FLAG_CAN_USE_HEAP;
+ }
+
+ if (lh->version >= 0x0202)
+- lh->cmd_line_ptr = CL_MY_LOCATION;
++ lh->cmd_line_ptr = cl_my_location;
+ else
+ {
+ lh->cl_magic = CL_MAGIC;
+- lh->cl_offset = CL_MY_LOCATION - CL_BASE_ADDR;
++ lh->cl_offset = cl_my_location - cl_base_addr;
+ lh->setup_move_size
+- = (unsigned short) (CL_MY_END_ADDR - CL_BASE_ADDR + 1);
++ = (unsigned short) (cl_my_end_addr - cl_base_addr + 1);
+ }
+ }
+ else
+ {
+ /* Your kernel is quite old... */
+ lh->cl_magic = CL_MAGIC;
+- lh->cl_offset = CL_MY_LOCATION - CL_BASE_ADDR;
++ lh->cl_offset = cl_my_location - cl_base_addr;
+
+ setup_sects = LINUX_DEFAULT_SETUP_SECTS;
+ }
+@@ -256,12 +322,12 @@
+ return KERNEL_TYPE_NONE;
+ }
+
+- grub_printf (" [Linux-%s, setup=0x%x, size=0x%x]\n",
+- (big_linux ? "bzImage" : "zImage"), data_len, text_len);
++ if (!(save_load_flags & KERNEL_REALLY_LOAD))
++ grub_printf (" [Linux-%s, setup=0x%x, size=0x%x]\n",
++ (big_linux ? "bzImage" : "zImage"), data_len, text_len);
+
+- /* FIXME: SETUP_SECTS should be supported up to 63.
+- But do you know there are >640KB conventional memory machines? */
+- if (mbi.mem_lower >= 608 && setup_sects < 60)
++ save_load_flags = load_flags;
++ if (will_fit)
+ {
+ /* Video mode selection support. What a mess! */
+ /* NOTE: Even the word "mess" is not still enough to
+@@ -299,68 +365,25 @@
+ }
+ }
+
+- /* Check the mem= option to limit memory used for initrd. */
+- {
+- char *mem;
+-
+- mem = grub_strstr (arg, "mem=");
+- if (mem)
+- {
+- char *value = mem + 4;
+-
+- safe_parse_maxint (&value, &linux_mem_size);
+- switch (errnum)
+- {
+- case ERR_NUMBER_OVERFLOW:
+- /* If an overflow occurs, use the maximum address for
+- initrd instead. This is good, because MAXINT is
+- greater than LINUX_INITRD_MAX_ADDRESS. */
+- linux_mem_size = LINUX_INITRD_MAX_ADDRESS;
+- errnum = ERR_NONE;
+- break;
+-
+- case ERR_NONE:
+- {
+- int shift = 0;
+-
+- switch (grub_tolower (*value))
+- {
+- case 'g':
+- shift += 10;
+- case 'm':
+- shift += 10;
+- case 'k':
+- shift += 10;
+- default:
+- break;
+- }
+-
+- /* Check an overflow. */
+- if (linux_mem_size > (MAXINT >> shift))
+- linux_mem_size = LINUX_INITRD_MAX_ADDRESS;
+- else
+- linux_mem_size <<= shift;
+- }
+- break;
+-
+- default:
+- linux_mem_size = 0;
+- errnum = ERR_NONE;
+- break;
+- }
+- }
+- else
+- linux_mem_size = 0;
+- }
+-
+- memmove ((char *) LINUX_SETUP, buffer, data_len + SECTOR_SIZE);
++ if (load_flags & KERNEL_REALLY_LOAD)
++ {
++ if (ramdisk_size)
++ {
++ lh->ramdisk_image = ramdisk_image;
++ lh->ramdisk_size = ramdisk_size;
++ }
++ memmove ((char *) linux_setup, buffer, data_len + SECTOR_SIZE);
++ }
+
+ if (lh->header != LINUX_MAGIC_SIGNATURE ||
+ lh->version < 0x0200)
+- /* Clear the heap space. */
+- grub_memset ((char *) LINUX_SETUP + ((setup_sects - 1) << 9),
+- 0,
+- (64 - setup_sects - 1) << 9);
++ {
++ if (load_flags & KERNEL_REALLY_LOAD)
++ /* Clear the heap space. */
++ grub_memset ((char *) linux_setup + ((setup_sects - 1) << 9),
++ 0,
++ (64 - setup_sects - 1) << 9);
++ }
+
+ /* Copy command-line plus memory hack to staging area.
+ NOTE: Linux has a bug that it doesn't handle multiple spaces
+@@ -372,25 +395,40 @@
+ avoid to copy spaces unnecessarily. Hell. */
+ {
+ char *src = skip_to (0, arg);
+- char *dest = (char *) CL_MY_LOCATION;
++ char *mem;
++ char *dest = (char *) cl_my_location;
+
+- while (((int) dest) < CL_MY_END_ADDR && *src)
++ while (((int) dest) < cl_my_end_addr && *src)
+ *(dest++) = *(src++);
+
++/* don't add ``mem='' for 2.4 kernels :
++
++Newer machines have several regions of reserved memory outside and
++inside these regions. grub's actions are suicide on newer laptops,
++and machines like servers with lots of memory. Laptops have special
++sections of memory above 1MB which must be reserved... Ditto for
++ACPI tables. Using mem=XXX completely eliminates any information
++that the BIOS has provided to the OS.
++
++*/
+ /* Add a mem option automatically only if the user doesn't
+ specify it explicitly. */
+- if (! grub_strstr (arg, "mem=")
+- && ! (load_flags & KERNEL_LOAD_NO_MEM_OPTION))
++ mem = grub_strstr (arg, "mem=") + 4;
++ if (mem != (char*)4)
++ {
++ if (safe_parse_maxint(&mem, &kernel_mem))
+ {
+- if (dest != (char *) CL_MY_LOCATION)
+- *(dest++) = ' ';
+-
+- grub_memmove (dest, "mem=", 4);
+- dest += 4;
+-
+- dest = convert_to_ascii (dest, 'u', (extended_memory + 0x400));
+- *(dest++) = 'K';
++ if (*mem != 'K' && *mem != 'k')
++ kernel_mem *= 1024;
+ }
++ else
++ {
++ /* ERRNUM is already set inside the function
++ safe_parse_maxint. */
++ grub_close ();
++ return KERNEL_TYPE_NONE;
++ }
++ }
+
+ *dest = 0;
+ }
+@@ -399,9 +437,10 @@
+ grub_seek (data_len + SECTOR_SIZE);
+
+ cur_addr = LINUX_STAGING_AREA + text_len;
+- grub_read ((char *) LINUX_STAGING_AREA, text_len);
+-
+- if (errnum == ERR_NONE)
++
++ if (!(load_flags & KERNEL_REALLY_LOAD) ||
++ grub_read ((char *) LINUX_STAGING_AREA, text_len)
++ >= (text_len - 16))
+ {
+ grub_close ();
+
+@@ -420,7 +459,8 @@
+ return big_linux ? KERNEL_TYPE_BIG_LINUX : KERNEL_TYPE_LINUX;
+ }
+
+- grub_close ();
++ else if (! errnum)
++ errnum = ERR_EXEC_FORMAT;
+ }
+ else
+ errnum = ERR_WONT_FIT;
+@@ -759,7 +799,6 @@
+ {
+ int len;
+ unsigned long moveto;
+- struct linux_kernel_header *lh;
+
+ #ifndef NO_DECOMPRESSION
+ no_decompression = 1;
+@@ -775,28 +814,41 @@
+ goto fail;
+ }
+
+- if (linux_mem_size)
+- moveto = linux_mem_size;
+- else
+- moveto = (mbi.mem_upper + 0x400) << 10;
+-
+- moveto = (moveto - len) & 0xfffff000;
+- if (moveto + len >= LINUX_INITRD_MAX_ADDRESS)
+- moveto = (LINUX_INITRD_MAX_ADDRESS - len) & 0xfffff000;
++ if (!kernel_mem)
++ kernel_mem = mbi.mem_upper;
++
++ moveto = (kernel_mem * 0x400 - (len + (0x1000 - (len % 0x1000)))) & 0xfffff000;
++ if (moveto + len > LINUX_INITRD_MAX_ADDRESS)
++ moveto = LINUX_INITRD_MAX_ADDRESS - (len + (0x1000 - (len % 0x1000)));
+
+ /* XXX: Linux 2.3.xx has a bug in the memory range check, so avoid
+ the last page.
+ XXX: Linux 2.2.xx has a bug in the memory range check, which is
+ worse than that of Linux 2.3.xx, so avoid the last 64kb. *sigh* */
+ moveto -= 0x10000;
++
++#ifndef VGA16
+ memmove ((void *) RAW_ADDR (moveto), (void *) cur_addr, len);
++#else
++ grub_memcpy ((void *) RAW_ADDR (moveto), (void *) cur_addr, len);
++#endif
+
+ printf (" [Linux-initrd @ 0x%x, 0x%x bytes]\n", moveto, len);
+
+ /* FIXME: Should check if the kernel supports INITRD. */
+- lh = (struct linux_kernel_header *) LINUX_SETUP;
+- lh->ramdisk_image = RAW_ADDR (moveto);
+- lh->ramdisk_size = len;
++ if (linux_setup == LINUX_SETUP)
++ {
++ struct linux_kernel_header *lh;
++
++ lh = (struct linux_kernel_header *) linux_setup;
++ lh->ramdisk_image = RAW_ADDR (moveto);
++ lh->ramdisk_size = len;
++ }
++ else
++ {
++ ramdisk_image = RAW_ADDR (moveto);
++ ramdisk_size = len;
++ }
+
+ grub_close ();
+
+diff -ru grub-0.92.orig/stage2/builtins.c grub-0.92/stage2/builtins.c
+--- grub-0.92.orig/stage2/builtins.c 2002-04-28 21:26:49.000000000 -0300
++++ grub-0.92/stage2/builtins.c 2002-06-17 21:21:02.000000000 -0300
+@@ -80,6 +80,11 @@
+ /* The BIOS drive map. */
+ static unsigned short bios_drive_map[DRIVE_MAP_SIZE + 1];
+
++extern char save_kernel[128];
++extern char save_args[256];
++extern unsigned long save_load_flags;
++extern kernel_t save_suggested_type;
++
+ /* Prototypes for allowing straightfoward calling of builtins functions
+ inside other functions. */
+ static int configfile_func (char *arg, int flags);
+@@ -133,6 +138,36 @@
+ grub_printf ("[%d,%d,%d]", sector, offset, length);
+ }
+
++#ifdef VGA16
++/* 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 (vga_inited)
++ set_palette(0, r, g, b);
++ return (0);
++ }
++
++ return (1);
++}
++
++static struct builtin builtin_background =
++{
++ "background",
++ background_func,
++ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
++ "background RRGGBB",
++ "Sets the background color when in graphics mode."
++ "RR is red, GG is green, and BB blue. Numbers must be in hexadecimal."
++};
++#endif
++
+ \f
+ /* blocklist */
+ static int
+@@ -235,7 +270,7 @@
+ };
+
+ /* boot */
+-static int
++int
+ boot_func (char *arg, int flags)
+ {
+ /* Clear the int15 handler if we can boot the kernel successfully.
+@@ -259,11 +294,25 @@
+
+ case KERNEL_TYPE_LINUX:
+ /* Linux */
++ if (!(save_load_flags & KERNEL_REALLY_LOAD))
++ {
++ /* "really" load, and hope nothing fails, cannot return... */
++ save_load_flags |= KERNEL_REALLY_LOAD;
++ load_image(save_kernel, save_args,
++ save_suggested_type, save_load_flags);
++ }
+ linux_boot ();
+ break;
+
+ case KERNEL_TYPE_BIG_LINUX:
+ /* Big Linux */
++ if (!(save_load_flags & KERNEL_REALLY_LOAD))
++ {
++ /* "really" load, and hope nothing fails, cannot return... */
++ save_load_flags |= KERNEL_REALLY_LOAD;
++ load_image(save_kernel, save_args,
++ save_suggested_type, save_load_flags);
++ }
+ big_linux_boot ();
+ break;
+
+@@ -399,6 +448,39 @@
+ #endif /* SUPPORT_NETBOOT */
+
+ \f
++#ifdef VGA16
++
++/* foreground */
++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;
++
++ border = (r << 16) | (g << 8) | b;
++ if (vga_inited)
++ 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."
++};
++
++#endif
++
+ /* cat */
+ static int
+ cat_func (char *arg, int flags)
+@@ -409,7 +491,7 @@
+ return 1;
+
+ while (grub_read (&c, 1))
+- grub_putchar (c);
++ putchar (c);
+
+ grub_close ();
+ return 0;
+@@ -425,8 +507,24 @@
+ };
+
+ \f
+-/* chainloader */
+ static int
++chainboot_func(char *arg, int flags)
++{
++ grub_strcpy(chainboot, arg);
++}
++
++static struct builtin builtin_chainboot =
++{
++ "chainboot",
++ chainboot_func,
++ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
++ "chainboot device",
++ "This option should be used from an installer, if the user does not "
++ "select any option, try to chainload the specified hard disk."
++};
++
++/* chainloader */
++int
+ chainloader_func (char *arg, int flags)
+ {
+ int force = 0;
+@@ -974,6 +1072,43 @@
+ };
+
+ \f
++#ifdef VGA16
++/* display */
++static int
++display_func(char *arg, int flags)
++{
++ int i;
++
++ for (i = 0; i < MAX_DISPLAYS; i++) {
++ if (grub_strcmp(arg, display_entries[i].name) == 0)
++ break;
++ }
++
++ if (i >= MAX_DISPLAYS)
++ return (1);
++
++ display_idx = i;
++ if (display->End)
++ (*display->End)();
++ display = &display_entries[display_idx];
++
++ /* Restart cmain */
++ grub_longjmp (restart_env, 0);
++ /*NOTREACHED*/
++
++ return (0);
++}
++
++static struct builtin builtin_display =
++{
++ "display",
++ display_func,
++ BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
++ "display MODEL",
++ "Changes display type. Available modes are \"text\" and \"vga16\"."
++};
++#endif
++
+ /* dump FROM TO */
+ #ifdef GRUB_UTIL
+ static int
+@@ -1298,6 +1433,39 @@
+ " the devices which contain the file."
+ };
+
++#ifdef VGA16
++
++/* 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 (vga_inited)
++ 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."
++};
++
++#endif
++
+ \f
+ /* fstest */
+ static int
+@@ -1450,12 +1618,11 @@
+
+ \f
+ /* help */
+-#define MAX_SHORT_DOC_LEN 39
+-#define MAX_LONG_DOC_LEN 66
+-
+ static int
+ help_func (char *arg, int flags)
+ {
++ int MAX_SHORT_DOC_LEN = (view_x1 - view_x0 + 1) / 2 - 1;
++ int MAX_LONG_DOC_LEN = (view_x1 - view_x0) - 14;
+ int all = 0;
+
+ if (grub_memcmp (arg, "--all", sizeof ("--all") - 1) == 0)
+@@ -1491,13 +1658,13 @@
+ len = MAX_SHORT_DOC_LEN - 1;
+
+ for (i = 0; i < len; i++)
+- grub_putchar ((*builtin)->short_doc[i]);
++ putchar ((*builtin)->short_doc[i]);
+
+ for (; i < MAX_SHORT_DOC_LEN; i++)
+- grub_putchar (' ');
++ putchar (' ');
+
+ if (! left)
+- grub_putchar ('\n');
++ putchar ('\n');
+
+ left = ! left;
+ }
+@@ -1505,7 +1672,7 @@
+ /* If the last entry was at the left column, no newline was printed
+ at the end. */
+ if (! left)
+- grub_putchar ('\n');
++ putchar ('\n');
+ }
+ else
+ {
+@@ -1552,8 +1719,8 @@
+
+ grub_printf (" ");
+ for (i = 0; i < len; i++)
+- grub_putchar (*doc++);
+- grub_putchar ('\n');
++ putchar (*doc++);
++ putchar ('\n');
+ }
+ }
+ }
+@@ -3097,7 +3264,7 @@
+ print_fsys_type ();
+ }
+
+-static int
++int
+ root_func (char *arg, int flags)
+ {
+ int hdbias = 0;
+@@ -3965,6 +4132,74 @@
+ " to tell GRUB the file name under your OS."
+ };
+
++#ifdef VGA16
++/*splashimage*/
++static int
++splashimage_func(char *arg, int flags)
++{
++ if (strlen(arg) > 63)
++ return (1);
++ if (flags == BUILTIN_CMDLINE) {
++ if (!grub_open(arg))
++ return (1);
++ grub_close();
++ }
++
++ if (flags == BUILTIN_CMDLINE || !splash_set) {
++ strcpy(splashimage, arg);
++ splash_set = 1;
++ }
++
++ if (flags == BUILTIN_CMDLINE && vga_inited) {
++ display->End();
++ display->Begin();
++ cls();
++/* grub_longjmp(restart_env, 0);*/
++ }
++
++ 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 && vga_inited) {
++ display->End();
++ display->Begin();
++ 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."
++};
++#endif
++
+ \f
+ #if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES)
+ /* terminal */
+@@ -4287,6 +4522,11 @@
+ return 0;
+ }
+
++#ifdef VGA16
++ if (display->End)
++ (*display->End)();
++#endif
++
+ /* Now trip to the graphics mode. */
+ if (set_vbe_mode (mode_number | (1 << 14)) != 0x004F)
+ {
+@@ -4336,6 +4576,13 @@
+ /* Why?! */
+ grub_reboot ();
+ }
++#ifdef VGA16
++ if (display->Begin) {
++ if (!(*display->Begin)())
++ grub_reboot ();
++ cls();
++ }
++#endif
+
+ return 0;
+ }
+@@ -4573,15 +4820,79 @@
+ " the information about only the mode."
+ };
+
++#ifdef VGA16
++
++/* viewport */
++static int
++viewport_func (char *arg, int flags)
++{
++ int i;
++ int x0 = 80, y0 = 25, x1 = 0, y1 = 0;
++ int *pos[4] = { &x0, &y0, &x1, &y1 };
++ extern int viewport_set;
++
++ 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;
++ }
++
++ x1 += x0;
++ y1 += y0;
++
++ /* minimum size is 60 colums and 16 rows */
++ if (x0 > x1 - 60 || y0 > y1 - 16 || x0 < 0 || y0 < 0 || x1 > 80 || y1 > 30)
++ return (1);
++
++ viewport_set = 1;
++ view_x0 = x0;
++ view_y0 = y0;
++ view_x1 = x1;
++ view_y1 = y1;
++
++ if (flags == BUILTIN_CMDLINE && vga_inited) {
++ display->End();
++ display->Begin();
++ cls();
++ }
++
++ return (0);
++}
++
++static struct builtin builtin_viewport =
++{
++ "viewport",
++ viewport_func,
++ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
++ "viewport x y width height",
++ "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 vga interface."
++};
++#endif
++
+ \f
+ /* The table of builtin commands. Sorted in dictionary order. */
+ struct builtin *builtin_table[] =
+ {
++#ifdef VGA16
++ &builtin_background,
++#endif
+ &builtin_blocklist,
+ &builtin_boot,
+ #ifdef SUPPORT_NETBOOT
+ &builtin_bootp,
+ #endif /* SUPPORT_NETBOOT */
++#ifdef VGA16
++ &builtin_border,
++#endif
+ &builtin_cat,
+ &builtin_chainloader,
+ &builtin_cmp,
+@@ -4595,6 +4906,9 @@
+ #ifdef SUPPORT_NETBOOT
+ &builtin_dhcp,
+ #endif /* SUPPORT_NETBOOT */
++#ifdef VGA16
++ &builtin_display,
++#endif
+ &builtin_displayapm,
+ &builtin_displaymem,
+ #ifdef GRUB_UTIL
+@@ -4603,6 +4917,9 @@
+ &builtin_embed,
+ &builtin_fallback,
+ &builtin_find,
++#ifdef VGA16
++ &builtin_foreground,
++#endif
+ &builtin_fstest,
+ &builtin_geometry,
+ &builtin_halt,
+@@ -4646,6 +4963,10 @@
+ #endif /* SUPPORT_SERIAL */
+ &builtin_setkey,
+ &builtin_setup,
++#ifdef VGA16
++ &builtin_shade,
++ &builtin_splashimage,
++#endif
+ #if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES)
+ &builtin_terminal,
+ #endif /* SUPPORT_SERIAL || SUPPORT_HERCULES */
+@@ -4659,5 +4980,8 @@
+ &builtin_unhide,
+ &builtin_uppermem,
+ &builtin_vbeprobe,
++#ifdef VGA16
++ &builtin_viewport,
++#endif
+ 0
+ };
+diff -ru grub-0.92.orig/stage2/char_io.c grub-0.92/stage2/char_io.c
+--- grub-0.92.orig/stage2/char_io.c 2002-03-25 18:43:55.000000000 -0300
++++ grub-0.92/stage2/char_io.c 2002-06-17 21:19:23.000000000 -0300
+@@ -33,6 +33,8 @@
+ int max_lines = 24;
+ int count_lines = -1;
+ int use_pager = 1;
++#else
++#define putchar grub_putchar
+ #endif
+
+ void
+@@ -265,9 +267,9 @@
+
+ /* 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
+-
++ int CMDLINE_WIDTH = (view_x1 - view_x0) - 2;
++ int CMDLINE_MARGIN = 10;
++
+ int xpos, lpos, c, section;
+ /* The length of PROMPT. */
+ int plen;
+@@ -316,7 +318,7 @@
+ {
+ int y = getxy () & 0xFF;
+
+- gotoxy (xpos, y);
++ gotoxy (xpos + view_x0, y);
+ }
+ # ifdef SUPPORT_SERIAL
+ else if (! (terminal & TERMINAL_DUMB) && (count > 4))
+@@ -328,7 +330,7 @@
+ int i;
+
+ for (i = 0; i < count; i++)
+- grub_putchar ('\b');
++ putchar ('\b');
+ }
+ # endif /* SUPPORT_SERIAL */
+ }
+@@ -354,7 +356,7 @@
+ {
+ int y = getxy () & 0xFF;
+
+- gotoxy (xpos, y);
++ gotoxy (xpos + view_x0, y);
+ }
+ # ifdef SUPPORT_SERIAL
+ else if (! (terminal & TERMINAL_DUMB) && (count > 4))
+@@ -368,9 +370,9 @@
+ for (i = lpos - count; i < lpos; i++)
+ {
+ if (! echo_char)
+- grub_putchar (buf[i]);
++ putchar (buf[i]);
+ else
+- grub_putchar (echo_char);
++ putchar (echo_char);
+ }
+ }
+ # endif /* SUPPORT_SERIAL */
+@@ -398,7 +400,7 @@
+ /* From the start to the end. */
+ len = CMDLINE_WIDTH;
+ pos = 0;
+- grub_putchar ('\r');
++ putchar ('\r');
+
+ /* If SECTION is the first section, print the prompt, otherwise,
+ print `<'. */
+@@ -410,7 +412,7 @@
+ }
+ else
+ {
+- grub_putchar ('<');
++ putchar ('<');
+ len--;
+ pos++;
+ }
+@@ -446,9 +448,9 @@
+ for (i = start; i < start + len && i < llen; i++)
+ {
+ if (! echo_char)
+- grub_putchar (buf[i]);
++ putchar (buf[i]);
+ else
+- grub_putchar (echo_char);
++ putchar (echo_char);
+
+ pos++;
+ }
+@@ -467,9 +469,9 @@
+ if (pos == CMDLINE_WIDTH)
+ {
+ if (start + len < llen)
+- grub_putchar ('>');
++ putchar ('>');
+ else
+- grub_putchar (' ');
++ putchar (' ');
+
+ pos++;
+ }
+@@ -483,7 +485,7 @@
+ {
+ int y = getxy () & 0xFF;
+
+- gotoxy (xpos, y);
++ gotoxy (xpos + view_x0, y);
+ }
+ # ifdef SUPPORT_SERIAL
+ else if (! (terminal & TERMINAL_SERIAL) && (pos - xpos > 4))
+@@ -493,7 +495,7 @@
+ else
+ {
+ for (i = 0; i < pos - xpos; i++)
+- grub_putchar ('\b');
++ putchar ('\b');
+ }
+ # endif /* SUPPORT_SERIAL */
+ }
+@@ -503,7 +505,7 @@
+ void cl_init (void)
+ {
+ /* Distinguish us from other lines and error messages! */
+- grub_putchar ('\n');
++ putchar ('\n');
+
+ /* Print full line and set position here. */
+ cl_refresh (1, 0);
+@@ -634,7 +636,7 @@
+ /* There are more than one candidates, so print
+ the list. */
+
+- grub_putchar ('\n');
++ putchar ('\n');
+ /* Enable the auto fill mode temporarily. */
+ auto_fill = 1;
+ print_completions (is_filename, 0);
+@@ -776,7 +778,7 @@
+ }
+ }
+
+- grub_putchar ('\n');
++ putchar ('\n');
+
+ /* If ECHO_CHAR is NUL, remove the leading spaces. */
+ lpos = 0;
+@@ -1121,8 +1123,8 @@
+ else if (c >= ' ' && c <= '~')
+ {
+ /* Fold a line only if AUTO_FILL is true. */
+- if (auto_fill && col >= 79)
+- grub_putchar ('\n');
++ if (auto_fill && col >= view_x1 - view_x0)
++ putchar ('\n');
+
+ col++;
+ }
+@@ -1173,7 +1175,7 @@
+
+ #ifndef STAGE1_5
+ void
+-gotoxy (int x, int y)
++grub_gotoxy (int x, int y)
+ {
+ if (terminal & TERMINAL_CONSOLE)
+ console_gotoxy (x, y);
+@@ -1197,7 +1199,7 @@
+ #endif /* SUPPORT_SERIAL */
+
+ int
+-getxy (void)
++grub_getxy (void)
+ {
+ int ret = 0;
+
+@@ -1302,7 +1304,7 @@
+ #endif /* SUPPORT_SERIAL */
+
+ void
+-cls (void)
++grub_cls (void)
+ {
+ if (terminal & TERMINAL_CONSOLE)
+ console_cls ();
+@@ -1330,7 +1332,7 @@
+ #endif /* SUPPORT_SERIAL */
+
+ void
+-set_attrib (int attr)
++grub_set_attrib (int attr)
+ {
+ #ifdef SUPPORT_HERCULES
+ if (terminal & TERMINAL_HERCULES)
+@@ -1445,6 +1447,8 @@
+ || (addr >= RAW_ADDR (0x100000)
+ && RAW_ADDR (mbi.mem_upper * 1024) < ((addr - 0x100000) + len)))
+ errnum = ERR_WONT_FIT;
++ else
++ errnum = 0;
+
+ return ! errnum;
+ }
+diff -ru grub-0.92.orig/stage2/cmdline.c grub-0.92/stage2/cmdline.c
+--- grub-0.92.orig/stage2/cmdline.c 2002-03-24 09:28:54.000000000 -0300
++++ grub-0.92/stage2/cmdline.c 2002-06-17 21:19:23.000000000 -0300
+@@ -125,7 +125,7 @@
+ init_page ();
+ #ifdef SUPPORT_DISKLESS
+ print_network_configuration ();
+- grub_putchar ('\n');
++ putchar ('\n');
+ #endif
+ print_cmdline_message (forever);
+
+diff -ru grub-0.92.orig/stage2/disk_io.c grub-0.92/stage2/disk_io.c
+--- grub-0.92.orig/stage2/disk_io.c 2001-11-28 16:43:56.000000000 -0200
++++ grub-0.92/stage2/disk_io.c 2002-06-17 21:19:23.000000000 -0300
+@@ -1267,7 +1267,7 @@
+ }
+
+ if (! is_completion)
+- grub_putchar ('\n');
++ putchar ('\n');
+
+ print_error ();
+ do_completion = 0;
+@@ -1334,7 +1334,7 @@
+ }
+
+ if (! is_completion)
+- grub_putchar ('\n');
++ putchar ('\n');
+ }
+ else
+ {
+@@ -1408,7 +1408,7 @@
+ }
+
+ if (! is_completion)
+- grub_putchar ('\n');
++ putchar ('\n');
+ }
+ else
+ errnum = ERR_BAD_FILENAME;
+diff -ru grub-0.92.orig/stage2/shared.h grub-0.92/stage2/shared.h
+--- grub-0.92.orig/stage2/shared.h 2002-03-25 18:43:55.000000000 -0300
++++ grub-0.92/stage2/shared.h 2002-06-17 21:19:23.000000000 -0300
+@@ -368,7 +368,9 @@
+ #define printf grub_printf
+ #define sprintf grub_sprintf
+ #undef putchar
+-#define putchar grub_putchar
++#ifdef GRUB_UTIL
++ #define putchar grub_putchar
++#endif
+ #define strncat grub_strncat
+ #define strstr grub_strstr
+ #define memcmp grub_memcmp
+@@ -383,6 +385,9 @@
+ /*
+ * Below this should be ONLY defines and other constructs for C code.
+ */
++#ifdef VGA16
++#define VIDEO 0xA0000
++#endif
+
+ /* multiboot stuff */
+
+@@ -779,26 +784,26 @@
+ int currticks (void);
+
+ /* Clear the screen. */
+-void cls (void);
++void grub_cls (void);
+
+ /* The console part of cls. */
+ void console_cls (void);
+
+ #ifndef GRUB_UTIL
+ /* Turn off cursor. */
+-void nocursor (void);
++void grub_nocursor (void);
+ #endif
+
+ /* Get the current cursor position (where 0,0 is the top left hand
+ corner of the screen). Returns packed values, (RET >> 8) is x,
+ (RET & 0xff) is y. */
+-int getxy (void);
++int grub_getxy (void);
+
+ /* The console part of getxy. */
+ int console_getxy (void);
+
+ /* Set the cursor position. */
+-void gotoxy (int x, int y);
++void grub_gotoxy (int x, int y);
+
+ /* The console part of gotoxy. */
+ void console_gotoxy (int x, int y);
+@@ -826,11 +831,67 @@
+
+ /* Sets text mode character attribute at the cursor position. See A_*
+ constants defined above. */
+-void set_attrib (int attr);
++void grub_set_attrib (int attr);
+
+ /* The console part of set_attrib. */
+ void console_set_attrib (int attr);
+
++extern int view_x0, view_y0, view_x1, view_y1;
++#ifdef VGA16
++#define MAX_DISPLAYS 2
++
++#define cls() (display->Cls ? (*display->Cls)() : 0)
++#define gotoxy(x, y) (display->Gotoxy ? (*display->Gotoxy)(x, y) : 0)
++#define putchar(c) (display->Putchar ? (*display->Putchar)(c) : 0)
++#define set_attrib(a) (display->SetAttrib ? (*display->SetAttrib)(a) : 0)
++#define getxy() (display->Getxy ? (*display->Getxy)() : 0)
++#define nocursor() (display->Nocursor ? (*display->Nocursor)() : 0)
++struct display_entry {
++ char *name;
++ int (*Begin)(void);
++ void (*End)(void);
++ void (*Cls)(void);
++ void (*Gotoxy)(int x, int y);
++ void (*Putchar)(int ch);
++ void (*SetAttrib)(int attr);
++ int (*Getxy)(void);
++ void (*Nocursor)(void);
++};
++struct display_entry display_entries[MAX_DISPLAYS + 1];
++extern struct display_entry *display;
++
++extern int vga_inited, foreground, background, shade, border;
++extern int display_idx, splash_set;
++extern short cursorX, cursorY, cursorWidth, cursorHeight;
++extern char cursorBuf[16], splashimage[64];
++
++int vga16_begin(void);
++void vga16_end(void);
++void vga16_cls(void);
++void vga16_gotoxy(int x, int y);
++void vga16_putchar(int ch);
++int vga16_getxy(void);
++void vga16_nocursor(void);
++void vga16_set_attrib(int attr);
++
++int read_image();
++void set_palette(int index, int red, int green, int blue);
++void *get_font(void);
++/* return previous video mode */
++int set_videomode(int mode);
++
++int hex(int);
++void set_int1c_handler();
++void unset_int1c_handler();
++void cursor(int state);
++#else
++#define cls grub_cls
++#define gotoxy grub_gotoxy
++#define set_attrib grub_set_attrib
++#define getxy grub_getxy
++#define nocursor grub_nocursor
++#endif
++
+ /* Low-level disk I/O */
+ int get_diskinfo (int drive, struct geometry *geometry);
+ int biosdisk (int subfunc, int drive, struct geometry *geometry,
+@@ -840,6 +901,8 @@
+ /* Command-line interface functions. */
+ #ifndef STAGE1_5
+
++extern char chainboot[];
++
+ /* The flags for the builtins. */
+ #define BUILTIN_CMDLINE 0x1 /* Run in the command-line. */
+ #define BUILTIN_MENU 0x2 /* Run in the menu. */
+@@ -1018,6 +1081,7 @@
+ /* Define flags for load_image here. */
+ /* Don't pass a Linux's mem option automatically. */
+ #define KERNEL_LOAD_NO_MEM_OPTION (1 << 0)
++#define KERNEL_REALLY_LOAD (1 << 16)
+
+ kernel_t load_image (char *kernel, char *arg, kernel_t suggested_type,
+ unsigned long load_flags);
+diff -ru grub-0.92.orig/stage2/stage2.c grub-0.92/stage2/stage2.c
+--- grub-0.92.orig/stage2/stage2.c 2002-03-24 09:28:54.000000000 -0300
++++ grub-0.92/stage2/stage2.c 2002-06-17 21:19:23.000000000 -0300
+@@ -19,7 +19,13 @@
+
+ #include "shared.h"
+
++char chainboot[16];
++int view_x0 = 0, view_y0 = 0, view_x1 = 80, view_y1 = 25;
+ grub_jmp_buf restart_env;
++#ifdef VGA16
++int vga_disabled = 0, viewport_set = 0;
++int sx0, sy0, sx1, sy1;
++#endif
+
+ #if defined(PRESET_MENU_STRING) || defined(SUPPORT_DISKLESS)
+
+@@ -109,12 +115,12 @@
+ }
+ #endif /* SUPPORT_SERIAL */
+
+- gotoxy (77, y + 1);
++ gotoxy (view_x1 - 3, y + 1);
+
+ if (first)
+- grub_putchar (disp_up);
++ putchar (disp_up);
+ else
+- grub_putchar (' ');
++ putchar (' ');
+
+ menu_entries = get_entry (menu_entries, first, 0);
+
+@@ -122,13 +128,13 @@
+ {
+ int j = 0;
+
+- gotoxy (3, y + i);
++ gotoxy (view_x0 + 3, y + i);
+
+ while (*menu_entries)
+ {
+- if (j < 71)
++ if (j < (view_x1 - view_x0) - 9)
+ {
+- grub_putchar (*menu_entries);
++ putchar (*menu_entries);
+ j++;
+ }
+
+@@ -138,16 +144,16 @@
+ if (*(menu_entries - 1))
+ menu_entries++;
+
+- for (; j < 71; j++)
+- grub_putchar (' ');
++ for (; j < (view_x1 - view_x0) - 9; j++)
++ putchar (' ');
+ }
+
+- gotoxy (77, y + size);
++ gotoxy (view_x1 - 3, y + size);
+
+ if (*menu_entries)
+- grub_putchar (disp_down);
++ putchar (disp_down);
+ else
+- grub_putchar (' ');
++ putchar (' ');
+ }
+
+
+@@ -159,20 +165,20 @@
+ #define LINE_LENGTH 67
+
+ for (i = 0; i < LINE_LENGTH; i++)
+- grub_putchar ('-');
+- grub_putchar ('\n');
++ putchar ('-');
++ putchar ('\n');
+
+ for (i = first; i < size; i++)
+ {
+ /* grub's printf can't %02d so ... */
+ if (i < 10)
+- grub_putchar (' ');
++ putchar (' ');
+ grub_printf ("%d: %s\n", i, get_entry (menu_entries, i, 0));
+ }
+
+ for (i = 0; i < LINE_LENGTH; i++)
+- grub_putchar ('-');
+- grub_putchar ('\n');
++ putchar ('-');
++ putchar ('\n');
+
+ #undef LINE_LENGTH
+ }
+@@ -211,10 +217,10 @@
+ )
+ # endif
+ {
+- for (i = 0; i < 14; i++)
++ for (i = 0; i < 12; i++)
+ {
+ int j;
+- for (j = 0; j < 75; j++)
++ for (j = view_x0; j < (view_x1 - view_x0) - 5; j++)
+ {
+ gotoxy (j + 1, i + y);
+ set_attrib (normal_color);
+@@ -223,33 +229,33 @@
+ }
+ #endif
+
+- gotoxy (1, y);
++ gotoxy (view_x0 + 1, y);
+
+- grub_putchar (disp_ul);
+- for (i = 0; i < 73; i++)
+- grub_putchar (disp_horiz);
+- grub_putchar (disp_ur);
++ putchar (disp_ul);
++ for (i = 0; i < view_x1 - 7; i++)
++ putchar (disp_horiz);
++ putchar (disp_ur);
+
+ i = 1;
+
+ while (1)
+ {
+- gotoxy (1, y + i);
++ gotoxy (view_x0 + 1, y + i);
+
+ if (i > size)
+ break;
+
+- grub_putchar (disp_vert);
+- gotoxy (75, y + i);
+- grub_putchar (disp_vert);
++ putchar (disp_vert);
++ gotoxy (view_x1 - 5, y + i);
++ putchar (disp_vert);
+
+ i++;
+ }
+
+- grub_putchar (disp_ll);
+- for (i = 0; i < 73; i++)
+- grub_putchar (disp_horiz);
+- grub_putchar (disp_lr);
++ putchar (disp_ll);
++ for (i = view_x0; i < view_x1 - 7; i++)
++ putchar (disp_horiz);
++ putchar (disp_lr);
+ }
+
+ static void
+@@ -261,27 +267,27 @@
+ if (terminal & TERMINAL_SERIAL)
+ {
+ menu_entries = get_entry (menu_entries, entryno, 0);
+- gotoxy (2, y);
+- grub_putchar (' ');
+- for (x = 3; x < 75; x++)
++ gotoxy (view_x0 + 2, y);
++ putchar (' ');
++ for (x = view_x0 + 3; x < view_x1 - 5; x++)
+ {
+- if (*menu_entries && x < 71)
+- grub_putchar (*menu_entries++);
++ if (*menu_entries && x < view_x1 - 9)
++ putchar (*menu_entries++);
+ else
+- grub_putchar (' ');
++ putchar (' ');
+ }
+ }
+ else
+ #endif /* SUPPORT_SERIAL */
+ {
+- for (x = 2; x < 75; x++)
++ for (x = view_x0 + 2; x < view_x1 - 5; x++)
+ {
+ gotoxy (x, y);
+ set_attrib (attr);
+ }
+ }
+
+- gotoxy (74, y);
++ gotoxy (view_x1 - 6, y);
+ }
+
+ /* Set the attribute of the line Y to normal state. */
+@@ -320,6 +326,7 @@
+ run_menu (char *menu_entries, char *config_entries, int num_entries,
+ char *heap, int entryno)
+ {
++ int timeout = 1;
+ int c, time1, time2 = -1, first_entry = 0;
+ char *cur_entry = 0;
+ int disp_up = DISP_UP;
+@@ -399,7 +406,7 @@
+ #endif /* ! GRUB_UTIL */
+
+ if (! (terminal & TERMINAL_DUMB))
+- print_border (3, 12);
++ print_border (3 + view_y0, 12);
+
+ #ifdef GRUB_UTIL
+ /* In the grub shell, always use ACS_*. */
+@@ -455,10 +462,10 @@
+ grub_printf ("\n\nThe selected entry is %d ", entryno);
+ else
+ {
+- print_entries (3, 12, first_entry, menu_entries);
++ print_entries (view_y0 + 3, 12, first_entry, menu_entries);
+
+ /* highlight initial line */
+- set_line_highlight (4 + entryno, first_entry + entryno,
++ set_line_highlight (view_y0 + 4 + entryno, first_entry + entryno,
+ menu_entries);
+ }
+ }
+@@ -487,9 +494,9 @@
+ entryno, grub_timeout);
+ else
+ {
+- gotoxy (3, 22);
+- printf ("The highlighted entry will be booted automatically in %d seconds. ", grub_timeout);
+- gotoxy (74, 4 + entryno);
++ gotoxy (view_x0 + 3, view_y1 - 2);
++ printf ("Select an option to install (%d seconds left). ", grub_timeout);
++ gotoxy (view_x0 - 6, view_y0 + 4 + entryno);
+ }
+
+ grub_timeout--;
+@@ -513,14 +520,15 @@
+ if (grub_timeout >= 0)
+ {
+ if (terminal & TERMINAL_DUMB)
+- grub_putchar ('\r');
++ putchar ('\r');
+ else
+- gotoxy (3, 22);
++ gotoxy (view_x0 + 3, view_y1 - 2);
+ printf (" ");
+ grub_timeout = -1;
+ fallback_entry = -1;
+ if (! (terminal & TERMINAL_DUMB))
+- gotoxy (74, 4 + entryno);
++ gotoxy (view_x1 - 6, view_x0 + 4 + entryno);
++ timeout = 0;
+ }
+
+ /* We told them above (at least in SUPPORT_SERIAL) to use
+@@ -536,17 +544,17 @@
+ {
+ if (entryno > 0)
+ {
+- set_line_normal (4 + entryno, first_entry + entryno,
++ set_line_normal (view_y0 + 4 + entryno, first_entry + entryno,
+ menu_entries);
+ entryno--;
+- set_line_highlight (4 + entryno, first_entry + entryno,
++ set_line_highlight (view_y0 + 4 + entryno, first_entry + entryno,
+ menu_entries);
+ }
+ else if (first_entry > 0)
+ {
+ first_entry--;
+- print_entries (3, 12, first_entry, menu_entries);
+- set_line_highlight (4, first_entry + entryno,
++ print_entries (view_y0 + 3, 12, first_entry, menu_entries);
++ set_line_highlight (view_y0 + 4, first_entry + entryno,
+ menu_entries);
+ }
+ }
+@@ -558,17 +566,17 @@
+ else
+ if (entryno < 11)
+ {
+- set_line_normal (4 + entryno, first_entry + entryno,
++ set_line_normal (view_y0 + 4 + entryno, first_entry + entryno,
+ menu_entries);
+ entryno++;
+- set_line_highlight (4 + entryno, first_entry + entryno,
++ set_line_highlight (view_y0 + 4 + entryno, first_entry + entryno,
+ menu_entries);
+ }
+ else if (num_entries > 12 + first_entry)
+ {
+ first_entry++;
+- print_entries (3, 12, first_entry, menu_entries);
+- set_line_highlight (15, first_entry + entryno, menu_entries);
++ print_entries (view_y0 + 3, 12, first_entry, menu_entries);
++ set_line_highlight (view_y0 + 15, first_entry + entryno, menu_entries);
+ }
+ }
+
+@@ -582,7 +590,7 @@
+ if ((c == 'd') || (c == 'o') || (c == 'O'))
+ {
+ if (! (terminal & TERMINAL_DUMB))
+- set_line_normal (4 + entryno, first_entry + entryno,
++ set_line_normal (view_y0 + 4 + entryno, first_entry + entryno,
+ menu_entries);
+
+ /* insert after is almost exactly like insert before */
+@@ -640,8 +648,8 @@
+ }
+ else
+ {
+- print_entries (3, 12, first_entry, menu_entries);
+- set_line_highlight (4 + entryno, first_entry + entryno,
++ print_entries (view_y0 + 3, 12, first_entry, menu_entries);
++ set_line_highlight (view_y0 + 4 + entryno, first_entry + entryno,
+ menu_entries);
+ }
+ }
+@@ -664,7 +672,7 @@
+ if (terminal & TERMINAL_DUMB)
+ grub_printf ("\r ");
+ else
+- gotoxy (1, 21);
++ gotoxy (view_x0 + 1, view_y1 - 3);
+
+ /* Wipe out the previously entered password */
+ memset (entered, 0, sizeof (entered));
+@@ -807,11 +815,26 @@
+ boot_entry:
+ /* Enable the auto fill mode. */
+ auto_fill = 1;
+-
+- cls ();
++
++ if (timeout && *chainboot) {
++ errnum = 0;
++ if (root_func(chainboot, 0) == 0) {
++ /* If can set the new root device */
++ if (chainloader_func("+1", 0) == 0)
++ /* If can load the new boot */
++ boot_func("", 0);
++ }
++ }
+
+ while (1)
+ {
++ cls ();
++#ifdef VGA16
++ if (display->End)
++ (*display->End)();
++ display = &display_entries[0];
++#endif
++
+ if (config_entries)
+ printf (" Booting \'%s\'\n\n",
+ get_entry (menu_entries, first_entry + entryno, 0));
+@@ -840,6 +863,16 @@
+ break;
+ }
+
++#ifdef VGA16
++ if (display_idx >= 0)
++ display = &display_entries[display_idx];
++ else if (!vga_disabled)
++ display = &display_entries[1];
++
++ if (!display->Begin || !(*display->Begin)())
++ display = &display_entries[0];
++#endif
++
+ show_menu = 1;
+ goto restart;
+ }
+@@ -904,6 +937,560 @@
+ return pos;
+ }
+
++#ifdef VGA16
++struct display_entry display_entries[MAX_DISPLAYS + 1] = {
++ {"text", 0, 0, grub_cls, grub_gotoxy, grub_putchar, grub_set_attrib,
++ grub_getxy, grub_nocursor},
++ {"vga16",
++ vga16_begin, vga16_end, vga16_cls, vga16_gotoxy, vga16_putchar,
++ vga16_set_attrib, vga16_getxy, vga16_nocursor},
++ {0, 0, 0, 0, 0, 0, 0, 0, 0}
++};
++struct display_entry *display;
++int display_idx = -1;
++
++/* default vga palette */
++char vga16pal[16][3] = {
++ { 0, 0, 0},
++ { 0, 0, 42},
++ { 0, 42, 0},
++ { 0, 42, 42},
++ {42, 0, 0},
++ {42, 0, 42},
++ {42, 21, 0},
++ {42, 42, 42},
++ {21, 21, 21},
++ {21, 21, 63},
++ {21, 63, 21},
++ {21, 63, 63},
++ {63, 21, 21},
++ {63, 21, 63},
++ {63, 63, 21},
++ {63, 63, 63},
++};
++
++int fontx, fonty;
++unsigned char *font8x16;
++int saved_videomode, no_scroll = 0, no_cursor = 0, shade = 1, vga_inited = 0;
++unsigned short text[80 * 30];
++int foreground = (63 << 16) | (63 << 8) | (63), background = 0, border = 0;
++int splash_set;
++char splashimage[64];
++#define VSHADOW VSHADOW1
++unsigned char VSHADOW1[38400];
++unsigned char VSHADOW2[38400];
++unsigned char VSHADOW4[38400];
++unsigned char VSHADOW8[38400];
++
++static inline void
++outb(unsigned short port, unsigned char val)
++{
++ __asm __volatile ("outb %0,%1"::"a" (val), "d" (port));
++}
++
++static void
++ModeReg(int value)
++{
++ outb(0x3ce, 5);
++ outb(0x3cf, value);
++}
++
++static void
++MapMask(int value)
++{
++ outb(0x3c4, 2);
++ outb(0x3c5, value);
++}
++
++/* set/reset register */
++static void
++SetRes(int value)
++{
++ outb(0x3ce, 0);
++ outb(0x3cf, value);
++}
++
++/* enable set/reset register */
++static void
++ESetRes(int value)
++{
++ outb(0x3ce, 1);
++ outb(0x3cf, value);
++}
++
++static void
++ReadMap(int value)
++{
++ outb(0x3ce, 4);
++ outb(0x3cf, value);
++}
++
++/* bit mask register */
++static void
++BitMask(int value)
++{
++ outb(0x3ce, 8);
++ outb(0x3cf, value);
++}
++
++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];
++}
++
++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');
++}
++
++static void
++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;
++ }
++}
++
++void
++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*)VIDEO + 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);
++}
++
++int
++read_image(void)
++{
++ char buf[32], pal[16];
++ unsigned char c, base, mask, *s1, *s2, *s4, *s8;
++ unsigned i, len, idx, colors, x, y, width, height;
++
++ if (!grub_open(splashimage))
++ 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;
++ 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();
++
++ set_palette(0, (background >> 16), (background >> 8) & 63, background & 63);
++ set_palette(15, (foreground >> 16), (foreground >> 8) & 63, foreground & 63);
++
++ set_palette(0x11, (border >> 16), (border >> 8) & 63, border & 63);
++
++ return (1);
++}
++
++int
++vga16_begin(void)
++{
++ if (vga_inited)
++ return (1);
++
++ if (!*splashimage)
++ grub_strcpy(splashimage, "/boot/grub/splash.xpm");
++
++ saved_videomode = set_videomode(0x12);
++ if (!read_image()) {
++ set_videomode(saved_videomode);
++ return (0);
++ }
++
++ font8x16 = (unsigned char*)get_font();
++
++ cursorWidth = 8;
++ cursorHeight = 16;
++
++ set_int1c_handler();
++
++ view_x0 = sx0;
++ view_y0 = sy0;
++ view_x1 = sx1;
++ view_y1 = sy1;
++
++ return (vga_inited = 1);
++}
++
++void
++vga16_end(void)
++{
++ if (vga_inited) {
++ unset_int1c_handler();
++ set_videomode(saved_videomode);
++ vga_inited = 0;
++ no_cursor = 0;
++ }
++
++ sx0 = view_x0;
++ sy0 = view_y0;
++ sx1 = view_x1;
++ sy1 = view_y1;
++ view_x0 = 0;
++ view_x1 = 80;
++ view_y0 = 0;
++ view_y1 = 25;
++}
++
++void
++vga16_cls(void)
++{
++ int i;
++ unsigned char *mem, *s1, *s2, *s4, *s8;
++
++ SetXY(view_x0, view_y0);
++
++ mem = (unsigned char*)VIDEO;
++ 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] = ' ';
++
++ BitMask(0xff);
++
++ /* plano 1 */
++ MapMask(1);
++ grub_memcpy(mem, s1, 38400);
++
++ /* plano 2 */
++ MapMask(2);
++ grub_memcpy(mem, s2, 38400);
++
++ /* plano 3 */
++ MapMask(4);
++ grub_memcpy(mem, s4, 38400);
++
++ /* plano 4 */
++ MapMask(8);
++ grub_memcpy(mem, s8, 38400);
++
++ MapMask(15);
++
++ if (no_cursor) {
++ no_cursor = 0;
++ set_int1c_handler();
++ }
++}
++
++void
++vga16_gotoxy(int x, int y)
++{
++ cursor(0);
++
++ SetXY(x, y);
++
++ cursor(1);
++}
++
++static void
++scroll(void)
++{
++ int i, j;
++
++ if (no_scroll)
++ return;
++
++ no_scroll = 1;
++
++ for (j = view_y0 + 1; j < view_y1; j++) {
++ gotoxy(view_x0, j - 1);
++ for (i = view_x0; i < view_x1; i++)
++ putchar(text[j * 80 + i]);
++ }
++
++ gotoxy(view_x0, view_y1 - 1);
++ for (i = view_x0; i < view_x1; i++)
++ putchar(' ');
++
++ SetXY(view_x0, view_y1 - 1);
++
++ no_scroll = 0;
++}
++
++void
++vga16_putchar(int ch)
++{
++ ch &= 0xff;
++
++ cursor(0);
++
++ if (ch == '\n') {
++ SetXY(view_x0, fonty);
++ if (fonty + 1 < view_y1)
++ SetXY(view_x0, fonty + 1);
++ else
++ scroll();
++ cursor(1);
++ return;
++ }
++ else if (ch == '\r') {
++ SetXY(view_x0, fonty);
++ cursor(1);
++ return;
++ }
++
++ text[fonty * 80 + fontx] = ch;
++
++ cursor(0);
++
++ if ((fontx + 1) >= view_x1) {
++ SetXY(view_x0, fonty);
++ if (fonty + 1 < view_y1)
++ SetXY(view_x0, fonty + 1);
++ else
++ scroll();
++ }
++ else
++ SetXY(fontx + 1, fonty);
++
++ cursor(1);
++}
++
++int
++vga16_getxy()
++{
++ return ((fontx << 8) | fonty);
++}
++
++void
++vga16_nocursor()
++{
++ if (!no_cursor) {
++ no_cursor = 1;
++ unset_int1c_handler();
++ cursor(0);
++ }
++}
++
++void
++vga16_set_attrib(int attrib)
++{
++ text[fonty * 80 + fontx] &= 0x00ff;
++ if (attrib & 0xf0)
++ text[fonty * 80 + fontx] |= 0x100;
++ cursor(0);
++}
++#endif
+
+ /* This is the starting function in C. */
+ void
+@@ -924,7 +1511,15 @@
+ menu_entries = (char *) MENU_BUF;
+ init_config ();
+ }
+-
++
++#ifdef VGA16
++ /* Make sure it points to a valid entry */
++ display = &display_entries[0];
++
++ if (ASCII_CHAR(checkkey()) == 0x1b)
++ vga_disabled = 1;
++#endif
++
+ /* Initialize the environment for restarting Stage 2. */
+ grub_setjmp (restart_env);
+
+@@ -1069,6 +1664,29 @@
+ while (is_preset);
+ }
+
++#ifdef VGA16
++ if (display_idx >= 0)
++ display = &display_entries[display_idx];
++ else if (!vga_disabled) {
++ display = &display_entries[1];
++ }
++ if (!viewport_set)
++ view_y1 = 30;
++ sx0 = view_x0;
++ sy0 = view_y0;
++ sx1 = view_x1;
++ sy1 = view_y1;
++
++ if (!display->Begin || !(*display->Begin)())
++ display = &display_entries[0];
++
++ if (!vga_inited) {
++ sx0 = sy0 = view_x0 = view_y0 = 0;
++ sx1 = view_x1 = 80;
++ sy1 = view_y1 = 25;
++ }
++#endif
++
+ if (! num_entries)
+ {
+ /* If no acceptable config file, goto command-line, starting
+diff -ru grub-0.92.orig/stage2/builtins.c grub-0.92/stage2/builtins.c
+--- grub-0.92.orig/stage2/builtins.c 2002-06-25 17:58:03.000000000 -0300
++++ grub-0.92/stage2/builtins.c 2002-06-25 17:36:23.000000000 -0300
+@@ -4856,6 +4856,7 @@
+ view_y0 = y0;
+ view_x1 = x1;
+ view_y1 = y1;
++ max_lines = view_y1 - view_y0;
+
+ if (flags == BUILTIN_CMDLINE && vga_inited) {
+ display->End();
+Only in grub-0.92/stage2: builtins.c~
+diff -ru grub-0.92.orig/stage2/char_io.c grub-0.92/stage2/char_io.c
+--- grub-0.92.orig/stage2/char_io.c 2002-06-25 17:58:03.000000000 -0300
++++ grub-0.92/stage2/char_io.c 2002-06-25 17:53:31.000000000 -0300
+@@ -460,7 +460,7 @@
+ /* Fill up the rest of the line with spaces. */
+ for (; i < start + len; i++)
+ {
+- grub_putchar (' ');
++ putchar (' ');
+ pos++;
+ }
+
+diff -ru grub-0.92.orig/stage2/stage2.c grub-0.92/stage2/stage2.c
+--- grub-0.92.orig/stage2/stage2.c 2002-06-25 17:58:03.000000000 -0300
++++ grub-0.92/stage2/stage2.c 2002-06-25 18:07:39.000000000 -0300
+@@ -217,10 +217,10 @@
+ )
+ # endif
+ {
+- for (i = 0; i < 12; i++)
++ for (i = 0; i < 14; i++)
+ {
+ int j;
+- for (j = view_x0; j < (view_x1 - view_x0) - 5; j++)
++ for (j = view_x0; j < view_x1 - 5; j++)
+ {
+ gotoxy (j + 1, i + y);
+ set_attrib (normal_color);
+@@ -232,7 +232,7 @@
+ gotoxy (view_x0 + 1, y);
+
+ putchar (disp_ul);
+- for (i = 0; i < view_x1 - 7; i++)
++ for (i = view_x0; i < view_x1 - 7; i++)
+ putchar (disp_horiz);
+ putchar (disp_ur);
+
+@@ -1448,6 +1448,11 @@
+ cursor(1);
+ return;
+ }
++ else if (ch == '\b') {
++ if (fontx < view_x0)
++ SetXY(fontx - 1, fonty);
++ return;
++ }
+
+ text[fonty * 80 + fontx] = ch;
+