From 2bf905c893bac50e2536ad24e6ee5a1eac7d6da8 Mon Sep 17 00:00:00 2001
From: James Meyer <james.meyer@operamail.com>
Date: Mon, 20 Sep 2010 03:14:50 +0000
Subject: grub-gfx: added grub-gfx to replace the standard grub.

---
 abs/core-testing/grub-gfx.tar.gz                   |  Bin 0 -> 28009 bytes
 .../grub-gfx/040_all_grub-0.96-nxstack.patch       |  623 ++++++++++
 .../grub-gfx/05-grub-0.97-initrdaddr.diff          |   16 +
 abs/core-testing/grub-gfx/PKGBUILD                 |  106 ++
 abs/core-testing/grub-gfx/ext4.patch               |  263 ++++
 abs/core-testing/grub-gfx/grub-0.97-graphics.patch | 1293 ++++++++++++++++++++
 abs/core-testing/grub-gfx/grub-gfx.install         |   46 +
 abs/core-testing/grub-gfx/grub-inode-size.patch    |   94 ++
 abs/core-testing/grub-gfx/i2o.patch                |   45 +
 abs/core-testing/grub-gfx/install-grub             |  187 +++
 abs/core-testing/grub-gfx/intelmac.patch           |   67 +
 abs/core-testing/grub-gfx/menu.lst                 |   47 +
 abs/core-testing/grub-gfx/more-raid.patch          |  100 ++
 abs/core-testing/grub-gfx/special-devices.patch    |   18 +
 abs/core-testing/grub-gfx/splash.xpm.gz            |  Bin 0 -> 4019 bytes
 15 files changed, 2905 insertions(+)
 create mode 100644 abs/core-testing/grub-gfx.tar.gz
 create mode 100644 abs/core-testing/grub-gfx/040_all_grub-0.96-nxstack.patch
 create mode 100644 abs/core-testing/grub-gfx/05-grub-0.97-initrdaddr.diff
 create mode 100644 abs/core-testing/grub-gfx/PKGBUILD
 create mode 100644 abs/core-testing/grub-gfx/ext4.patch
 create mode 100644 abs/core-testing/grub-gfx/grub-0.97-graphics.patch
 create mode 100644 abs/core-testing/grub-gfx/grub-gfx.install
 create mode 100644 abs/core-testing/grub-gfx/grub-inode-size.patch
 create mode 100644 abs/core-testing/grub-gfx/i2o.patch
 create mode 100755 abs/core-testing/grub-gfx/install-grub
 create mode 100644 abs/core-testing/grub-gfx/intelmac.patch
 create mode 100644 abs/core-testing/grub-gfx/menu.lst
 create mode 100644 abs/core-testing/grub-gfx/more-raid.patch
 create mode 100644 abs/core-testing/grub-gfx/special-devices.patch
 create mode 100644 abs/core-testing/grub-gfx/splash.xpm.gz

diff --git a/abs/core-testing/grub-gfx.tar.gz b/abs/core-testing/grub-gfx.tar.gz
new file mode 100644
index 0000000..68f9e8a
Binary files /dev/null and b/abs/core-testing/grub-gfx.tar.gz differ
diff --git a/abs/core-testing/grub-gfx/040_all_grub-0.96-nxstack.patch b/abs/core-testing/grub-gfx/040_all_grub-0.96-nxstack.patch
new file mode 100644
index 0000000..121941c
--- /dev/null
+++ b/abs/core-testing/grub-gfx/040_all_grub-0.96-nxstack.patch
@@ -0,0 +1,623 @@
+Fix NX segfaulting on amd64.
+
+Patch by Peter Jones.
+
+http://lists.gnu.org/archive/html/bug-grub/2005-03/msg00011.html
+
+--- grub-0.97/grub/asmstub.c
++++ grub-0.97/grub/asmstub.c
+@@ -42,6 +42,7 @@
+ #include <sys/time.h>
+ #include <termios.h>
+ #include <signal.h>
++#include <sys/mman.h>
+ 
+ #ifdef __linux__
+ # include <sys/ioctl.h>		/* ioctl */
+@@ -79,7 +80,7 @@
+ struct apm_info apm_bios_info;
+ 
+ /* Emulation requirements. */
+-char *grub_scratch_mem = 0;
++void *grub_scratch_mem = 0;
+ 
+ struct geometry *disks = 0;
+ 
+@@ -103,14 +104,62 @@
+ static unsigned int serial_speed;
+ #endif /* SIMULATE_SLOWNESS_OF_SERIAL */
+ 
++/* This allocates page-aligned storage of the specified size, which must be
++ * a multiple of the page size as determined by calling sysconf(_SC_PAGESIZE)
++ */
++#ifdef __linux__
++static void *
++grub_mmap_alloc(size_t len)
++{
++  int mmap_flags = MAP_ANONYMOUS|MAP_PRIVATE|MAP_EXECUTABLE;
++
++#ifdef MAP_32BIT
++  mmap_flags |= MAP_32BIT;
++#endif
++  /* Mark the simulated stack executable, as GCC uses stack trampolines
++   * to implement nested functions. */
++  return mmap(NULL, len, PROT_READ|PROT_WRITE|PROT_EXEC, mmap_flags, -1, 0);
++}
++#else /* !defined(__linux__) */
++static void *
++grub_mmap_alloc(size_t len)
++{
++  int fd = 0, offset = 0, ret = 0;
++  void *pa = MAP_FAILED; 
++  char template[] = "/tmp/grub_mmap_alloc_XXXXXX";
++  errno_t e;
++
++  fd = mkstemp(template);
++  if (fd < 0)
++    return pa;
++
++  unlink(template);
++
++  ret = ftruncate(fd, len);
++  if (ret < 0)
++    return pa;
++
++  /* Mark the simulated stack executable, as GCC uses stack trampolines
++   * to implement nested functions. */
++  pa = mmap(NULL, len, PROT_READ|PROT_WRITE|PROT_EXEC,
++                  MAP_PRIVATE|MAP_EXECUTABLE, fd, offset);
++
++  e = errno;
++  close(fd);
++  errno = e;
++  return pa;
++}
++#endif /* defined(__linux__) */
++
+ /* The main entry point into this mess. */
+ int
+ grub_stage2 (void)
+ {
+   /* These need to be static, because they survive our stack transitions. */
+   static int status = 0;
+-  static char *realstack;
+-  char *scratch, *simstack;
++  static void *realstack;
++  void *simstack_alloc_base, *simstack;
++  size_t simstack_size, page_size;
+   int i;
+ 
+   /* We need a nested function so that we get a clean stack frame,
+@@ -140,9 +189,35 @@
+   }
+ 
+   assert (grub_scratch_mem == 0);
+-  scratch = malloc (0x100000 + EXTENDED_MEMSIZE + 15);
+-  assert (scratch);
+-  grub_scratch_mem = (char *) ((((int) scratch) >> 4) << 4);
++
++  /* Allocate enough pages for 0x100000 + EXTENDED_SIZE + 15, and
++   * make sure the memory is aligned to a multiple of the system's
++   * page size */
++  page_size = sysconf (_SC_PAGESIZE);
++  simstack_size = ( 0x100000 + EXTENDED_MEMSIZE + 15);
++  if (simstack_size % page_size)
++    {
++      /* If we're not on a page_size boundary, round up to the next one */
++      simstack_size &= ~(page_size-1);
++      simstack_size += page_size;
++    }
++
++  /* Add one for a PROT_NONE boundary page at each end. */
++  simstack_size += 2 * page_size;
++
++  simstack_alloc_base = grub_mmap_alloc(simstack_size);
++  assert (simstack_alloc_base != MAP_FAILED);
++
++  /* mark pages above and below our simstack area as innaccessable.
++   * If the implementation we're using doesn't support that, then the
++   * new protection modes are undefined.  It's safe to just ignore
++   * them, though.  It'd be nice if we knew that we'd get a SEGV for
++   * touching the area, but that's all.  it'd be nice to have. */
++  mprotect (simstack_alloc_base, page_size, PROT_NONE);
++  mprotect ((void *)((unsigned long)simstack_alloc_base +
++                         simstack_size - page_size),  page_size, PROT_NONE);
++
++  grub_scratch_mem = (void *)((unsigned long)simstack_alloc_base + page_size);
+ 
+   /* FIXME: simulate the memory holes using mprot, if available. */
+ 
+@@ -215,7 +290,7 @@
+   device_map = 0;
+   free (disks);
+   disks = 0;
+-  free (scratch);
++  munmap(simstack_alloc_base, simstack_size);
+   grub_scratch_mem = 0;
+ 
+   if (serial_device)
+--- grub-0.97/stage2/builtins.c
++++ grub-0.97/stage2/builtins.c
+@@ -131,63 +131,98 @@
+ }
+ 
+ 
++/* blocklist_read_helper nee disk_read_blocklist_func was a nested
++ * function, to which pointers were taken and exposed globally.  Even
++ * in the GNU-C nested functions extension, they have local linkage,
++ * and aren't guaranteed to be accessable *at all* outside of their 
++ * containing scope.
++ *
++ * Above and beyond all of that, the variables within blocklist_func_context
++ * are originally local variables, with local (not even static) linkage,
++ * from within blocklist_func.  These were each referenced by
++ * disk_read_blocklist_func, which is only called from other functions
++ * through a globally scoped pointer.
++ * 
++ * The documentation in GCC actually uses the words "all hell will break
++ * loose" to describe this scenario.
++ *
++ * Also, "start_sector" was also used uninitialized, but gcc doesn't warn
++ * about it (possibly because of the scoping madness?)
++ */
++   
++static struct {
++       int start_sector;
++       int num_sectors;
++       int num_entries;
++       int last_length;
++} blocklist_func_context = {
++       .start_sector = 0,
++       .num_sectors = 0,
++       .num_entries = 0,
++       .last_length = 0
++};
++
++/* Collect contiguous blocks into one entry as many as possible,
++   and print the blocklist notation on the screen.  */
++static void
++blocklist_read_helper (int sector, int offset, int length)
++{
++  int *start_sector = &blocklist_func_context.start_sector;
++  int *num_sectors = &blocklist_func_context.num_sectors;
++  int *num_entries = &blocklist_func_context.num_entries;
++  int *last_length = &blocklist_func_context.last_length;
++
++  if (*num_sectors > 0)
++  {
++    if (*start_sector + *num_sectors == sector
++      && offset == 0 && *last_length == SECTOR_SIZE)
++    {
++      *num_sectors++;
++      *last_length = length;
++      return;
++    }
++    else
++    {
++      if (*last_length == SECTOR_SIZE)
++        grub_printf ("%s%d+%d", *num_entries ? "," : "",
++          *start_sector - part_start, *num_sectors);
++      else if (*num_sectors > 1)
++        grub_printf ("%s%d+%d,%d[0-%d]", *num_entries ? "," : "",
++          *start_sector - part_start, *num_sectors-1,
++          *start_sector + *num_sectors-1 - part_start, 
++          *last_length);
++      else
++        grub_printf ("%s%d[0-%d]", *num_entries ? "," : "",
++          *start_sector - part_start, *last_length);
++      *num_entries++;
++      *num_sectors = 0;
++    }
++  }
++
++  if (offset > 0)
++  {
++    grub_printf("%s%d[%d-%d]", *num_entries ? "," : "",
++          sector-part_start, offset, offset+length);
++    *num_entries++;
++  }
++  else
++  {
++    *start_sector = sector;
++    *num_sectors = 1;
++    *last_length = length;
++  }
++}
++
+ /* blocklist */
+ static int
+ blocklist_func (char *arg, int flags)
+ {
+   char *dummy = (char *) RAW_ADDR (0x100000);
+-  int start_sector;
+-  int num_sectors = 0;
+-  int num_entries = 0;
+-  int last_length = 0;
+-
+-  auto void disk_read_blocklist_func (int sector, int offset, int length);
+-  
+-  /* Collect contiguous blocks into one entry as many as possible,
+-     and print the blocklist notation on the screen.  */
+-  auto void disk_read_blocklist_func (int sector, int offset, int length)
+-    {
+-      if (num_sectors > 0)
+-	{
+-	  if (start_sector + num_sectors == sector
+-	      && offset == 0 && last_length == SECTOR_SIZE)
+-	    {
+-	      num_sectors++;
+-	      last_length = length;
+-	      return;
+-	    }
+-	  else
+-	    {
+-	      if (last_length == SECTOR_SIZE)
+-		grub_printf ("%s%d+%d", num_entries ? "," : "",
+-			     start_sector - part_start, num_sectors);
+-	      else if (num_sectors > 1)
+-		grub_printf ("%s%d+%d,%d[0-%d]", num_entries ? "," : "",
+-			     start_sector - part_start, num_sectors-1,
+-			     start_sector + num_sectors-1 - part_start, 
+-			     last_length);
+-	      else
+-		grub_printf ("%s%d[0-%d]", num_entries ? "," : "",
+-			     start_sector - part_start, last_length);
+-	      num_entries++;
+-	      num_sectors = 0;
+-	    }
+-	}
+-
+-      if (offset > 0)
+-	{
+-	  grub_printf("%s%d[%d-%d]", num_entries ? "," : "",
+-		      sector-part_start, offset, offset+length);
+-	  num_entries++;
+-	}
+-      else
+-	{
+-	  start_sector = sector;
+-	  num_sectors = 1;
+-	  last_length = length;
+-	}
+-    }
+ 
++  int *start_sector = &blocklist_func_context.start_sector;
++  int *num_sectors = &blocklist_func_context.num_sectors;
++  int *num_entries = &blocklist_func_context.num_entries;
++  
+   /* Open the file.  */
+   if (! grub_open (arg))
+     return 1;
+@@ -204,15 +241,15 @@
+   grub_printf (")");
+ 
+   /* Read in the whole file to DUMMY.  */
+-  disk_read_hook = disk_read_blocklist_func;
++  disk_read_hook = blocklist_read_helper;
+   if (! grub_read (dummy, -1))
+     goto fail;
+ 
+   /* The last entry may not be printed yet.  Don't check if it is a
+    * full sector, since it doesn't matter if we read too much. */
+-  if (num_sectors > 0)
+-    grub_printf ("%s%d+%d", num_entries ? "," : "",
+-		 start_sector - part_start, num_sectors);
++  if (*num_sectors > 0)
++	grub_printf ("%s%d+%d", *num_entries ? "," : "",
++                *start_sector - part_start, *num_sectors);
+ 
+   grub_printf ("\n");
+   
+@@ -1868,6 +1905,77 @@
+ 
+ 
+ /* install */
++static struct {
++       int saved_sector;
++       int installaddr;
++       int installlist;
++       char *stage2_first_buffer;
++} install_func_context = {
++       .saved_sector = 0,
++       .installaddr = 0,
++       .installlist = 0,
++       .stage2_first_buffer = NULL,
++};
++
++/* Save the first sector of Stage2 in STAGE2_SECT.  */
++/* Formerly disk_read_savesect_func with local scope inside install_func */
++static void
++install_savesect_helper(int sector, int offset, int length)
++{
++  if (debug)
++    printf ("[%d]", sector);
++
++  /* ReiserFS has files which sometimes contain data not aligned
++     on sector boundaries.  Returning an error is better than
++     silently failing. */
++  if (offset != 0 || length != SECTOR_SIZE)
++    errnum = ERR_UNALIGNED;
++
++  install_func_context.saved_sector = sector;
++}
++
++/* Write SECTOR to INSTALLLIST, and update INSTALLADDR and  INSTALLSECT.  */
++/* Formerly disk_read_blocklist_func with local scope inside install_func */
++static void
++install_blocklist_helper (int sector, int offset, int length)
++{
++  int *installaddr = &install_func_context.installaddr;
++  int *installlist = &install_func_context.installlist;
++  char **stage2_first_buffer = &install_func_context.stage2_first_buffer;
++  /* Was the last sector full? */
++  static int last_length = SECTOR_SIZE;
++
++  if (debug)
++    printf("[%d]", sector);
++
++  if (offset != 0 || last_length != SECTOR_SIZE)
++    {
++      /* We found a non-sector-aligned data block. */
++      errnum = ERR_UNALIGNED;
++      return;
++    }
++
++  last_length = length;
++
++  if (*((unsigned long *) (*installlist - 4))
++      + *((unsigned short *) *installlist) != sector
++      || *installlist == (int) *stage2_first_buffer + SECTOR_SIZE + 4)
++    {
++      *installlist -= 8;
++
++      if (*((unsigned long *) (*installlist - 8)))
++        errnum = ERR_WONT_FIT;
++      else
++        {
++          *((unsigned short *) (*installlist + 2)) = (*installaddr >> 4);
++          *((unsigned long *) (*installlist - 4)) = sector;
++        }
++    }
++
++  *((unsigned short *) *installlist) += 1;
++  *installaddr += 512;
++}
++
+ static int
+ install_func (char *arg, int flags)
+ {
+@@ -1875,8 +1983,12 @@
+   char *stage1_buffer = (char *) RAW_ADDR (0x100000);
+   char *stage2_buffer = stage1_buffer + SECTOR_SIZE;
+   char *old_sect = stage2_buffer + SECTOR_SIZE;
+-  char *stage2_first_buffer = old_sect + SECTOR_SIZE;
+-  char *stage2_second_buffer = stage2_first_buffer + SECTOR_SIZE;
++  /* stage2_first_buffer used to be defined as:
++   * char *stage2_first_buffer = old_sect + SECTOR_SIZE;  */
++  char **stage2_first_buffer = &install_func_context.stage2_first_buffer;
++  /* and stage2_second_buffer was:
++   * char *stage2_second_buffer = stage2_first_buffer + SECTOR_SIZE; */
++  char *stage2_second_buffer = old_sect + SECTOR_SIZE + SECTOR_SIZE;
+   /* XXX: Probably SECTOR_SIZE is reasonable.  */
+   char *config_filename = stage2_second_buffer + SECTOR_SIZE;
+   char *dummy = config_filename + SECTOR_SIZE;
+@@ -1885,10 +1997,11 @@
+   int src_drive, src_partition, src_part_start;
+   int i;
+   struct geometry dest_geom, src_geom;
+-  int saved_sector;
++  int *saved_sector = &install_func_context.saved_sector;
+   int stage2_first_sector, stage2_second_sector;
+   char *ptr;
+-  int installaddr, installlist;
++  int *installaddr = &install_func_context.installaddr;
++  int *installlist = &install_func_context.installlist;
+   /* Point to the location of the name of a configuration file in Stage 2.  */
+   char *config_file_location;
+   /* If FILE is a Stage 1.5?  */
+@@ -1897,67 +2010,13 @@
+   int is_open = 0;
+   /* If LBA is forced?  */
+   int is_force_lba = 0;
+-  /* Was the last sector full? */
+-  int last_length = SECTOR_SIZE;
+-  
++
++  *stage2_first_buffer = old_sect + SECTOR_SIZE;
+ #ifdef GRUB_UTIL
+   /* If the Stage 2 is in a partition mounted by an OS, this will store
+      the filename under the OS.  */
+   char *stage2_os_file = 0;
+ #endif /* GRUB_UTIL */
+-  
+-  auto void disk_read_savesect_func (int sector, int offset, int length);
+-  auto void disk_read_blocklist_func (int sector, int offset, int length);
+-  
+-  /* Save the first sector of Stage2 in STAGE2_SECT.  */
+-  auto void disk_read_savesect_func (int sector, int offset, int length)
+-    {
+-      if (debug)
+-	printf ("[%d]", sector);
+-
+-      /* ReiserFS has files which sometimes contain data not aligned
+-         on sector boundaries.  Returning an error is better than
+-         silently failing. */
+-      if (offset != 0 || length != SECTOR_SIZE)
+-	errnum = ERR_UNALIGNED;
+-
+-      saved_sector = sector;
+-    }
+-
+-  /* Write SECTOR to INSTALLLIST, and update INSTALLADDR and
+-     INSTALLSECT.  */
+-  auto void disk_read_blocklist_func (int sector, int offset, int length)
+-    {
+-      if (debug)
+-	printf("[%d]", sector);
+-
+-      if (offset != 0 || last_length != SECTOR_SIZE)
+-	{
+-	  /* We found a non-sector-aligned data block. */
+-	  errnum = ERR_UNALIGNED;
+-	  return;
+-	}
+-
+-      last_length = length;
+-
+-      if (*((unsigned long *) (installlist - 4))
+-	  + *((unsigned short *) installlist) != sector
+-	  || installlist == (int) stage2_first_buffer + SECTOR_SIZE + 4)
+-	{
+-	  installlist -= 8;
+-
+-	  if (*((unsigned long *) (installlist - 8)))
+-	    errnum = ERR_WONT_FIT;
+-	  else
+-	    {
+-	      *((unsigned short *) (installlist + 2)) = (installaddr >> 4);
+-	      *((unsigned long *) (installlist - 4)) = sector;
+-	    }
+-	}
+-
+-      *((unsigned short *) installlist) += 1;
+-      installaddr += 512;
+-    }
+ 
+   /* First, check the GNU-style long option.  */
+   while (1)
+@@ -1987,10 +2049,10 @@
+   addr = skip_to (0, file);
+ 
+   /* Get the installation address.  */
+-  if (! safe_parse_maxint (&addr, &installaddr))
++  if (! safe_parse_maxint (&addr, installaddr))
+     {
+       /* ADDR is not specified.  */
+-      installaddr = 0;
++      *installaddr = 0;
+       ptr = addr;
+       errnum = 0;
+     }
+@@ -2084,17 +2146,17 @@
+     = (dest_drive & BIOS_FLAG_FIXED_DISK);
+   
+   /* Read the first sector of Stage 2.  */
+-  disk_read_hook = disk_read_savesect_func;
+-  if (grub_read (stage2_first_buffer, SECTOR_SIZE) != SECTOR_SIZE)
++  disk_read_hook = install_savesect_helper;
++  if (grub_read (*stage2_first_buffer, SECTOR_SIZE) != SECTOR_SIZE)
+     goto fail;
+ 
+-  stage2_first_sector = saved_sector;
++  stage2_first_sector = *saved_sector;
+   
+   /* Read the second sector of Stage 2.  */
+   if (grub_read (stage2_second_buffer, SECTOR_SIZE) != SECTOR_SIZE)
+     goto fail;
+ 
+-  stage2_second_sector = saved_sector;
++  stage2_second_sector = *saved_sector;
+   
+   /* Check for the version of Stage 2.  */
+   if (*((short *) (stage2_second_buffer + STAGE2_VER_MAJ_OFFS))
+@@ -2110,27 +2172,27 @@
+ 
+   /* If INSTALLADDR is not specified explicitly in the command-line,
+      determine it by the Stage 2 id.  */
+-  if (! installaddr)
++  if (! *installaddr)
+     {
+       if (! is_stage1_5)
+ 	/* Stage 2.  */
+-	installaddr = 0x8000;
++	*installaddr = 0x8000;
+       else
+ 	/* Stage 1.5.  */
+-	installaddr = 0x2000;
++	*installaddr = 0x2000;
+     }
+ 
+   *((unsigned long *) (stage1_buffer + STAGE1_STAGE2_SECTOR))
+     = stage2_first_sector;
+   *((unsigned short *) (stage1_buffer + STAGE1_STAGE2_ADDRESS))
+-    = installaddr;
++    = *installaddr;
+   *((unsigned short *) (stage1_buffer + STAGE1_STAGE2_SEGMENT))
+-    = installaddr >> 4;
++    = *installaddr >> 4;
+ 
+-  i = (int) stage2_first_buffer + SECTOR_SIZE - 4;
++  i = (int) *stage2_first_buffer + SECTOR_SIZE - 4;
+   while (*((unsigned long *) i))
+     {
+-      if (i < (int) stage2_first_buffer
++      if (i < (int) *stage2_first_buffer
+ 	  || (*((int *) (i - 4)) & 0x80000000)
+ 	  || *((unsigned short *) i) >= 0xA00
+ 	  || *((short *) (i + 2)) == 0)
+@@ -2144,13 +2206,13 @@
+       i -= 8;
+     }
+ 
+-  installlist = (int) stage2_first_buffer + SECTOR_SIZE + 4;
+-  installaddr += SECTOR_SIZE;
++  *installlist = (int) *stage2_first_buffer + SECTOR_SIZE + 4;
++  *installaddr += SECTOR_SIZE;
+   
+   /* Read the whole of Stage2 except for the first sector.  */
+   grub_seek (SECTOR_SIZE);
+ 
+-  disk_read_hook = disk_read_blocklist_func;
++  disk_read_hook = install_blocklist_helper;
+   if (! grub_read (dummy, -1))
+     goto fail;
+   
+@@ -2233,7 +2295,7 @@
+ 	  /* Skip the first sector.  */
+ 	  grub_seek (SECTOR_SIZE);
+ 	  
+-	  disk_read_hook = disk_read_savesect_func;
++	  disk_read_hook = install_savesect_helper;
+ 	  if (grub_read (stage2_buffer, SECTOR_SIZE) != SECTOR_SIZE)
+ 	    goto fail;
+ 	  
+@@ -2303,7 +2365,7 @@
+ 	  else
+ #endif /* GRUB_UTIL */
+ 	    {
+-	      if (! devwrite (saved_sector - part_start, 1, stage2_buffer))
++	      if (! devwrite (*saved_sector - part_start, 1, stage2_buffer))
+ 		goto fail;
+ 	    }
+ 	}
+@@ -2325,7 +2387,7 @@
+ 	  goto fail;
+ 	}
+ 
+-      if (fwrite (stage2_first_buffer, 1, SECTOR_SIZE, fp) != SECTOR_SIZE)
++      if (fwrite (*stage2_first_buffer, 1, SECTOR_SIZE, fp) != SECTOR_SIZE)
+ 	{
+ 	  fclose (fp);
+ 	  errnum = ERR_WRITE;
+@@ -2352,7 +2414,7 @@
+ 	goto fail;
+ 
+       if (! devwrite (stage2_first_sector - src_part_start, 1,
+-		      stage2_first_buffer))
++		      *stage2_first_buffer))
+ 	goto fail;
+ 
+       if (! devwrite (stage2_second_sector - src_part_start, 1,
+--- grub-0.97/stage2/shared.h
++++ grub-0.97/stage2/shared.h
+@@ -36,8 +36,8 @@
+ 
+ /* Maybe redirect memory requests through grub_scratch_mem. */
+ #ifdef GRUB_UTIL
+-extern char *grub_scratch_mem;
+-# define RAW_ADDR(x) ((x) + (int) grub_scratch_mem)
++extern void *grub_scratch_mem;
++# define RAW_ADDR(x) ((x) + (unsigned long) grub_scratch_mem)
+ # define RAW_SEG(x) (RAW_ADDR ((x) << 4) >> 4)
+ #else
+ # define RAW_ADDR(x) (x)
diff --git a/abs/core-testing/grub-gfx/05-grub-0.97-initrdaddr.diff b/abs/core-testing/grub-gfx/05-grub-0.97-initrdaddr.diff
new file mode 100644
index 0000000..ccf5f3e
--- /dev/null
+++ b/abs/core-testing/grub-gfx/05-grub-0.97-initrdaddr.diff
@@ -0,0 +1,16 @@
+--- grub-0.96/stage2/boot.c
++++ grub-0.96/stage2/boot.c
+@@ -824,8 +824,11 @@
+     moveto = (mbi.mem_upper + 0x400) << 10;
+   
+   moveto = (moveto - len) & 0xfffff000;
+-  max_addr = (lh->header == LINUX_MAGIC_SIGNATURE && lh->version >= 0x0203
+-	      ? lh->initrd_addr_max : LINUX_INITRD_MAX_ADDRESS);
++  max_addr = LINUX_INITRD_MAX_ADDRESS;
++  if (lh->header == LINUX_MAGIC_SIGNATURE &&
++      lh->version >= 0x0203 &&
++      lh->initrd_addr_max < max_addr)
++    max_addr = lh->initrd_addr_max;
+   if (moveto + len >= max_addr)
+     moveto = (max_addr - len) & 0xfffff000;
+   
diff --git a/abs/core-testing/grub-gfx/PKGBUILD b/abs/core-testing/grub-gfx/PKGBUILD
new file mode 100644
index 0000000..5d95294
--- /dev/null
+++ b/abs/core-testing/grub-gfx/PKGBUILD
@@ -0,0 +1,106 @@
+# Maintainer: Douglas Soares de Andrade <dsandrade@gmail.com>
+# Contributor: judd <jvinet@zeroflux.org>
+# Contributor: Mario A. Vazquez
+# Contributor: Jerzy Goca <juras256@epf.pl>
+
+pkgname=grub
+pkgver=0.97
+pkgrel=43
+pkgdesc="A GNU multiboot boot loader"
+arch=('i686' 'x86_64')
+license=('GPL')
+url="http://www.gnu.org/software/grub/"
+depends=('ncurses')
+makedepends=('automake>=1.10' 'autoconf>=2.61' 'patch')
+#conflicts=('grub')
+groups=('base')
+provides=('grub')
+source=(ftp://alpha.gnu.org/gnu/grub/grub-$pkgver.tar.gz \
+        menu.lst install-grub grub-0.97-graphics.patch \
+        splash.xpm.gz grub-inode-size.patch \
+        040_all_grub-0.96-nxstack.patch \
+        05-grub-0.97-initrdaddr.diff ext4.patch \
+        i2o.patch special-devices.patch more-raid.patch intelmac.patch)
+backup=('boot/grub/menu.lst')
+install=grub-gfx.install
+
+build() {
+  cd $startdir/src/grub-$pkgver
+
+  #set destination architecture here
+  DESTARCH="i686"
+  #DESTARCH="x86_64"
+
+  # graphics patch
+  patch -p1 < ../grub-0.97-graphics.patch || return 1
+
+  # optimizations break the build -- disable them
+  # adding special devices to grub, patches are from fedora
+  patch -Np1 -i ../special-devices.patch || return 1
+  patch -Np1 -i ../i2o.patch || return 1
+  patch -Np1 -i ../more-raid.patch || return 1
+  patch -Np1 -i ../intelmac.patch || return 1
+  patch -Np1 -i ../grub-inode-size.patch || return 1
+  patch -Np1 -i ../ext4.patch || return 1
+
+  # correcting problems for new wersion of autotools
+  sed -i -e'/^AC_PROG_CC/ a\AM_PROG_CC_C_O\ ' configure.ac
+  sed -i -e'/^AC_PROG_CC/ a\AM_PROG_AS\ ' configure.ac
+  aclocal
+  autoconf
+  automake
+
+  #arch64 fixes for static build
+  if [ "$CARCH" = "x86_64" ]; then
+    echo "this package has to be build on i686, won't compile on x86_64"
+    sleep 5
+  else
+    if [ "$DESTARCH" = "x86_64" ]; then
+      # patch from gentoo for fixing a segfault
+      patch -Np1 -i ../040_all_grub-0.96-nxstack.patch || return 1
+      # patch from frugalware to make it boot when more than 2GB ram installed
+      patch -Np1 -i ../05-grub-0.97-initrdaddr.diff || return 1
+      CFLAGS="-static" ./configure --prefix=/usr --bindir=/bin --sbindir=/sbin
+    else
+      CFLAGS= ./configure --prefix=/usr --bindir=/bin --sbindir=/sbin
+    fi
+  fi
+
+  CFLAGS= make || return 1
+  make DESTDIR=$startdir/pkg install
+  install -D -m644 ../menu.lst $startdir/pkg/boot/grub/menu.lst
+  install -D -m755 ../install-grub $startdir/pkg/sbin/install-grub
+
+  # symlink for compatibility with the <=0.7 installer
+  mkdir -p $startdir/pkg/usr/share
+  ln -s ../lib/grub $startdir/pkg/usr/share/grub
+
+  # splashimage xpm install
+  install -D -m644 $startdir/splash.xpm.gz $startdir/pkg/boot/grub/splash.xpm.gz
+
+  # Create a symlink to people that was using it
+  pushd $startdir/pkg/boot/grub/
+  ln -s splash.xpm.gz arch.xpm.gz
+  popd
+
+  rm -f $pkgdir/usr/share/info/dir || return 1
+
+  if [ "$DESTARCH" = "x86_64" ]; then
+    # fool makepkg into building a x86_64 package
+    export CARCH="x86_64"
+  fi
+
+}
+md5sums=('cd3f3eb54446be6003156158d51f4884'
+         '58cfec4abda85307f779147ab9a6be48'
+         '3182c4ae4963a16930bc772bba89dacf'
+         '12f043616b51ce2ba82e46c9186a528d'
+         '342f59f24cf5de5f013eacda68e617eb'
+         'ada26cbc681907823cc4ff2a55b97866'
+         'eb9d69c46af3a0667c1f651817d7f075'
+         'ccd2d757e79e3a03dc19ede7391ed328'
+         '39e0f9a05b7e04aceb24fc7bc4893e3d'
+         '826fdbf446067f9861baf9f6a69a4583'
+         '49f6d4bcced0bc8bbcff273f3254bbfa'
+         'f41f702014a064918d7afc6fc23baa6e'
+         '175dc6b9f4ab94e8056c3afb3e34460a')
diff --git a/abs/core-testing/grub-gfx/ext4.patch b/abs/core-testing/grub-gfx/ext4.patch
new file mode 100644
index 0000000..8a2f9bd
--- /dev/null
+++ b/abs/core-testing/grub-gfx/ext4.patch
@@ -0,0 +1,263 @@
+diff -ruNp grub-0.97/stage2/fsys_ext2fs.c grub-0.97-patch/stage2/fsys_ext2fs.c
+--- grub-0.97/stage2/fsys_ext2fs.c      2004-08-08 20:19:18.000000000 +0200
++++ grub-0.97-patch/stage2/fsys_ext2fs.c        2007-12-29 16:25:19.000000000 
++0100
+@@ -51,6 +51,9 @@ typedef unsigned int __u32;
+ #define EXT2_TIND_BLOCK                 (EXT2_DIND_BLOCK + 1)
+ #define EXT2_N_BLOCKS                   (EXT2_TIND_BLOCK + 1)
+ 
++/* Inode flags */
++#define EXT4_EXTENTS_FL                 0x00080000 /* Inode uses extents */
++
+ /* include/linux/ext2_fs.h */
+ struct ext2_super_block
+   {
+@@ -191,6 +194,42 @@ struct ext2_dir_entry
+ #define EXT2_DIR_REC_LEN(name_len)      (((name_len) + 8 + EXT2_DIR_ROUND) & \
+                                          ~EXT2_DIR_ROUND)
+ 
++/* linux/ext4_fs_extents.h */
++/*
++ * This is the extent on-disk structure.
++ * It's used at the bottom of the tree.
++ */
++struct ext4_extent {
++    __u32 ee_block;       /* first logical block extent covers */
++    __u16 ee_len;         /* number of blocks covered by extent */
++    __u16 ee_start_hi;    /* high 16 bits of physical block */
++    __u32 ee_start;       /* low 32 bits of physical block */
++};
++
++/*
++ * This is index on-disk structure.
++ * It's used at all the levels except the bottom.
++ */
++struct ext4_extent_idx {
++    __u32 ei_block;       /* index covers logical blocks from 'block' */
++    __u32 ei_leaf;        /* pointer to the physical block of the next *
++                                 * level. leaf or next index could be there */
++    __u16 ei_leaf_hi;     /* high 16 bits of physical block */
++    __u16 ei_unused;
++};
++
++/*
++ * Each block (leaves and indexes), even inode-stored has header.
++ */
++struct ext4_extent_header {
++    __u16  eh_magic;       /* probably will support different formats */
++    __u16  eh_entries;     /* number of valid entries */
++    __u16  eh_max;         /* capacity of store in entries */
++    __u16  eh_depth;       /* has tree real underlying blocks? */
++    __u32  eh_generation;  /* generation of the tree */
++};
++
++#define EXT4_EXT_MAGIC          0xf30a
+ 
+ /* ext2/super.c */
+ #define log2(n) ffz(~(n))
+@@ -279,6 +318,26 @@ ext2_rdfsb (int fsblock, int buffer)
+                  EXT2_BLOCK_SIZE (SUPERBLOCK), (char *) buffer);
+ }
+ 
++/* Walk through extents index tree to find the good leaf */
++static struct ext4_extent_header * 
++ext4_recurse_extent_index(struct ext4_extent_header *extent_block, int logical_block)
++{
++  int i;
++  struct ext4_extent_idx *index = (struct ext4_extent_idx *) (extent_block + 1);
++  if (extent_block->eh_magic != EXT4_EXT_MAGIC)
++    return NULL;
++  if (extent_block->eh_depth == 0)
++    return extent_block;
++  for (i = 0; i < extent_block->eh_entries; i++)
++    {
++      if (logical_block < index[i].ei_block)
++        break;
++    }
++  if (i == 0 || !ext2_rdfsb(index[i-1].ei_leaf, DATABLOCK1))
++    return NULL;
++  return (ext4_recurse_extent_index((struct ext4_extent_header *) DATABLOCK1, logical_block));
++}
++
+ /* from
+   ext2/inode.c:ext2_bmap()
+ */
+--- grub-0.97/stage2/fsys_ext2fs.c~	2008-12-28 20:19:00.000000000 +0100
++++ grub-0.97/stage2/fsys_ext2fs.c	2008-12-28 20:19:00.000000000 +0100
+@@ -366,83 +366,106 @@
+     }
+   printf ("logical block %d\n", logical_block);
+ #endif /* E2DEBUG */
+-
+-  /* if it is directly pointed to by the inode, return that physical addr */
+-  if (logical_block < EXT2_NDIR_BLOCKS)
+-    {
+-#ifdef E2DEBUG
+-      printf ("returning %d\n", (unsigned char *) (INODE->i_block[logical_block]));
+-      printf ("returning %d\n", INODE->i_block[logical_block]);
+-#endif /* E2DEBUG */
+-      return INODE->i_block[logical_block];
+-    }
+-  /* else */
+-  logical_block -= EXT2_NDIR_BLOCKS;
+-  /* try the indirect block */
+-  if (logical_block < EXT2_ADDR_PER_BLOCK (SUPERBLOCK))
++  /* standard ext2 inode */
++  if (!(INODE->i_flags & EXT4_EXTENTS_FL))
+     {
+-      if (mapblock1 != 1
+-	  && !ext2_rdfsb (INODE->i_block[EXT2_IND_BLOCK], DATABLOCK1))
+-	{
+-	  errnum = ERR_FSYS_CORRUPT;
+-	  return -1;
+-	}
+-      mapblock1 = 1;
+-      return ((__u32 *) DATABLOCK1)[logical_block];
+-    }
+-  /* else */
+-  logical_block -= EXT2_ADDR_PER_BLOCK (SUPERBLOCK);
+-  /* now try the double indirect block */
+-  if (logical_block < (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2)))
+-    {
+-      int bnum;
+-      if (mapblock1 != 2
+-	  && !ext2_rdfsb (INODE->i_block[EXT2_DIND_BLOCK], DATABLOCK1))
+-	{
+-	  errnum = ERR_FSYS_CORRUPT;
+-	  return -1;
+-	}
+-      mapblock1 = 2;
+-      if ((bnum = (((__u32 *) DATABLOCK1)
+-		   [logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)]))
+-	  != mapblock2
+-	  && !ext2_rdfsb (bnum, DATABLOCK2))
+-	{
+-	  errnum = ERR_FSYS_CORRUPT;
+-	  return -1;
+-	}
+-      mapblock2 = bnum;
++      /* if it is directly pointed to by the inode, return that physical addr */
++      if (logical_block < EXT2_NDIR_BLOCKS)
++        {
++#ifdef E2DEBUG
++          printf ("returning %d\n", (unsigned char *) (INODE->i_block[logical_block]));
++          printf ("returning %d\n", INODE->i_block[logical_block]);
++#endif /* E2DEBUG */
++          return INODE->i_block[logical_block];
++        }
++      /* else */
++      logical_block -= EXT2_NDIR_BLOCKS;
++      /* try the indirect block */
++      if (logical_block < EXT2_ADDR_PER_BLOCK (SUPERBLOCK))
++        {
++          if (mapblock1 != 1
++         && !ext2_rdfsb (INODE->i_block[EXT2_IND_BLOCK], DATABLOCK1))
++       {
++         errnum = ERR_FSYS_CORRUPT;
++         return -1;
++       }
++          mapblock1 = 1;
++          return ((__u32 *) DATABLOCK1)[logical_block];
++        }
++      /* else */
++      logical_block -= EXT2_ADDR_PER_BLOCK (SUPERBLOCK);
++      /* now try the double indirect block */
++      if (logical_block < (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2)))
++        {
++          int bnum;
++          if (mapblock1 != 2
++         && !ext2_rdfsb (INODE->i_block[EXT2_DIND_BLOCK], DATABLOCK1))
++       {
++         errnum = ERR_FSYS_CORRUPT;
++         return -1;
++       }
++          mapblock1 = 2;
++          if ((bnum = (((__u32 *) DATABLOCK1)
++                  [logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)]))
++         != mapblock2
++         && !ext2_rdfsb (bnum, DATABLOCK2))
++       {
++         errnum = ERR_FSYS_CORRUPT;
++         return -1;
++       }
++          mapblock2 = bnum;
++          return ((__u32 *) DATABLOCK2)
++            [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
++        }
++      /* else */
++      mapblock2 = -1;
++      logical_block -= (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2));
++      if (mapblock1 != 3
++          && !ext2_rdfsb (INODE->i_block[EXT2_TIND_BLOCK], DATABLOCK1))
++        {
++          errnum = ERR_FSYS_CORRUPT;
++          return -1;
++        }
++      mapblock1 = 3;
++      if (!ext2_rdfsb (((__u32 *) DATABLOCK1)
++                  [logical_block >> (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)
++                                     * 2)],
++                  DATABLOCK2))
++        {
++          errnum = ERR_FSYS_CORRUPT;
++          return -1;
++        }
++      if (!ext2_rdfsb (((__u32 *) DATABLOCK2)
++                  [(logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK))
++                   & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)],
++                  DATABLOCK2))
++        {
++          errnum = ERR_FSYS_CORRUPT;
++          return -1;
++        }
+       return ((__u32 *) DATABLOCK2)
+-	[logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
+-    }
+-  /* else */
+-  mapblock2 = -1;
+-  logical_block -= (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2));
+-  if (mapblock1 != 3
+-      && !ext2_rdfsb (INODE->i_block[EXT2_TIND_BLOCK], DATABLOCK1))
+-    {
+-      errnum = ERR_FSYS_CORRUPT;
+-      return -1;
++       [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
+     }
+-  mapblock1 = 3;
+-  if (!ext2_rdfsb (((__u32 *) DATABLOCK1)
+-		   [logical_block >> (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)
+-				      * 2)],
+-		   DATABLOCK2))
+-    {
+-      errnum = ERR_FSYS_CORRUPT;
+-      return -1;
+-    }
+-  if (!ext2_rdfsb (((__u32 *) DATABLOCK2)
+-		   [(logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK))
+-		    & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)],
+-		   DATABLOCK2))
++  /* inode is in extents format */
++  else
+     {
++      int i;
++      struct ext4_extent_header *extent_hdr = ext4_recurse_extent_index((struct ext4_extent_header *) INODE->i_block, logical_block);
++      struct ext4_extent *extent = (struct ext4_extent *) (extent_hdr + 1);
++      if ( extent_hdr == NULL || extent_hdr->eh_magic != EXT4_EXT_MAGIC)
++      {
++        errnum = ERR_FSYS_CORRUPT;
++        return -1;
++      }
++      for (i = 0; i<extent_hdr->eh_entries; i++)
++        {
++          if (extent[i].ee_block <= logical_block && logical_block < extent[i].ee_block + extent[i].ee_len && !(extent[i].ee_len>>15))
++            return (logical_block - extent[i].ee_block + extent[i].ee_start);
++        }
++      /* We should not arrive here */
+       errnum = ERR_FSYS_CORRUPT;
+       return -1;
+     }
+-  return ((__u32 *) DATABLOCK2)
+-    [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
+ }
+ 
+ /* preconditions: all preconds of ext2fs_block_map */
diff --git a/abs/core-testing/grub-gfx/grub-0.97-graphics.patch b/abs/core-testing/grub-gfx/grub-0.97-graphics.patch
new file mode 100644
index 0000000..e0baa90
--- /dev/null
+++ b/abs/core-testing/grub-gfx/grub-0.97-graphics.patch
@@ -0,0 +1,1293 @@
+diff -urpN grub-0.97/configure.ac grub-0.97-gfx/configure.ac
+--- grub-0.97/configure.ac	2005-10-13 16:27:23.000000000 -0400
++++ grub-0.97-gfx/configure.ac	2005-10-13 16:27:35.000000000 -0400
+@@ -595,6 +595,11 @@ AC_ARG_ENABLE(diskless,
+   [  --enable-diskless       enable diskless support])
+ AM_CONDITIONAL(DISKLESS_SUPPORT, test "x$enable_diskless" = xyes)
+ 
++dnl Graphical splashscreen support
++AC_ARG_ENABLE(graphics,
++  [  --disable-graphics      disable graphics terminal support])
++AM_CONDITIONAL(GRAPHICS_SUPPORT, test "x$enable_graphics" != xno)
++
+ dnl Hercules terminal
+ AC_ARG_ENABLE(hercules,
+   [  --disable-hercules      disable hercules terminal support])
+diff -urpN grub-0.97/stage2/Makefile.am grub-0.97-gfx/stage2/Makefile.am
+--- grub-0.97/stage2/Makefile.am	2005-10-13 16:27:23.000000000 -0400
++++ grub-0.97-gfx/stage2/Makefile.am	2005-10-13 16:27:35.000000000 -0400
+@@ -7,7 +7,7 @@ noinst_HEADERS = apic.h defs.h dir.h dis
+         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 @@ libgrub_a_SOURCES = boot.c builtins.c ch
+ 	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 @@ else
+ 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 @@ pre_stage2_exec_SOURCES = asm.S bios.c b
+ 	cmdline.c common.c console.c disk_io.c fsys_ext2fs.c \
+ 	fsys_fat.c fsys_ffs.c fsys_iso9660.c fsys_jfs.c fsys_minix.c \
+ 	fsys_reiserfs.c fsys_ufs2.c fsys_vstafs.c fsys_xfs.c gunzip.c \
+-	hercules.c md5.c serial.c smp-imps.c stage2.c terminfo.c tparm.c
++	hercules.c md5.c serial.c smp-imps.c stage2.c terminfo.c tparm.c \
++	graphics.c
+ pre_stage2_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS)
+ pre_stage2_exec_CCASFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS)
+ pre_stage2_exec_LDFLAGS = $(PRE_STAGE2_LINK)
+diff -urpN grub-0.97/stage2/asm.S grub-0.97-gfx/stage2/asm.S
+--- grub-0.97/stage2/asm.S	2005-10-13 16:27:23.000000000 -0400
++++ grub-0.97-gfx/stage2/asm.S	2005-10-13 16:27:35.000000000 -0400
+@@ -2216,6 +2216,156 @@ ENTRY(console_setcursor)
+ 	pop	%ebx
+ 	pop	%ebp
+ 	ret
++
++/* graphics mode functions */
++#ifdef SUPPORT_GRAPHICS
++VARIABLE(cursorX)
++.word	0
++VARIABLE(cursorY)
++.word	0
++VARIABLE(cursorCount)
++.word 0
++VARIABLE(cursorBuf)
++.byte	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
++
++	
++/*
++ * int set_videomode(mode)
++ * BIOS call "INT 10H Function 0h" to set video mode
++ *	Call with	%ah = 0x0
++ *			%al = video mode
++ *      Returns old videomode.
++ */
++ENTRY(set_videomode)
++	push	%ebp
++	push	%ebx
++	push	%ecx
++
++	movb	0x10(%esp), %cl
++
++	call	EXT_C(prot_to_real)
++	.code16
++
++	xorw	%bx, %bx
++	movb	$0xf, %ah
++	int	$0x10			/* Get Current Video mode */
++	movb	%al, %ch
++	xorb	%ah, %ah
++	movb	%cl, %al
++        int	$0x10			/* Set Video mode */
++
++	DATA32	call	EXT_C(real_to_prot)
++	.code32
++
++	xorb	%ah, %ah
++	movb	%ch, %al
++
++	pop	%ecx
++	pop	%ebx
++	pop	%ebp
++	ret
++
++
++/*
++ * unsigned char * graphics_get_font()
++ * BIOS call "INT 10H Function 11h" to set font
++ *      Call with       %ah = 0x11
++ */
++ENTRY(graphics_get_font)
++	push	%ebp
++	push	%ebx
++	push	%ecx
++	push	%edx
++
++	call	EXT_C(prot_to_real)
++	.code16
++
++	movw	$0x1130, %ax
++	movb	$6, %bh		/* font 8x16 */
++	int	$0x10
++	movw	%bp, %dx
++	movw	%es, %cx
++
++	DATA32	call	EXT_C(real_to_prot)
++	.code32
++
++	xorl	%eax, %eax
++	movw	%cx, %ax
++	shll	$4, %eax
++	movw	%dx, %ax
++
++	pop	%edx
++	pop	%ecx
++	pop	%ebx
++	pop	%ebp
++	ret
++	
++
++	
++/*
++ * graphics_set_palette(index, red, green, blue)
++ * BIOS call "INT 10H Function 10h" to set individual dac register
++ *	Call with	%ah = 0x10
++ *			%bx = register number
++ *			%ch = new value for green (0-63)
++ *			%cl = new value for blue (0-63)
++ *			%dh = new value for red (0-63)
++ */
++
++ENTRY(graphics_set_palette)
++	push	%ebp
++	push	%eax
++	push	%ebx
++	push	%ecx
++	push	%edx
++
++	movw	$0x3c8, %bx		/* address write mode register */
++
++	/* wait vertical retrace */
++
++	movw	$0x3da, %dx
++l1b:	inb	%dx, %al	/* wait vertical active display */
++	test	$8, %al
++	jnz	l1b
++
++l2b:	inb	%dx, %al	/* wait vertical retrace */
++	test	$8, %al
++	jnz	l2b
++
++	mov	%bx, %dx
++	movb	0x18(%esp), %al		/* index */
++	outb	%al, %dx
++	inc	%dx
++
++	movb	0x1c(%esp), %al		/* red */
++	outb	%al, %dx
++
++	movb	0x20(%esp), %al		/* green */
++	outb	%al, %dx
++
++	movb	0x24(%esp), %al		/* blue */
++	outb	%al, %dx
++
++	movw	0x18(%esp), %bx
++
++	call	EXT_C(prot_to_real)
++	.code16
++
++	movb	%bl, %bh
++	movw	$0x1000, %ax
++	int	$0x10
++
++	DATA32	call	EXT_C(real_to_prot)
++	.code32	
++
++	pop	%edx
++	pop	%ecx
++	pop	%ebx
++	pop	%eax
++	pop	%ebp
++	ret
++
++#endif /* SUPPORT_GRAPHICS */
+ 		
+ /*
+  * getrtsecs()
+diff -urpN grub-0.97/stage2/builtins.c grub-0.97-gfx/stage2/builtins.c
+--- grub-0.97/stage2/builtins.c	2005-10-13 16:27:23.000000000 -0400
++++ grub-0.97-gfx/stage2/builtins.c	2005-10-13 16:27:35.000000000 -0400
+@@ -852,6 +852,138 @@ static struct builtin builtin_dhcp =
+ };
+ #endif /* SUPPORT_NETBOOT */
+ 
++static int terminal_func (char *arg, int flags);
++
++#ifdef SUPPORT_GRAPHICS
++
++static int splashimage_func(char *arg, int flags) {
++    char splashimage[64];
++    int i;
++    
++    /* filename can only be 64 characters due to our buffer size */
++    if (strlen(arg) > 63)
++	return 1;
++    if (flags == BUILTIN_CMDLINE) {
++	if (!grub_open(arg))
++	    return 1;
++	grub_close();
++    }
++
++    strcpy(splashimage, arg);
++
++    /* get rid of TERM_NEED_INIT from the graphics terminal. */
++    for (i = 0; term_table[i].name; i++) {
++	if (grub_strcmp (term_table[i].name, "graphics") == 0) {
++	    term_table[i].flags &= ~TERM_NEED_INIT;
++	    break;
++	}
++    }
++    
++    graphics_set_splash(splashimage);
++
++    if (flags == BUILTIN_CMDLINE && graphics_inited) {
++	graphics_end();
++	graphics_init();
++	graphics_cls();
++    }
++
++    /* FIXME: should we be explicitly switching the terminal as a 
++     * side effect here? */
++    terminal_func("graphics", flags);
++
++    return 0;
++}
++
++static struct builtin builtin_splashimage =
++{
++  "splashimage",
++  splashimage_func,
++  BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
++  "splashimage FILE",
++  "Load FILE as the background image when in graphics mode."
++};
++
++
++/* foreground */
++static int
++foreground_func(char *arg, int flags)
++{
++    if (grub_strlen(arg) == 6) {
++	int r = ((hex(arg[0]) << 4) | hex(arg[1])) >> 2;
++	int g = ((hex(arg[2]) << 4) | hex(arg[3])) >> 2;
++	int b = ((hex(arg[4]) << 4) | hex(arg[5])) >> 2;
++
++	foreground = (r << 16) | (g << 8) | b;
++	if (graphics_inited)
++	    graphics_set_palette(15, r, g, b);
++
++	return (0);
++    }
++
++    return (1);
++}
++
++static struct builtin builtin_foreground =
++{
++  "foreground",
++  foreground_func,
++  BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
++  "foreground RRGGBB",
++  "Sets the foreground color when in graphics mode."
++  "RR is red, GG is green, and BB blue. Numbers must be in hexadecimal."
++};
++
++
++/* background */
++static int
++background_func(char *arg, int flags)
++{
++    if (grub_strlen(arg) == 6) {
++	int r = ((hex(arg[0]) << 4) | hex(arg[1])) >> 2;
++	int g = ((hex(arg[2]) << 4) | hex(arg[3])) >> 2;
++	int b = ((hex(arg[4]) << 4) | hex(arg[5])) >> 2;
++
++	background = (r << 16) | (g << 8) | b;
++	if (graphics_inited)
++	    graphics_set_palette(0, r, g, b);
++	return (0);
++    }
++
++    return (1);
++}
++
++static struct builtin builtin_background =
++{
++  "background",
++  background_func,
++  BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
++  "background RRGGBB",
++  "Sets the background color when in graphics mode."
++  "RR is red, GG is green, and BB blue. Numbers must be in hexadecimal."
++};
++
++#endif /* SUPPORT_GRAPHICS */
++
++
++/* clear */
++static int 
++clear_func() 
++{
++  if (current_term->cls)
++    current_term->cls();
++
++  return 0;
++}
++
++static struct builtin builtin_clear =
++{
++  "clear",
++  clear_func,
++  BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
++  "clear",
++  "Clear the screen"
++};
++
+ 
+ /* displayapm */
+ static int
+@@ -4085,7 +4217,7 @@ static struct builtin builtin_setup =
+ };
+ 
+ 
+-#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 +4376,21 @@ terminal_func (char *arg, int flags)
+  end:
+   current_term = term_table + default_term;
+   current_term->flags = term_flags;
+-  
++
+   if (lines)
+     max_lines = lines;
+   else
+-    /* 24 would be a good default value.  */
+-    max_lines = 24;
+-  
++    max_lines = current_term->max_lines;
++
+   /* If the interface is currently the command-line,
+      restart it to repaint the screen.  */
+-  if (current_term != prev_term && (flags & BUILTIN_CMDLINE))
++  if ((current_term != prev_term) && (flags & BUILTIN_CMDLINE)){
++    if (prev_term->shutdown)
++      prev_term->shutdown();
++    if (current_term->startup)
++      current_term->startup();
+     grub_longjmp (restart_cmdline_env, 0);
++  }
+   
+   return 0;
+ }
+@@ -4264,7 +4400,7 @@ static struct builtin builtin_terminal =
+   "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 +4412,7 @@ static struct builtin builtin_terminal =
+   " 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,6 +4931,9 @@ static struct builtin builtin_vbeprobe =
+ /* 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
+@@ -4802,6 +4941,7 @@ struct builtin *builtin_table[] =
+ #endif /* SUPPORT_NETBOOT */
+   &builtin_cat,
+   &builtin_chainloader,
++  &builtin_clear,
+   &builtin_cmp,
+   &builtin_color,
+   &builtin_configfile,
+@@ -4821,6 +4961,9 @@ struct builtin *builtin_table[] =
+   &builtin_embed,
+   &builtin_fallback,
+   &builtin_find,
++#ifdef SUPPORT_GRAPHICS
++  &builtin_foreground,
++#endif
+   &builtin_fstest,
+   &builtin_geometry,
+   &builtin_halt,
+@@ -4864,9 +5007,12 @@ struct builtin *builtin_table[] =
+ #endif /* SUPPORT_SERIAL */
+   &builtin_setkey,
+   &builtin_setup,
+-#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES)
++#ifdef SUPPORT_GRAPHICS
++  &builtin_splashimage,
++#endif /* SUPPORT_GRAPHICS */
++#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) || defined(SUPPORT_GRAPHICS)
+   &builtin_terminal,
+-#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES */
++#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES || SUPPORT_GRAPHICS */
+ #ifdef SUPPORT_SERIAL
+   &builtin_terminfo,
+ #endif /* SUPPORT_SERIAL */
+diff -urpN grub-0.97/stage2/char_io.c grub-0.97-gfx/stage2/char_io.c
+--- grub-0.97/stage2/char_io.c	2005-10-13 16:27:23.000000000 -0400
++++ grub-0.97-gfx/stage2/char_io.c	2005-10-13 16:27:35.000000000 -0400
+@@ -35,6 +35,7 @@ struct term_entry term_table[] =
+     {
+       "console",
+       0,
++      24,
+       console_putchar,
+       console_checkkey,
+       console_getkey,
+@@ -43,13 +44,16 @@ struct term_entry term_table[] =
+       console_cls,
+       console_setcolorstate,
+       console_setcolor,
+-      console_setcursor
++      console_setcursor,
++      0, 
++      0
+     },
+ #ifdef SUPPORT_SERIAL
+     {
+       "serial",
+       /* A serial device must be initialized.  */
+       TERM_NEED_INIT,
++      24,
+       serial_putchar,
+       serial_checkkey,
+       serial_getkey,
+@@ -58,6 +62,8 @@ struct term_entry term_table[] =
+       serial_cls,
+       serial_setcolorstate,
+       0,
++      0,
++      0, 
+       0
+     },
+ #endif /* SUPPORT_SERIAL */
+@@ -65,6 +71,7 @@ struct term_entry term_table[] =
+     {
+       "hercules",
+       0,
++      24,
+       hercules_putchar,
+       console_checkkey,
+       console_getkey,
+@@ -73,9 +80,28 @@ struct term_entry term_table[] =
+       hercules_cls,
+       hercules_setcolorstate,
+       hercules_setcolor,
+-      hercules_setcursor
++      hercules_setcursor,
++      0,
++      0
+     },      
+ #endif /* SUPPORT_HERCULES */
++#ifdef SUPPORT_GRAPHICS
++    { "graphics",
++      TERM_NEED_INIT, /* flags */
++      30, /* number of lines */
++      graphics_putchar, /* putchar */
++      console_checkkey, /* checkkey */
++      console_getkey, /* getkey */
++      graphics_getxy, /* getxy */
++      graphics_gotoxy, /* gotoxy */
++      graphics_cls, /* cls */
++      graphics_setcolorstate, /* setcolorstate */
++      graphics_setcolor, /* setcolor */
++      graphics_setcursor, /* nocursor */
++      graphics_init, /* initialize */
++      graphics_end /* shutdown */
++    },
++#endif /* SUPPORT_GRAPHICS */
+     /* This must be the last entry.  */
+     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+   };
+@@ -1046,13 +1072,15 @@ grub_putchar (int c)
+ 		 the following grub_printf call will print newlines.  */
+ 	      count_lines = -1;
+ 
++	      grub_printf("\n");
+ 	      if (current_term->setcolorstate)
+ 		current_term->setcolorstate (COLOR_STATE_HIGHLIGHT);
+ 	      
+-	      grub_printf ("\n[Hit return to continue]");
++	      grub_printf ("[Hit return to continue]");
+ 
+ 	      if (current_term->setcolorstate)
+ 		current_term->setcolorstate (COLOR_STATE_NORMAL);
++	        
+ 	      
+ 	      do
+ 		{
+@@ -1090,7 +1118,7 @@ void
+ 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 +1245,16 @@ memcheck (int addr, int len)
+   return ! errnum;
+ }
+ 
++void
++grub_memcpy(void *dest, const void *src, int len)
++{
++  int i;
++  register char *d = (char*)dest, *s = (char*)src;
++
++  for (i = 0; i < len; i++)
++    d[i] = s[i];
++}
++
+ void *
+ grub_memmove (void *to, const void *from, int len)
+ {
+diff -urpN grub-0.97/stage2/graphics.c grub-0.97-gfx/stage2/graphics.c
+--- grub-0.97/stage2/graphics.c	1969-12-31 20:00:00.000000000 -0400
++++ grub-0.97-gfx/stage2/graphics.c	2005-10-13 16:27:35.000000000 -0400
+@@ -0,0 +1,552 @@
++/* 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>
++ */
++/*
++ *  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[64];
++
++#define VSHADOW VSHADOW1
++unsigned char VSHADOW1[38400];
++unsigned char VSHADOW2[38400];
++unsigned char VSHADOW4[38400];
++unsigned char VSHADOW8[38400];
++
++/* constants to define the viewable area */
++const int x0 = 0;
++const int x1 = 80;
++const int y0 = 0;
++const int y1 = 30;
++
++/* text buffer has to be kept around so that we can write things as we
++ * scroll and the like */
++unsigned short text[80 * 30];
++
++/* why do these have to be kept here? */
++int foreground = (63 << 16) | (63 << 8) | (63), background = 0, border = 0;
++
++/* current position */
++static int fontx = 0;
++static int fonty = 0;
++
++/* global state so that we don't try to recursively scroll or cursor */
++static int no_scroll = 0;
++
++/* color state */
++static int graphics_standard_color = A_NORMAL;
++static int graphics_normal_color = A_NORMAL;
++static int graphics_highlight_color = A_REVERSE;
++static int graphics_current_color = A_NORMAL;
++static color_state graphics_color_state = COLOR_STATE_STANDARD;
++
++
++/* graphics local functions */
++static void graphics_setxy(int col, int row);
++static void graphics_scroll();
++
++/* FIXME: where do these really belong? */
++static inline void outb(unsigned short port, unsigned char val)
++{
++    __asm __volatile ("outb %0,%1"::"a" (val), "d" (port));
++}
++
++static void MapMask(int value) {
++    outb(0x3c4, 2);
++    outb(0x3c5, value);
++}
++
++/* bit mask register */
++static void BitMask(int value) {
++    outb(0x3ce, 8);
++    outb(0x3cf, value);
++}
++
++
++
++/* Set the splash image */
++void graphics_set_splash(char *splashfile) {
++    grub_strcpy(splashimage, splashfile);
++}
++
++/* Get the current splash image */
++char *graphics_get_splash(void) {
++    return splashimage;
++}
++
++/* Initialize a vga16 graphics display with the palette based off of
++ * the image in splashimage.  If the image doesn't exist, leave graphics
++ * mode.  */
++int graphics_init()
++{
++    if (!graphics_inited) {
++        saved_videomode = set_videomode(0x12);
++    }
++
++    if (!read_image(splashimage)) {
++        set_videomode(saved_videomode);
++        grub_printf("failed to read image\n");
++        return 0;
++    }
++
++    font8x16 = (unsigned char*)graphics_get_font();
++
++    graphics_inited = 1;
++
++    /* make sure that the highlight color is set correctly */
++    graphics_highlight_color = ((graphics_normal_color >> 4) | 
++				((graphics_normal_color & 0xf) << 4));
++
++    return 1;
++}
++
++/* Leave graphics mode */
++void graphics_end(void)
++{
++    if (graphics_inited) {
++        set_videomode(saved_videomode);
++        graphics_inited = 0;
++    }
++}
++
++/* Print ch on the screen.  Handle any needed scrolling or the like */
++void graphics_putchar(int ch) {
++    ch &= 0xff;
++
++    graphics_cursor(0);
++
++    if (ch == '\n') {
++        if (fonty + 1 < y1)
++            graphics_setxy(fontx, fonty + 1);
++        else
++            graphics_scroll();
++        graphics_cursor(1);
++        return;
++    } else if (ch == '\r') {
++        graphics_setxy(x0, fonty);
++        graphics_cursor(1);
++        return;
++    }
++
++    graphics_cursor(0);
++
++    text[fonty * 80 + fontx] = ch;
++    text[fonty * 80 + fontx] &= 0x00ff;
++    if (graphics_current_color & 0xf0)
++        text[fonty * 80 + fontx] |= 0x100;
++
++    graphics_cursor(0);
++
++    if ((fontx + 1) >= x1) {
++        graphics_setxy(x0, fonty);
++        if (fonty + 1 < y1)
++            graphics_setxy(x0, fonty + 1);
++        else
++            graphics_scroll();
++    } else {
++        graphics_setxy(fontx + 1, fonty);
++    }
++
++    graphics_cursor(1);
++}
++
++/* get the current location of the cursor */
++int graphics_getxy(void) {
++    return (fontx << 8) | fonty;
++}
++
++void graphics_gotoxy(int x, int y) {
++    graphics_cursor(0);
++
++    graphics_setxy(x, y);
++
++    graphics_cursor(1);
++}
++
++void graphics_cls(void) {
++    int i;
++    unsigned char *mem, *s1, *s2, *s4, *s8;
++
++    graphics_cursor(0);
++    graphics_gotoxy(x0, y0);
++
++    mem = (unsigned char*)VIDEOMEM;
++    s1 = (unsigned char*)VSHADOW1;
++    s2 = (unsigned char*)VSHADOW2;
++    s4 = (unsigned char*)VSHADOW4;
++    s8 = (unsigned char*)VSHADOW8;
++
++    for (i = 0; i < 80 * 30; i++)
++        text[i] = ' ';
++    graphics_cursor(1);
++
++    BitMask(0xff);
++
++    /* plano 1 */
++    MapMask(1);
++    grub_memcpy(mem, s1, 38400);
++
++    /* plano 2 */
++    MapMask(2);
++    grub_memcpy(mem, s2, 38400);
++
++    /* plano 3 */
++    MapMask(4);
++    grub_memcpy(mem, s4, 38400);
++
++    /* plano 4 */
++    MapMask(8);
++    grub_memcpy(mem, s8, 38400);
++
++    MapMask(15);
++ 
++}
++
++void graphics_setcolorstate (color_state state) {
++    switch (state) {
++    case COLOR_STATE_STANDARD:
++        graphics_current_color = graphics_standard_color;
++        break;
++    case COLOR_STATE_NORMAL:
++        graphics_current_color = graphics_normal_color;
++        break;
++    case COLOR_STATE_HIGHLIGHT:
++        graphics_current_color = graphics_highlight_color;
++        break;
++    default:
++        graphics_current_color = graphics_standard_color;
++        break;
++    }
++
++    graphics_color_state = state;
++}
++
++void graphics_setcolor (int normal_color, int highlight_color) {
++    graphics_normal_color = normal_color;
++    graphics_highlight_color = highlight_color;
++
++    graphics_setcolorstate (graphics_color_state);
++}
++
++void graphics_setcursor (int on) {
++    /* FIXME: we don't have a cursor in graphics */
++    return;
++}
++
++/* Read in the splashscreen image and set the palette up appropriately.
++ * Format of splashscreen is an xpm (can be gzipped) with 16 colors and
++ * 640x480. */
++int read_image(char *s)
++{
++    char buf[32], pal[16];
++    unsigned char c, base, mask, *s1, *s2, *s4, *s8;
++    unsigned i, len, idx, colors, x, y, width, height;
++
++    if (!grub_open(s))
++        return 0;
++
++    /* read header */
++    if (!grub_read((char*)&buf, 10) || grub_memcmp(buf, "/* XPM */\n", 10)) {
++        grub_close();
++        return 0;
++    }
++    
++    /* parse info */
++    while (grub_read(&c, 1)) {
++        if (c == '"')
++            break;
++    }
++
++    while (grub_read(&c, 1) && (c == ' ' || c == '\t'))
++        ;
++
++    i = 0;
++    width = c - '0';
++    while (grub_read(&c, 1)) {
++        if (c >= '0' && c <= '9')
++            width = width * 10 + c - '0';
++        else
++            break;
++    }
++    while (grub_read(&c, 1) && (c == ' ' || c == '\t'))
++        ;
++
++    height = c - '0';
++    while (grub_read(&c, 1)) {
++        if (c >= '0' && c <= '9')
++            height = height * 10 + c - '0';
++        else
++            break;
++    }
++    while (grub_read(&c, 1) && (c == ' ' || c == '\t'))
++        ;
++
++    colors = c - '0';
++    while (grub_read(&c, 1)) {
++        if (c >= '0' && c <= '9')
++            colors = colors * 10 + c - '0';
++        else
++            break;
++    }
++
++    base = 0;
++    while (grub_read(&c, 1) && c != '"')
++        ;
++
++    /* palette */
++    for (i = 0, idx = 1; i < colors; i++) {
++        len = 0;
++
++        while (grub_read(&c, 1) && c != '"')
++            ;
++        grub_read(&c, 1);       /* char */
++        base = c;
++        grub_read(buf, 4);      /* \t c # */
++
++        while (grub_read(&c, 1) && c != '"') {
++            if (len < sizeof(buf))
++                buf[len++] = c;
++        }
++
++        if (len == 6 && idx < 15) {
++            int r = ((hex(buf[0]) << 4) | hex(buf[1])) >> 2;
++            int g = ((hex(buf[2]) << 4) | hex(buf[3])) >> 2;
++            int b = ((hex(buf[4]) << 4) | hex(buf[5])) >> 2;
++
++            pal[idx] = base;
++            graphics_set_palette(idx, r, g, b);
++            ++idx;
++        }
++    }
++
++    x = y = len = 0;
++
++    s1 = (unsigned char*)VSHADOW1;
++    s2 = (unsigned char*)VSHADOW2;
++    s4 = (unsigned char*)VSHADOW4;
++    s8 = (unsigned char*)VSHADOW8;
++
++    for (i = 0; i < 38400; i++)
++        s1[i] = s2[i] = s4[i] = s8[i] = 0;
++
++    /* parse xpm data */
++    while (y < height) {
++        while (1) {
++            if (!grub_read(&c, 1)) {
++                grub_close();
++                return 0;
++            }
++            if (c == '"')
++                break;
++        }
++
++        while (grub_read(&c, 1) && c != '"') {
++            for (i = 1; i < 15; i++)
++                if (pal[i] == c) {
++                    c = i;
++                    break;
++                }
++
++            mask = 0x80 >> (x & 7);
++            if (c & 1)
++                s1[len + (x >> 3)] |= mask;
++            if (c & 2)
++                s2[len + (x >> 3)] |= mask;
++            if (c & 4)
++                s4[len + (x >> 3)] |= mask;
++            if (c & 8)
++                s8[len + (x >> 3)] |= mask;
++
++            if (++x >= 640) {
++                x = 0;
++
++                if (y < 480)
++                    len += 80;
++                ++y;
++            }
++        }
++    }
++
++    grub_close();
++
++    graphics_set_palette(0, (background >> 16), (background >> 8) & 63, 
++                background & 63);
++    graphics_set_palette(15, (foreground >> 16), (foreground >> 8) & 63, 
++                foreground & 63);
++    graphics_set_palette(0x11, (border >> 16), (border >> 8) & 63, 
++                         border & 63);
++
++    return 1;
++}
++
++
++/* Convert a character which is a hex digit to the appropriate integer */
++int hex(int v)
++{
++    if (v >= 'A' && v <= 'F')
++        return (v - 'A' + 10);
++    if (v >= 'a' && v <= 'f')
++        return (v - 'a' + 10);
++    return (v - '0');
++}
++
++
++/* move the graphics cursor location to col, row */
++static void graphics_setxy(int col, int row) {
++    if (col >= x0 && col < x1) {
++        fontx = col;
++        cursorX = col << 3;
++    }
++    if (row >= y0 && row < y1) {
++        fonty = row;
++        cursorY = row << 4;
++    }
++}
++
++/* scroll the screen */
++static void graphics_scroll() {
++    int i, j;
++
++    /* we don't want to scroll recursively... that would be bad */
++    if (no_scroll)
++        return;
++    no_scroll = 1;
++
++    /* move everything up a line */
++    for (j = y0 + 1; j < y1; j++) {
++        graphics_gotoxy(x0, j - 1);
++        for (i = x0; i < x1; i++) {
++            graphics_putchar(text[j * 80 + i]);
++        }
++    }
++
++    /* last line should be blank */
++    graphics_gotoxy(x0, y1 - 1);
++    for (i = x0; i < x1; i++)
++        graphics_putchar(' ');
++    graphics_setxy(x0, y1 - 1);
++
++    no_scroll = 0;
++}
++
++
++void graphics_cursor(int set) {
++    unsigned char *pat, *mem, *ptr, chr[16 << 2];
++    int i, ch, invert, offset;
++
++    if (set && no_scroll)
++        return;
++
++    offset = cursorY * 80 + fontx;
++    ch = text[fonty * 80 + fontx] & 0xff;
++    invert = (text[fonty * 80 + fontx] & 0xff00) != 0;
++    pat = font8x16 + (ch << 4);
++
++    mem = (unsigned char*)VIDEOMEM + offset;
++
++    if (!set) {
++        for (i = 0; i < 16; i++) {
++            unsigned char mask = pat[i];
++
++            if (!invert) {
++                chr[i     ] = ((unsigned char*)VSHADOW1)[offset];
++                chr[16 + i] = ((unsigned char*)VSHADOW2)[offset];
++                chr[32 + i] = ((unsigned char*)VSHADOW4)[offset];
++                chr[48 + i] = ((unsigned char*)VSHADOW8)[offset];
++
++                /* FIXME: if (shade) */
++                if (1) {
++                    if (ch == DISP_VERT || ch == DISP_LL ||
++                        ch == DISP_UR || ch == DISP_LR) {
++                        unsigned char pmask = ~(pat[i] >> 1);
++
++                        chr[i     ] &= pmask;
++                        chr[16 + i] &= pmask;
++                        chr[32 + i] &= pmask;
++                        chr[48 + i] &= pmask;
++                    }
++                    if (i > 0 && ch != DISP_VERT) {
++                        unsigned char pmask = ~(pat[i - 1] >> 1);
++
++                        chr[i     ] &= pmask;
++                        chr[16 + i] &= pmask;
++                        chr[32 + i] &= pmask;
++                        chr[48 + i] &= pmask;
++                        if (ch == DISP_HORIZ || ch == DISP_UR || ch == DISP_LR) {
++                            pmask = ~pat[i - 1];
++
++                            chr[i     ] &= pmask;
++                            chr[16 + i] &= pmask;
++                            chr[32 + i] &= pmask;
++                            chr[48 + i] &= pmask;
++                        }
++                    }
++                }
++                chr[i     ] |= mask;
++                chr[16 + i] |= mask;
++                chr[32 + i] |= mask;
++                chr[48 + i] |= mask;
++
++                offset += 80;
++            }
++            else {
++                chr[i     ] = mask;
++                chr[16 + i] = mask;
++                chr[32 + i] = mask;
++                chr[48 + i] = mask;
++            }
++        }
++    }
++    else {
++        MapMask(15);
++        ptr = mem;
++        for (i = 0; i < 16; i++, ptr += 80) {
++            cursorBuf[i] = pat[i];
++            *ptr = ~pat[i];
++        }
++        return;
++    }
++
++    offset = 0;
++    for (i = 1; i < 16; i <<= 1, offset += 16) {
++        int j;
++
++        MapMask(i);
++        ptr = mem;
++        for (j = 0; j < 16; j++, ptr += 80)
++            *ptr = chr[j + offset];
++    }
++
++    MapMask(15);
++}
++
++#endif /* SUPPORT_GRAPHICS */
+diff -urpN grub-0.97/stage2/graphics.h grub-0.97-gfx/stage2/graphics.h
+--- grub-0.97/stage2/graphics.h	1969-12-31 20:00:00.000000000 -0400
++++ grub-0.97-gfx/stage2/graphics.h	2005-10-13 16:27:35.000000000 -0400
+@@ -0,0 +1,42 @@
++/* graphics.h - graphics console interface */
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 2002  Free Software Foundation, Inc.
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifndef GRAPHICS_H
++#define GRAPHICS_H
++
++/* magic constant */
++#define VIDEOMEM 0xA0000
++
++/* function prototypes */
++char *graphics_get_splash(void);
++
++int read_image(char *s);
++void graphics_cursor(int set);
++
++/* function prototypes for asm functions */
++void * graphics_get_font();
++void graphics_set_palette(int idx, int red, int green, int blue);
++void set_int1c_handler();
++void unset_int1c_handler();
++
++extern short cursorX, cursorY;
++extern char cursorBuf[16];
++
++#endif /* GRAPHICS_H */
+diff -urpN grub-0.97/stage2/shared.h grub-0.97-gfx/stage2/shared.h
+--- grub-0.97/stage2/shared.h	2005-10-13 16:27:23.000000000 -0400
++++ grub-0.97-gfx/stage2/shared.h	2005-10-13 16:27:35.000000000 -0400
+@@ -871,6 +871,7 @@ int grub_sprintf (char *buffer, const ch
+ int grub_tolower (int c);
+ int grub_isspace (int c);
+ int grub_strncat (char *s1, const char *s2, int n);
++void grub_memcpy(void *dest, const void *src, int len);
+ void *grub_memmove (void *to, const void *from, int len);
+ void *grub_memset (void *start, int c, int len);
+ int grub_strncat (char *s1, const char *s2, int n);
+diff -urpN grub-0.97/stage2/stage2.c grub-0.97-gfx/stage2/stage2.c
+--- grub-0.97/stage2/stage2.c	2005-10-13 16:27:23.000000000 -0400
++++ grub-0.97-gfx/stage2/stage2.c	2005-10-13 16:27:35.000000000 -0400
+@@ -233,6 +233,7 @@ run_menu (char *menu_entries, char *conf
+ {
+   int c, time1, time2 = -1, first_entry = 0;
+   char *cur_entry = 0;
++  struct term_entry *prev_term = NULL;
+ 
+   /*
+    *  Main loop for menu UI.
+@@ -714,6 +715,15 @@ restart:
+   
+   cls ();
+   setcursor (1);
++  /* if our terminal needed initialization, we should shut it down
++   * before booting the kernel, but we want to save what it was so
++   * we can come back if needed */
++  prev_term = current_term;
++  if (current_term->shutdown) 
++    {
++      (*current_term->shutdown)();
++      current_term = term_table; /* assumption: console is first */
++    }
+   
+   while (1)
+     {
+@@ -748,6 +758,13 @@ restart:
+ 	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;
+ }
+@@ -1050,6 +1067,10 @@ cmain (void)
+ 	  while (is_preset);
+ 	}
+ 
++      /* go ahead and make sure the terminal is setup */
++      if (current_term->startup)
++        (*current_term->startup)();
++
+       if (! num_entries)
+ 	{
+ 	  /* If no acceptable config file, goto command-line, starting
+diff -urpN grub-0.97/stage2/term.h grub-0.97-gfx/stage2/term.h
+--- grub-0.97/stage2/term.h	2005-10-13 16:27:23.000000000 -0400
++++ grub-0.97-gfx/stage2/term.h	2005-10-13 16:27:35.000000000 -0400
+@@ -60,6 +60,8 @@ struct term_entry
+   const char *name;
+   /* The feature flags defined above.  */
+   unsigned long flags;
++  /* Default for maximum number of lines if not specified */
++  unsigned short max_lines;
+   /* Put a character.  */
+   void (*putchar) (int c);
+   /* Check if any input character is available.  */
+@@ -79,6 +81,11 @@ struct term_entry
+   void (*setcolor) (int normal_color, int highlight_color);
+   /* Turn on/off the cursor.  */
+   int (*setcursor) (int on);
++
++  /* function to start a terminal */
++  int (*startup) (void);
++  /* function to use to shutdown a terminal */
++  void (*shutdown) (void);
+ };
+ 
+ /* This lists up available terminals.  */
+@@ -124,4 +131,23 @@ void hercules_setcolor (int normal_color
+ int hercules_setcursor (int on);
+ #endif
+ 
++#ifdef SUPPORT_GRAPHICS
++extern int foreground, background, border, graphics_inited;
++
++void graphics_set_splash(char *splashfile);
++int set_videomode (int mode);
++void graphics_putchar (int c);
++int graphics_getxy(void);
++void graphics_gotoxy(int x, int y);
++void graphics_cls(void);
++void graphics_setcolorstate (color_state state);
++void graphics_setcolor (int normal_color, int highlight_color);
++void graphics_setcursor (int on);
++int graphics_init(void);
++void graphics_end(void);
++
++int hex(int v);
++void graphics_set_palette(int idx, int red, int green, int blue);
++#endif /* SUPPORT_GRAPHICS */
++
+ #endif /* ! GRUB_TERM_HEADER */
diff --git a/abs/core-testing/grub-gfx/grub-gfx.install b/abs/core-testing/grub-gfx/grub-gfx.install
new file mode 100644
index 0000000..6c73b15
--- /dev/null
+++ b/abs/core-testing/grub-gfx/grub-gfx.install
@@ -0,0 +1,46 @@
+# arg 1:  the new package version
+pre_install() {
+  /bin/true
+}
+
+# arg 1:  the new package version
+post_install() {
+	echo
+	echo "*********************************************************************"
+    echo "You need to run install-grub /dev/device or grub-install /dev/device "
+    echo "to update grub loader."
+    echo "Note: Device should be any of these (sda, sdb, hda, hdb, sda1, hda1) "
+    echo "If you are in doubt, see your old grub config file (menu.lst.pacsave)"
+    echo "********************************************************************"
+	echo
+}
+
+# arg 1:  the new package version
+# arg 2:  the old package version
+pre_upgrade() {
+  /bin/true
+}
+
+# arg 1:  the new package version
+# arg 2:  the old package version
+post_upgrade() {
+	echo
+	echo "*********************************************************************"
+    echo "You need to run install-grub /dev/device or grub-install /dev/device "
+    echo "to update grub loader."
+    echo "Note: Device should be any of these (sda, sdb, hda, hdb, sda1, hda1) "
+    echo "If you are in doubt, see your old grub config file (menu.lst.pacsave)"
+    echo "********************************************************************"
+	echo
+}
+
+# arg 1:  the old package version
+pre_remove() {
+	/bin/true
+}
+
+# arg 1:  the old package version
+post_remove() {
+  /bin/true
+}
+
diff --git a/abs/core-testing/grub-gfx/grub-inode-size.patch b/abs/core-testing/grub-gfx/grub-inode-size.patch
new file mode 100644
index 0000000..bef3bc1
--- /dev/null
+++ b/abs/core-testing/grub-gfx/grub-inode-size.patch
@@ -0,0 +1,94 @@
+diff -Nrup a/stage2/fsys_ext2fs.c b/stage2/fsys_ext2fs.c
+--- a/stage2/fsys_ext2fs.c	2004-08-08 20:19:18.000000000 +0200
++++ b/stage2/fsys_ext2fs.c	2008-01-30 14:27:20.000000000 +0100
+@@ -79,7 +79,52 @@ struct ext2_super_block
+     __u32 s_rev_level;		/* Revision level */
+     __u16 s_def_resuid;		/* Default uid for reserved blocks */
+     __u16 s_def_resgid;		/* Default gid for reserved blocks */
+-    __u32 s_reserved[235];	/* Padding to the end of the block */
++    /*
++     * These fields are for EXT2_DYNAMIC_REV superblocks only.
++     *
++     * Note: the difference between the compatible feature set and
++     * the incompatible feature set is that if there is a bit set
++     * in the incompatible feature set that the kernel doesn't
++     * know about, it should refuse to mount the filesystem.
++     *
++     * e2fsck's requirements are more strict; if it doesn't know
++     * about a feature in either the compatible or incompatible
++     * feature set, it must abort and not try to meddle with
++     * things it doesn't understand...
++     */
++    __u32 s_first_ino;		/* First non-reserved inode */
++    __u16 s_inode_size;		/* size of inode structure */
++    __u16 s_block_group_nr;	/* block group # of this superblock */
++    __u32 s_feature_compat;	/* compatible feature set */
++    __u32 s_feature_incompat;	/* incompatible feature set */
++    __u32 s_feature_ro_compat;	/* readonly-compatible feature set */
++    __u8  s_uuid[16];		/* 128-bit uuid for volume */
++    char  s_volume_name[16];	/* volume name */
++    char  s_last_mounted[64];	/* directory where last mounted */
++    __u32 s_algorithm_usage_bitmap; /* For compression */
++    /*
++     * Performance hints.  Directory preallocation should only
++     * happen if the EXT2_FEATURE_COMPAT_DIR_PREALLOC flag is on.
++     */
++    __u8  s_prealloc_blocks;	/* Nr of blocks to try to preallocate*/
++    __u8  s_prealloc_dir_blocks;	/* Nr to preallocate for dirs */
++    __u16 s_reserved_gdt_blocks;/* Per group table for online growth */
++    /*
++     * Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set.
++     */
++    __u8 s_journal_uuid[16];	/* uuid of journal superblock */
++    __u32 s_journal_inum;	/* inode number of journal file */
++    __u32 s_journal_dev;	/* device number of journal file */
++    __u32 s_last_orphan;	/* start of list of inodes to delete */
++    __u32 s_hash_seed[4];	/* HTREE hash seed */
++    __u8  s_def_hash_version;	/* Default hash version to use */
++    __u8  s_jnl_backup_type; 	/* Default type of journal backup */
++    __u16 s_reserved_word_pad;
++    __u32 s_default_mount_opts;
++    __u32 s_first_meta_bg;	/* First metablock group */
++    __u32 s_mkfs_time;		/* When the filesystem was created */
++    __u32 s_jnl_blocks[17]; 	/* Backup of the journal inode */
++    __u32 s_reserved[172];	/* Padding to the end of the block */
+   };
+ 
+ struct ext2_group_desc
+@@ -218,6 +263,9 @@ struct ext2_dir_entry
+ #define EXT2_ADDR_PER_BLOCK(s)          (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
+ #define EXT2_ADDR_PER_BLOCK_BITS(s)		(log2(EXT2_ADDR_PER_BLOCK(s)))
+ 
++#define EXT2_INODE_SIZE(s)		(SUPERBLOCK->s_inode_size)
++#define EXT2_INODES_PER_BLOCK(s)	(EXT2_BLOCK_SIZE(s)/EXT2_INODE_SIZE(s))
++
+ /* linux/ext2_fs.h */
+ #define EXT2_BLOCK_SIZE_BITS(s)        ((s)->s_log_block_size + 10)
+ /* kind of from ext2/super.c */
+@@ -553,7 +601,7 @@ ext2fs_dir (char *dirname)
+       gdp = GROUP_DESC;
+       ino_blk = gdp[desc].bg_inode_table +
+ 	(((current_ino - 1) % (SUPERBLOCK->s_inodes_per_group))
+-	 >> log2 (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)));
++	 >> log2 (EXT2_INODES_PER_BLOCK (SUPERBLOCK)));
+ #ifdef E2DEBUG
+       printf ("inode table fsblock=%d\n", ino_blk);
+ #endif /* E2DEBUG */
+@@ -565,13 +613,12 @@ ext2fs_dir (char *dirname)
+       /* reset indirect blocks! */
+       mapblock2 = mapblock1 = -1;
+ 
+-      raw_inode = INODE +
+-	((current_ino - 1)
+-	 & (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode) - 1));
++      raw_inode = (struct ext2_inode *)((char *)INODE +
++	((current_ino - 1) & (EXT2_INODES_PER_BLOCK (SUPERBLOCK) - 1)) *
++	EXT2_INODE_SIZE (SUPERBLOCK));
+ #ifdef E2DEBUG
+       printf ("ipb=%d, sizeof(inode)=%d\n",
+-	      (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)),
+-	      sizeof (struct ext2_inode));
++	      EXT2_INODES_PER_BLOCK (SUPERBLOCK), EXT2_INODE_SIZE (SUPERBLOCK));
+       printf ("inode=%x, raw_inode=%x\n", INODE, raw_inode);
+       printf ("offset into inode table block=%d\n", (int) raw_inode - (int) INODE);
+       for (i = (unsigned char *) INODE; i <= (unsigned char *) raw_inode;
diff --git a/abs/core-testing/grub-gfx/i2o.patch b/abs/core-testing/grub-gfx/i2o.patch
new file mode 100644
index 0000000..2af846c
--- /dev/null
+++ b/abs/core-testing/grub-gfx/i2o.patch
@@ -0,0 +1,45 @@
+Only in grub-0.94/docs: grub.info
+Only in grub-0.94/docs: multiboot.info
+diff -ur grub-0.94/lib/device.c grub-0.94.new/lib/device.c
+--- grub-0.94/lib/device.c	2004-05-07 04:50:36.375238696 +0200
++++ grub-0.94.new/lib/device.c	2004-05-07 04:48:57.611253104 +0200
+@@ -419,6 +419,12 @@
+ {
+   sprintf (name, "/dev/rd/c%dd%d", controller, drive);
+ }
++
++static void
++get_i2o_disk_name (char *name, int unit)
++{
++  sprintf (name, "/dev/i2o/hd%c", unit + 'a');
++}
+ #endif
+ 
+ /* Check if DEVICE can be read. If an error occurs, return zero,
+@@ -789,6 +795,26 @@
+ 	  }
+       }
+   }
++
++  /* I2O disks.  */
++  for (i = 0; i < 8; i++)
++    {
++      char name[16];
++      
++      get_i2o_disk_name (name, i);
++      if (check_device (name))
++	{
++	  (*map)[num_hd + 0x80] = strdup (name);
++	  assert ((*map)[num_hd + 0x80]);
++	  
++	  /* If the device map file is opened, write the map.  */
++	  if (fp)
++	    fprintf (fp, "(hd%d)\t%s\n", num_hd, name);
++	  
++	  num_hd++;
++	}
++    }
++  
+ #endif /* __linux__ */
+   
+   /* OK, close the device map file if opened.  */
diff --git a/abs/core-testing/grub-gfx/install-grub b/abs/core-testing/grub-gfx/install-grub
new file mode 100755
index 0000000..3eb7ce5
--- /dev/null
+++ b/abs/core-testing/grub-gfx/install-grub
@@ -0,0 +1,187 @@
+#!/bin/bash
+
+#
+# This is a little helper script that tries to convert linux-style device
+# names to grub-style.  It's not very smart, so it
+# probably won't work for more complicated setups.
+#
+# If it doesn't work for you, try installing grub manually:
+#
+#    # mkdir -p /boot/grub
+#    # cp /usr/lib/grub/i386-pc/* /boot/grub/
+#
+# Then start up the 'grub' shell and run something like the following:
+#
+#    grub> root(hd0,0)
+#    grub> setup(hd0)
+#
+# The "root" line should point to the partition your kernel is located on,
+# /boot if you have a separate boot partition, otherwise your root (/).
+#
+# The "setup" line tells grub which disc/partition to install the
+# bootloader to.  In the example above, it will install to the MBR of the
+# primary master hard drive.
+#
+
+usage() {
+	echo "usage: install-grub <install_device> [boot_device]"
+	echo
+	echo "where <install_device> is the device where Grub will be installed"
+	echo "and [boot_device] is the partition that contains the /boot"
+	echo "directory (auto-detected if omitted)"
+	echo
+	echo "examples: install-grub /dev/hda"
+	echo "          install-grub /dev/hda /dev/hda1"
+	echo
+	exit 0
+}
+
+## new install-grub, code was taken from setup script
+ROOTDEV=$1
+PART_ROOT=$2
+VMLINUZ=vmlinuz26
+
+if [ "$ROOTDEV" = "" ]; then
+	usage
+fi
+if [ "$PART_ROOT" = "" ]; then
+	PART_ROOT=$(mount | grep "on /boot type" | cut -d' ' -f 1)
+fi
+if [ "$PART_ROOT" = "" ]; then
+	PART_ROOT=$(mount | grep "on / type" | cut -d' ' -f 1)
+fi
+if [ "$PART_ROOT" = "" ]; then
+	echo "error: could not determine BOOT_DEVICE, please specify manually" >&2
+	exit 1
+fi
+
+
+get_grub_map() {
+	[ -e /tmp/dev.map ]  && rm /tmp/dev.map	
+	/sbin/grub --no-floppy --device-map /tmp/dev.map >/tmp/grub.log 2>&1 <<EOF
+quit
+EOF
+}
+
+mapdev() {
+	partition_flag=0
+	device_found=0
+	devs=$(cat /tmp/dev.map | grep -v fd | sed 's/ *\t/ /' | sed ':a;$!N;$!ba;s/\n/ /g')
+	linuxdevice=$(echo $1 | cut -b1-8)
+	if [ "$(echo $1 | egrep '[0-9]$')" ]; then
+		# /dev/hdXY
+		pnum=$(echo $1 | cut -b9-)
+		pnum=$(($pnum-1))
+		partition_flag=1
+	fi
+	for  dev in $devs
+	do
+	    if [ "(" = $(echo $dev | cut -b1) ]; then
+		grubdevice="$dev"
+	    else
+		if [ "$dev" = "$linuxdevice" ]; then
+			device_found=1
+			break   
+		fi
+	   fi
+	done	
+	if [ "$device_found" = "1" ]; then
+		if [ "$partition_flag" = "0" ]; then
+			echo "$grubdevice"
+		else
+			grubdevice_stringlen=${#grubdevice}
+			let grubdevice_stringlen--
+			grubdevice=$(echo $grubdevice | cut -b1-$grubdevice_stringlen)
+			echo "$grubdevice,$pnum)"
+		fi
+	else
+		echo " DEVICE NOT FOUND"
+	fi
+}
+
+dogrub() {
+	get_grub_map	
+	if [ ! -f /boot/grub/menu.lst ]; then
+		echo "Error: Couldn't find /boot/grub/menu.lst.  Is GRUB installed?"
+		exit 1
+	fi
+	# try to auto-configure GRUB...
+	if [ "$PART_ROOT" != "" -a "$S_GRUB" != "1" ]; then
+		grubdev=$(mapdev $PART_ROOT)
+		# look for a separately-mounted /boot partition
+		bootdev=$(mount | grep /boot | cut -d' ' -f 1)
+		if [ "$grubdev" != "" -o "$bootdev" != "" ]; then
+			cp /boot/grub/menu.lst /tmp/.menu.lst
+			# remove the default entries by truncating the file at our little tag (#-*)
+			head -n $(cat /tmp/.menu.lst | grep -n '#-\*' | cut -d: -f 1) /tmp/.menu.lst >/boot/grub/menu.lst
+			rm -f /tmp/.menu.lst
+			echo "" >>/boot/grub/menu.lst
+			echo "# (0) Arch Linux" >>/boot/grub/menu.lst
+			echo "title  Arch Linux" >>/boot/grub/menu.lst
+			subdir=
+			if [ "$bootdev" != "" ]; then
+				grubdev=$(mapdev $bootdev)
+			else
+				subdir="/boot"
+			fi
+			echo "root   $grubdev" >>/boot/grub/menu.lst
+			echo "kernel $subdir/$VMLINUZ root=$PART_ROOT ro" >>/boot/grub/menu.lst
+			if [ "$VMLINUZ" = "vmlinuz26" ]; then
+				echo "initrd $subdir/kernel26.img" >>/boot/grub/menu.lst
+			fi
+			echo "" >>/boot/grub/menu.lst
+			# adding fallback/full image
+			echo "# (1) Arch Linux" >>/boot/grub/menu.lst
+			echo "title  Arch Linux Fallback" >>/boot/grub/menu.lst
+			echo "root   $grubdev" >>/boot/grub/menu.lst
+			echo "kernel $subdir/$VMLINUZ root=$PART_ROOT ro" >>/boot/grub/menu.lst
+			if [ "$VMLINUZ" = "vmlinuz26" ]; then
+				echo "initrd $subdir/kernel26-fallback.img" >>/boot/grub/menu.lst
+			fi
+			echo "" >>/boot/grub/menu.lst
+		fi
+	fi
+
+	echo "Installing the GRUB bootloader..."
+	cp -a /usr/lib/grub/i386-pc/* /boot/grub/
+	sync
+	# freeze xfs filesystems to enable grub installation on xfs filesystems
+	if [ -x /usr/sbin/xfs_freeze ]; then
+		/usr/sbin/xfs_freeze -f /boot > /dev/null 2>&1
+		/usr/sbin/xfs_freeze -f / > /dev/null 2>&1
+	fi
+	# look for a separately-mounted /boot partition
+	bootpart=$(mount | grep /boot | cut -d' ' -f 1)
+	if [ "$bootpart" = "" ]; then
+			bootpart=$PART_ROOT
+	fi
+	bootpart=$(mapdev $bootpart)
+	bootdev=$(mapdev $ROOTDEV)
+	if [ "$bootpart" = "" ]; then
+		echo "Error: Missing/Invalid root device: $bootpart"
+		exit 1
+	fi
+	/sbin/grub --no-floppy --batch >/tmp/grub.log 2>&1 <<EOF
+root $bootpart
+setup $bootdev
+quit
+EOF
+cat /tmp/grub.log
+	# unfreeze xfs filesystems
+	if [ -x /usr/sbin/xfs_freeze ]; then
+		/usr/sbin/xfs_freeze -u /boot > /dev/null 2>&1
+		/usr/sbin/xfs_freeze -u / > /dev/null 2>&1
+	fi
+
+	if grep "Error [0-9]*: " /tmp/grub.log >/dev/null; then
+		echo "Error installing GRUB. (see /tmp/grub.log for output)"
+		exit 1
+	fi
+	echo "GRUB was successfully installed."
+
+rm -f /tmp/grub.log
+
+exit 0
+}
+
+dogrub
\ No newline at end of file
diff --git a/abs/core-testing/grub-gfx/intelmac.patch b/abs/core-testing/grub-gfx/intelmac.patch
new file mode 100644
index 0000000..a3fabc7
--- /dev/null
+++ b/abs/core-testing/grub-gfx/intelmac.patch
@@ -0,0 +1,67 @@
+--- grub-0.97.orig/stage2/asm.S	2004-06-19 18:55:22.000000000 +0200
++++ grub-0.97/stage2/asm.S	2006-04-21 11:10:52.000000000 +0200
+@@ -1651,7 +1651,29 @@
+ 	jnz	3f
+ 	ret
+ 
+-3:	/* use keyboard controller */
++3:	/*
++	 * try to switch gateA20 using PORT92, the "Fast A20 and Init"
++	 * register
++	*/
++	mov $0x92, %dx
++	inb %dx, %al
++	/* skip the port92 code if it's unimplemented (read returns 0xff) */
++	cmpb $0xff, %al
++	jz 6f
++	
++	/* set or clear bit1, the ALT_A20_GATE bit */
++	movb 4(%esp), %ah
++	testb %ah, %ah
++	jz 4f
++	orb $2, %al
++	jmp 5f
++4:	and $0xfd, %al
++	
++	/* clear the INIT_NOW bit don't accidently reset the machine */
++5:	and $0xfe, %al
++	outb %al, %dx
++	
++6:	/* use keyboard controller */
+ 	pushl	%eax
+ 
+ 	call    gloop1
+@@ -1661,9 +1683,12 @@
+ 
+ gloopint1:
+ 	inb	$K_STATUS
++	cmpb	$0xff, %al
++	jz	gloopint1_done
+ 	andb	$K_IBUF_FUL, %al
+ 	jnz	gloopint1
+ 
++gloopint1_done:	
+ 	movb	$KB_OUTPUT_MASK, %al
+ 	cmpb	$0, 0x8(%esp)
+ 	jz	gdoit
+@@ -1684,6 +1709,8 @@
+ 
+ gloop1:
+ 	inb	$K_STATUS
++	cmpb	$0xff, %al
++	jz	gloop2ret
+ 	andb	$K_IBUF_FUL, %al
+ 	jnz	gloop1
+ 
+@@ -1991,6 +2018,11 @@
+ ENTRY(console_getkey)
+ 	push	%ebp
+ 
++wait_for_key:
++	call	EXT_C(console_checkkey)
++	incl	%eax
++	jz	wait_for_key
++	
+ 	call	EXT_C(prot_to_real)
+ 	.code16
+  
diff --git a/abs/core-testing/grub-gfx/menu.lst b/abs/core-testing/grub-gfx/menu.lst
new file mode 100644
index 0000000..cc2f0a8
--- /dev/null
+++ b/abs/core-testing/grub-gfx/menu.lst
@@ -0,0 +1,47 @@
+# Config file for GRUB - The GNU GRand Unified Bootloader
+# /boot/grub/menu.lst
+
+# DEVICE NAME CONVERSIONS 
+#
+#  Linux           Grub
+# -------------------------
+#  /dev/fd0        (fd0)
+#  /dev/hda        (hd0)
+#  /dev/hdb2       (hd1,1)
+#  /dev/hda3       (hd0,2)
+#
+
+#  FRAMEBUFFER RESOLUTION SETTINGS
+#     +-------------------------------------------------+
+#          | 640x480    800x600    1024x768   1280x1024
+#      ----+--------------------------------------------
+#      256 | 0x301=769  0x303=771  0x305=773   0x307=775
+#      32K | 0x310=784  0x313=787  0x316=790   0x319=793
+#      64K | 0x311=785  0x314=788  0x317=791   0x31A=794
+#      16M | 0x312=786  0x315=789  0x318=792   0x31B=795
+#     +-------------------------------------------------+
+
+# general configuration:
+timeout   5
+default   0
+color light-blue/black light-cyan/blue
+splashimage /boot/grub/splash.xpm.gz
+
+# boot sections follow
+# each is implicitly numbered from 0 in the order of appearance below
+#
+# TIP: If you want a 1024x768 framebuffer, add "vga=773" to your kernel line.
+#
+#-*
+
+# (0) Arch Linux
+title  Arch Linux  [/boot/vmlinuz26]
+root   (hd0,0)
+kernel /vmlinuz26 root=/dev/hda3 ro
+initrd /kernel26.img
+
+# (1) Windows
+#title Windows
+#rootnoverify (hd0,0)
+#makeactive
+#chainloader +1
diff --git a/abs/core-testing/grub-gfx/more-raid.patch b/abs/core-testing/grub-gfx/more-raid.patch
new file mode 100644
index 0000000..39db234
--- /dev/null
+++ b/abs/core-testing/grub-gfx/more-raid.patch
@@ -0,0 +1,100 @@
+--- grub-0.95/lib/device.c.moreraid	2004-11-30 17:09:36.736099360 -0500
++++ grub-0.95/lib/device.c	2004-11-30 17:12:17.319686944 -0500
+@@ -544,6 +544,17 @@
+ }
+ 
+ static void
++get_cciss_disk_name (char * name, int controller, int drive)
++{
++  sprintf (name, "/dev/cciss/c%dd%d", controller, drive);
++}
++
++static void
++get_cpqarray_disk_name (char * name, int controller, int drive)
++{
++  sprintf (name, "/dev/ida/c%dd%d", controller, drive);
++}
++static void
+ get_ataraid_disk_name (char *name, int unit)
+ {
+   sprintf (name, "/dev/ataraid/d%c", unit + '0');
+@@ -920,7 +931,7 @@
+     
+     for (controller = 0; controller < 8; controller++)
+       {
+-	for (drive = 0; drive < 15; drive++)
++	for (drive = 0; drive < 32; drive++)
+ 	  {
+ 	    char name[24];
+ 	    
+@@ -940,6 +951,70 @@
+       }
+   }
+ #endif /* __linux__ */
++
++#ifdef __linux__
++  /* This is for cciss - we have
++     /dev/cciss/c<controller>d<logical drive>p<partition>.
++     
++     cciss driver currently supports up to 8 controllers, 16 logical
++     drives, and 7 partitions.  */
++  {
++    int controller, drive;
++    
++    for (controller = 0; controller < 8; controller++)
++      {
++	for (drive = 0; drive < 16; drive++)
++	  {
++	    char name[24];
++	    
++	    get_cciss_disk_name (name, controller, drive);
++	    if (check_device (name))
++	      {
++		(*map)[num_hd + 0x80] = strdup (name);
++		assert ((*map)[num_hd + 0x80]);
++		
++		/* If the device map file is opened, write the map.  */
++		if (fp)
++		  fprintf (fp, "(hd%d)\t%s\n", num_hd, name);
++		
++		num_hd++;
++	      }
++	  }
++      }
++  }
++#endif /* __linux__ */
++
++#ifdef __linux__
++  /* This is for cpqarray - we have
++     /dev/ida/c<controller>d<logical drive>p<partition>.
++     
++     cpqarray driver currently supports up to 8 controllers, 16 logical
++     drives, and 15 partitions.  */
++  {
++    int controller, drive;
++    
++    for (controller = 0; controller < 8; controller++)
++      {
++	for (drive = 0; drive < 15; drive++)
++	  {
++	    char name[24];
++	    
++	    get_cpqarray_disk_name (name, controller, drive);
++	    if (check_device (name))
++	      {
++		(*map)[num_hd + 0x80] = strdup (name);
++		assert ((*map)[num_hd + 0x80]);
++		
++		/* If the device map file is opened, write the map.  */
++		if (fp)
++		  fprintf (fp, "(hd%d)\t%s\n", num_hd, name);
++		
++		num_hd++;
++	      }
++	  }
++      }
++  }
++#endif /* __linux__ */
+   
+   /* OK, close the device map file if opened.  */
+   if (fp)
diff --git a/abs/core-testing/grub-gfx/special-devices.patch b/abs/core-testing/grub-gfx/special-devices.patch
new file mode 100644
index 0000000..894f3e8
--- /dev/null
+++ b/abs/core-testing/grub-gfx/special-devices.patch
@@ -0,0 +1,18 @@
+--- grub-0.93/lib/device.c.raid	2002-05-20 05:53:46.000000000 -0400
++++ grub-0.93/lib/device.c	2002-12-28 23:24:10.000000000 -0500
+@@ -689,7 +689,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/ataraid/", 13) == 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);
diff --git a/abs/core-testing/grub-gfx/splash.xpm.gz b/abs/core-testing/grub-gfx/splash.xpm.gz
new file mode 100644
index 0000000..e44af43
Binary files /dev/null and b/abs/core-testing/grub-gfx/splash.xpm.gz differ
-- 
cgit v0.12