+++ /dev/null
---- grub-0.95/lib/device.c.orig 2004-05-23 18:34:29.000000000 +0200
-+++ grub-0.95/lib/device.c 2004-09-21 18:15:23.785137837 +0200
-@@ -828,9 +828,11 @@ int
- is_disk_device (char **map, int drive)
- {
- struct stat st;
-+ int retval;
-
- assert (map[drive] != 0);
-- assert (stat (map[drive], &st) == 0);
-+ retval = stat (map[drive], &st);
-+ assert (retval == 0);
- /* For now, disk devices under Linux are all block devices. */
- return S_ISBLK (st.st_mode);
- }
+++ /dev/null
---- grub-0.97/netboot/i82586.c.orig 2003-07-09 13:45:37.000000000 +0200
-+++ grub-0.97/netboot/i82586.c 2006-04-20 18:50:20.000000000 +0200
-@@ -735,7 +735,7 @@ static unsigned char exos_i186_init[] =
- static int exos205_probe2(void)
- {
- unsigned short i;
-- unsigned short shmem[10];
-+ unsigned short shmem[10] = { 0,0,0,0,0,0,0,0,0,0 };
-
- /* Fix the ISCP address and base. */
- init_words[3] = scb_base;
+++ /dev/null
-diff -ur grub-0.93~/docs/grub.texi grub-0.93/docs/grub.texi
---- grub-0.93~/docs/grub.texi 2003-02-06 12:30:12.000000000 +0100
-+++ grub-0.93/docs/grub.texi 2003-02-06 14:15:30.000000000 +0100
-@@ -2632,7 +2632,7 @@
- @node install
- @subsection install
-
--@deffn Command install [@option{--force-lba}] [@option{--stage2=os_stage2_file}] stage1_file [@option{d}] dest_dev stage2_file [addr] [@option{p}] [config_file] [real_config_file]
-+@deffn Command install [@option{--force-lba[=off]}] [@option{--stage2=os_stage2_file}] stage1_file [@option{d}] dest_dev stage2_file [addr] [@option{p}] [config_file] [real_config_file]
- This command is fairly complex, and you should not use this command
- unless you are familiar with GRUB. Use @command{setup} (@pxref{setup})
- instead.
-@@ -2679,6 +2679,13 @@
- bitmap even if they do have the support. So GRUB provides a solution to
- ignore the wrong bitmap, that is, the option @option{--force-lba}. Don't
- use this option if you know that your BIOS doesn't have LBA support.
-+On the other hand there is at least one known BIOS that does the opposite,
-+it claims to support LBA and then fails to provide it. Iff you have an
-+Adaptec 2940 with BIOS revision 1.21 ( newer ones just work and older ones
-+don't make the false claim ), or otherwise experience grub hanging
-+after stage1, you can try to use the option @option{--force-lba=off},
-+as long as all disk blocks involved in booting reside
-+within the first 1024 cylinders.
-
- @strong{Caution3:} You must specify the option @option{--stage2} in the
- grub shell, if you cannot unmount the filesystem where your stage2 file
-diff -ur grub-0.93~/stage1/stage1.S grub-0.93/stage1/stage1.S
---- grub-0.93~/stage1/stage1.S 2002-09-08 03:58:08.000000000 +0200
-+++ grub-0.93/stage1/stage1.S 2003-02-06 13:19:50.000000000 +0100
-@@ -163,7 +163,11 @@
- /* check if AH=0x42 is supported if FORCE_LBA is zero */
- MOV_MEM_TO_AL(ABS(force_lba)) /* movb ABS(force_lba), %al */
- testb %al, %al
-+ /* check if LBA is forced OFF 0x80 <= %al <= 0xff */
-+ js chs_mode
-+ /* or forced ON 0x01 <= %al <= 0x7f */
- jnz lba_mode
-+ /* otherwise trust BIOS int's result */
- andw $1, %cx
- jz chs_mode
-
-diff -ur grub-0.93~/stage2/asm.S grub-0.93/stage2/asm.S
---- grub-0.93~/stage2/asm.S 2003-02-06 12:30:12.000000000 +0100
-+++ grub-0.93/stage2/asm.S 2003-02-06 13:35:32.000000000 +0100
-@@ -1083,7 +1083,11 @@
- /* check if AH=0x42 is supported if FORCE_LBA is zero */
- movb EXT_C(force_lba), %al
- testb %al, %al
-+ /* check if LBA is forced OFF 0x80 <= %al <= 0xff */
-+ js 1f
-+ /* or forced ON 0x01 <= %al <= 0x7f */
- jnz 2f
-+ /* otherwise trust BIOS int's result */
- andw $1, %cx
- jnz 2f
-
-diff -ur grub-0.93~/stage2/builtins.c grub-0.93/stage2/builtins.c
---- grub-0.93~/stage2/builtins.c 2003-02-06 12:30:12.000000000 +0100
-+++ grub-0.93/stage2/builtins.c 2003-02-06 13:56:01.000000000 +0100
-@@ -1832,7 +1832,12 @@
- /* First, check the GNU-style long option. */
- while (1)
- {
-- if (grub_memcmp ("--force-lba", arg, sizeof ("--force-lba") - 1) == 0)
-+ if (grub_memcmp ("--force-lba=off", arg, sizeof ("--force-lba=off") - 1) == 0)
-+ {
-+ is_force_lba = 0xff;
-+ arg = skip_to (0, arg);
-+ }
-+ else if (grub_memcmp ("--force-lba", arg, sizeof ("--force-lba") - 1) == 0)
- {
- is_force_lba = 1;
- arg = skip_to (0, arg);
-@@ -2253,7 +2258,7 @@
- "install",
- install_func,
- BUILTIN_CMDLINE,
-- "install [--stage2=STAGE2_FILE] [--force-lba] STAGE1 [d] DEVICE STAGE2 [ADDR] [p] [CONFIG_FILE] [REAL_CONFIG_FILE]",
-+ "install [--stage2=STAGE2_FILE] [--force-lba[=off]] STAGE1 [d] DEVICE STAGE2 [ADDR] [p] [CONFIG_FILE] [REAL_CONFIG_FILE]",
- "Install STAGE1 on DEVICE, and install a blocklist for loading STAGE2"
- " as a Stage 2. If the option `d' is present, the Stage 1 will always"
- " look for the disk where STAGE2 was installed, rather than using"
-@@ -2266,8 +2271,9 @@
- " 1.5 and REAL_CONFIG_FILE is present, then the Stage 2 CONFIG_FILE is"
- " patched with the configuration filename REAL_CONFIG_FILE."
- " If the option `--force-lba' is specified, disable some sanity checks"
-- " for LBA mode. If the option `--stage2' is specified, rewrite the Stage"
-- " 2 via your OS's filesystem instead of the raw device."
-+ " for LBA mode, `--force-lba=off' will disable it completely. If the"
-+ " option `--stage2' is specified, rewrite the Stage 2 via your OS's"
-+ " filesystem instead of the raw device."
- };
-
- \f
-@@ -3898,7 +3904,12 @@
- /* Check if the user specifies --force-lba. */
- while (1)
- {
-- if (grub_memcmp ("--force-lba", arg, sizeof ("--force-lba") - 1) == 0)
-+ if (grub_memcmp ("--force-lba=off", arg, sizeof ("--force-lba=off") - 1) == 0)
-+ {
-+ is_force_lba = 0xff;
-+ arg = skip_to (0, arg);
-+ }
-+ else if (grub_memcmp ("--force-lba", arg, sizeof ("--force-lba") - 1) == 0)
- {
- is_force_lba = 1;
- arg = skip_to (0, arg);
-@@ -4026,7 +4037,9 @@
- #if 1
- /* Don't embed a drive number unnecessarily. */
- grub_sprintf (cmd_arg, "%s%s%s%s %s%s %s p %s %s",
-- is_force_lba? "--force-lba " : "",
-+ is_force_lba ?
-+ (is_force_lba == 0xff ? "--force-lba=off " : "--force-lba ")
-+ : "",
- stage2_arg? stage2_arg : "",
- stage2_arg? " " : "",
- stage1,
-@@ -4079,17 +4092,18 @@
- "setup",
- setup_func,
- BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
-- "setup [--prefix=DIR] [--stage2=STAGE2_FILE] [--force-lba] INSTALL_DEVICE [IMAGE_DEVICE]",
-+ "setup [--prefix=DIR] [--stage2=STAGE2_FILE] [--force-lba[=off]] INSTALL_DEVICE [IMAGE_DEVICE]",
- "Set up the installation of GRUB automatically. This command uses"
- " the more flexible command \"install\" in the backend and installs"
- " GRUB into the device INSTALL_DEVICE. If IMAGE_DEVICE is specified,"
- " then find the GRUB images in the device IMAGE_DEVICE, otherwise"
- " use the current \"root device\", which can be set by the command"
- " \"root\". If you know that your BIOS should support LBA but GRUB"
-- " doesn't work in LBA mode, specify the option `--force-lba'."
-- " If you install GRUB under the grub shell and you cannot unmount the"
-- " partition where GRUB images reside, specify the option `--stage2'"
-- " to tell GRUB the file name under your OS."
-+ " doesn't work in LBA mode, specify the option `--force-lba'. If the"
-+ " BIOS claims to support LBA mode but really doesn't, use"
-+ " `--force-lba=off'. If you install GRUB under the grub shell and"
-+ " you cannot unmount the partition where GRUB images reside, specify"
-+ " the option `--stage2' to tell GRUB the file name under your OS."
- };
-
- \f
+++ /dev/null
-diff -Burbp grub-0.93.orig/grub/main.c grub-0.93/grub/main.c
---- grub-0.93.orig/grub/main.c 2003-06-10 18:29:37.000000000 +0200
-+++ grub-0.93/grub/main.c 2003-06-10 18:30:36.000000000 +0200
-@@ -44,7 +44,7 @@ int use_curses = 0;
- int verbose = 0;
- int read_only = 0;
- int floppy_disks = 1;
--char *device_map_file = 0;
-+char *device_map_file = "/boot/grub/device.map";
- static int default_boot_drive;
- static int default_install_partition;
- static char *default_config_file;
-diff -Burbp grub-0.93.orig/lib/device.c grub-0.93/lib/device.c
---- grub-0.93.orig/lib/device.c 2003-06-10 18:29:37.000000000 +0200
-+++ grub-0.93/lib/device.c 2003-06-10 18:30:36.000000000 +0200
-@@ -382,6 +382,7 @@ read_device_map (FILE *fp, char **map, c
- probing devices. */
- char buf[1024]; /* XXX */
- int line_number = 0;
-+ int retval = 0; /* default to failure */
-
- while (fgets (buf, sizeof (buf), fp))
- {
-@@ -408,14 +409,14 @@ read_device_map (FILE *fp, char **map, c
- if (*ptr != '(')
- {
- show_error (line_number, "No open parenthesis found");
-- return 0;
-+ continue;
- }
-
- ptr++;
- if ((*ptr != 'f' && *ptr != 'h') || *(ptr + 1) != 'd')
- {
- show_error (line_number, "Bad drive name");
-- return 0;
-+ continue;
- }
-
- if (*ptr == 'f')
-@@ -426,7 +427,7 @@ read_device_map (FILE *fp, char **map, c
- if (drive < 0 || drive > 8)
- {
- show_error (line_number, "Bad device number");
-- return 0;
-+ continue;
- }
-
- if (! is_floppy)
-@@ -435,7 +436,7 @@ read_device_map (FILE *fp, char **map, c
- if (*ptr != ')')
- {
- show_error (line_number, "No close parenthesis found");
-- return 0;
-+ continue;
- }
-
- ptr++;
-@@ -446,7 +447,7 @@ read_device_map (FILE *fp, char **map, c
- if (! *ptr)
- {
- show_error (line_number, "No filename found");
-- return 0;
-+ continue;
- }
-
- /* Terminate the filename. */
-@@ -464,9 +465,11 @@ read_device_map (FILE *fp, char **map, c
-
- map[drive] = strdup (ptr);
- assert (map[drive]);
-+
-+ retval = 1; /* at least 1 drive configured successfully */
- }
-
-- return 1;
-+ return retval;
- }
-
- /* Initialize the device map MAP. *MAP will be allocated from the heap
-@@ -671,7 +674,7 @@ write_to_partition (char **map, int driv
- int sector, int size, const char *buf)
- {
- char dev[PATH_MAX]; /* XXX */
-- int fd;
-+ int fd, len, pnum;
-
- if ((partition & 0x00FF00) != 0x00FF00)
- {
-@@ -689,7 +692,16 @@ write_to_partition (char **map, int driv
- if (strcmp (dev + strlen(dev) - 5, "/disc") == 0)
- strcpy (dev + strlen(dev) - 5, "/part");
- }
-- sprintf (dev + strlen(dev), "%d", ((partition >> 16) & 0xFF) + 1);
-+
-+ len = strlen(dev);
-+ pnum = ((partition >> 16) & 0xFF);
-+ if (isdigit(dev[len-1]))
-+ {
-+ /* It is obviously some RAID disk: "/dev/<dsk>/c0d0" . "p1" */
-+ sprintf (dev + len, "p%d", pnum + 1);
-+ }
-+ else
-+ sprintf (dev + len, "%d", pnum + 1);
-
- /* Open the partition. */
- fd = open (dev, O_RDWR);
---- grub-0.94/util/grub-md5-crypt.in.orig 2003-07-09 04:45:51.000000000 -0700
-+++ grub-0.94/util/grub-md5-crypt.in 2004-05-11 09:26:31.943224317 -0700
-@@ -88,7 +88,7 @@
- fi
-
- # Run the grub shell.
--$grub_shell --batch --device-map=/dev/null <<EOF \
-+$grub_shell --batch <<EOF \
- | grep "^Encrypted: " | sed 's/^Encrypted: //'
- md5crypt
- $password
+++ /dev/null
---- 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;
-
+++ /dev/null
-diff -ur grub-0.93/Makefile.am grub-0.93.new/Makefile.am
---- grub-0.93/Makefile.am 2002-07-01 16:15:36.000000000 +0200
-+++ grub-0.93.new/Makefile.am 2003-02-04 13:03:36.000000000 +0100
-@@ -2,3 +2,4 @@
- AUTOMAKE_OPTIONS = 1.5
- SUBDIRS = netboot stage2 stage1 lib grub util docs
- EXTRA_DIST = BUGS MAINTENANCE
-+pkgdatadir=$(datadir)
-diff -ur grub-0.93/stage1/Makefile.am grub-0.93.new/stage1/Makefile.am
---- grub-0.93/stage1/Makefile.am 2002-09-08 03:58:08.000000000 +0200
-+++ grub-0.93.new/stage1/Makefile.am 2003-02-04 13:03:36.000000000 +0100
-@@ -1,4 +1,4 @@
--pkglibdir = $(libdir)/$(PACKAGE)/$(host_cpu)-$(host_vendor)
-+pkglibdir = /usr/lib/grub
- nodist_pkglib_DATA = stage1
-
- CLEANFILES = $(nodist_pkglib_DATA)
-diff -ur grub-0.93/stage2/Makefile.am grub-0.93.new/stage2/Makefile.am
---- grub-0.93/stage2/Makefile.am 2002-11-29 19:00:53.000000000 +0100
-+++ grub-0.93.new/stage2/Makefile.am 2003-02-04 13:03:36.000000000 +0100
-@@ -26,7 +26,7 @@
- -DSUPPORT_SERIAL=1 -DSUPPORT_HERCULES=1 -fwritable-strings
-
- # Stage 2 and Stage 1.5's.
--pkglibdir = $(libdir)/$(PACKAGE)/$(host_cpu)-$(host_vendor)
-+pkglibdir = /usr/lib/grub
-
- EXTRA_PROGRAMS = nbloader.exec pxeloader.exec diskless.exec
-
-diff -ur grub-0.93/util/grub-install.in grub-0.93.new/util/grub-install.in
---- grub-0.93/util/grub-install.in 2002-05-20 13:21:50.000000000 +0200
-+++ grub-0.93.new/util/grub-install.in 2003-02-04 13:03:36.000000000 +0100
-@@ -27,7 +27,7 @@
- host_cpu=@host_cpu@
- host_os=@host_os@
- host_vendor=@host_vendor@
--pkglibdir=${libdir}/${PACKAGE}/${host_cpu}-${host_vendor}
-+pkglibdir=${libdir}/${PACKAGE}/
-
- grub_shell=${sbindir}/grub
- grub_set_default=${sbindir}/grub-set-default
-@@ -378,14 +378,19 @@
- exit 1
- fi
-
--# Copy the GRUB images to the GRUB directory.
--for file in ${grubdir}/stage1 ${grubdir}/stage2 ${grubdir}/*stage1_5; do
-- rm -f $file || exit 1
--done
--for file in \
-- ${pkglibdir}/stage1 ${pkglibdir}/stage2 ${pkglibdir}/*stage1_5; do
-- cp -f $file ${grubdir} || exit 1
--done
-+# FHS says that /usr/share is used for architecture independent data,
-+# so all stage-files are directly installed to /usr/lib/grub.
-+# Therefor this part is no longer needed.
-+# <--cut_here-->
-+## Copy the GRUB images to the GRUB directory.
-+#for file in ${grubdir}/stage1 ${grubdir}/stage2 ${grubdir}/*stage1_5; do
-+# rm -f $file || exit 1
-+#done
-+#for file in \
-+# ${pkglibdir}/stage1 ${pkglibdir}/stage2 ${pkglibdir}/*stage1_5; do
-+# cp -f $file ${grubdir} || exit 1
-+#done
-+# <--uncut-->
-
- # Make sure that GRUB reads the same images as the host OS.
- test -n "$mkimg" && img_file=`$mkimg`
-Only in grub-0.93.new/util: grub-install.in.orig
+++ /dev/null
---- grub-0.96/grub/asmstub.c
-+++ grub-0.96/grub/asmstub.c
-@@ -43,6 +43,8 @@
- #include <termios.h>
- #include <signal.h>
-
-+#include <sys/mman.h>
-+
- #ifdef __linux__
- # include <sys/ioctl.h> /* ioctl */
- # if !defined(__GLIBC__) || \
-@@ -140,14 +142,30 @@
- }
-
- assert (grub_scratch_mem == 0);
-- scratch = malloc (0x100000 + EXTENDED_MEMSIZE + 15);
-+#ifdef MAP_32BIT
-+#define MY_MAP_SET MAP_PRIVATE | MAP_GROWSDOWN | MAP_ANONYMOUS | MAP_32BIT
-+#else
-+#define MY_MAP_SET MAP_PRIVATE | MAP_GROWSDOWN | MAP_ANONYMOUS
-+#endif
-+ scratch = mmap(NULL,
-+ 0x100000 + EXTENDED_MEMSIZE + 15,
-+ PROT_EXEC | PROT_READ | PROT_WRITE,
-+ MY_MAP_SET,
-+ -1,
-+ 0);
-+
- assert (scratch);
- grub_scratch_mem = (char *) ((((int) scratch) >> 4) << 4);
-
- /* FIXME: simulate the memory holes using mprot, if available. */
-
- assert (disks == 0);
-- disks = malloc (NUM_DISKS * sizeof (*disks));
-+ disks = mmap(NULL,
-+ NUM_DISKS * sizeof (*disks),
-+ PROT_EXEC | PROT_READ | PROT_WRITE,
-+ MY_MAP_SET,
-+ -1,
-+ 0);
- assert (disks);
- /* Initialize DISKS. */
- for (i = 0; i < NUM_DISKS; i++)
-@@ -213,9 +231,9 @@
- /* Release memory. */
- restore_device_map (device_map);
- device_map = 0;
-- free (disks);
-+ munmap(disks, NUM_DISKS * sizeof (*disks));
- disks = 0;
-- free (scratch);
-+ munmap(scratch, 0x100000 + EXTENDED_MEMSIZE + 15);
- grub_scratch_mem = 0;
-
- if (serial_device)
+++ /dev/null
---- grub-0.96/stage2/builtins.c.orig 2004-06-20 15:33:04.000000000 +0200
-+++ grub-0.96/stage2/builtins.c 2005-09-02 14:38:53.000000000 +0200
-@@ -762,11 +762,11 @@
- default_func (char *arg, int flags)
- {
- #ifndef SUPPORT_DISKLESS
-- if (grub_strcmp (arg, "saved") == 0)
-+ if (grub_strcmp (arg, "saved") == 0 || (saved_entryno & 0x4000))
- {
-- default_entry = saved_entryno;
-- return 0;
-+ default_entry = saved_entryno & 0x3fff;
- }
-+ else
- #endif /* SUPPORT_DISKLESS */
-
- if (! safe_parse_maxint (&arg, &default_entry))
-@@ -787,6 +787,22 @@
- #endif
- };
-
-+#ifndef SUPPORT_DISKLESS
-+static int savedefault_func (char *arg, int flags);
-+void __savedefault_once_reset()
-+{
-+ if (saved_entryno & 0x4000)
-+ {
-+ int saved_current_entryno = current_entryno;
-+ grub_timeout = 0;
-+ current_entryno = default_entry;
-+ savedefault_func("\0", BUILTIN_SCRIPT);
-+ current_entryno = saved_current_entryno;
-+ saved_entryno &= 0x3fff;
-+ }
-+}
-+#endif /* SUPPORT_DISKLESS */
-+
- \f
- #ifdef GRUB_UTIL
- /* device */
---- grub-0.96/stage2/stage2.c~ 2004-07-24 20:53:47.000000000 +0200
-+++ grub-0.96/stage2/stage2.c 2005-09-02 14:45:04.000000000 +0200
-@@ -827,6 +827,7 @@
- return pos;
- }
-
-+extern void __savedefault_once_reset();
-
- /* This is the starting function in C. */
- void
-@@ -1048,7 +1049,9 @@
- }
- while (is_preset);
- }
--
-+#ifndef SUPPORT_DISKLESS
-+ __savedefault_once_reset();
-+#endif
- if (! num_entries)
- {
- /* If no acceptable config file, goto command-line, starting
+++ /dev/null
---- docs/grub.texi
-+++ docs/grub.texi
-@@ -2118,6 +2118,7 @@
- * default:: Set the default entry
- * fallback:: Set the fallback entry
- * hiddenmenu:: Hide the menu interface
-+* gfxmenu:: Use graphical menu interface
- * timeout:: Set the timeout
- * title:: Start a menu entry
- @end menu
-@@ -2150,6 +2151,15 @@
- @end deffn
-
-
-+@node gfxmenu
-+@subsection gfxmenu
-+
-+@deffn Command gfxmenu file
-+Use the graphical menu interface. The graphics data are taken from
-+@var{file} and must be created using 'mkbootmsg' from the gfxboot package.
-+@end deffn
-+
-+
- @node hiddenmenu
- @subsection hiddenmenu
-
---- grub/asmstub.c
-+++ grub/asmstub.c
-@@ -498,6 +498,32 @@
- return 0;
- }
-
-+/* graphical menu functions . */
-+int
-+gfx_init (gfx_data_t *gfx_data)
-+{
-+ return 0;
-+}
-+
-+int
-+gfx_done (gfx_data_t *gfx_data)
-+{
-+ return 0;
-+}
-+
-+int
-+gfx_input (gfx_data_t *gfx_data, int *menu_entry)
-+{
-+ return 0;
-+}
-+
-+int
-+gfx_setup_menu (gfx_data_t *gfx_data)
-+{
-+ return 0;
-+}
-+
-+
- /* low-level timing info */
- int
- getrtsecs (void)
---- stage2/asm.S
-+++ stage2/asm.S
-@@ -1614,6 +1614,286 @@
- popl %ebp
- ret
-
-+
-+/*
-+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-+ *
-+ * graphical menu functions
-+ *
-+ */
-+
-+/*
-+ * int gfx_init (gfx_data_t *gfx_data)
-+ *
-+ * init gfx things
-+ *
-+ * return vales:
-+ * 0: ok
-+ * 1: failed
-+ * sets gfx_data->ok
-+ */
-+
-+ENTRY(gfx_init)
-+ pushl %ebp
-+ movl %esp, %ebp
-+
-+ pushl %edi
-+ pushl %esi
-+ pushl %ebx
-+
-+ movl 8(%ebp),%edx
-+ movl %edx,%edi
-+ leal gfx_ofs_sys_cfg(%edx),%esi
-+ andl $0xf,%edi
-+ shrl $4,%edx
-+
-+ pushl %ebp
-+
-+ call EXT_C(prot_to_real)
-+ .code16
-+
-+ pushw %ds
-+ movw %dx,%ds
-+
-+ lcall *gfx_ofs_jmp_table + 4 * 0 (%di)
-+
-+ sbbl %ebx,%ebx
-+ negl %ebx
-+
-+ popw %ds
-+
-+ DATA32 call EXT_C(real_to_prot)
-+ .code32
-+
-+ popl %ebp
-+
-+ movl %ebx,%eax
-+ xorl $1,%ebx
-+ movl 8(%ebp),%edx
-+ movl %ebx,gfx_ofs_ok(%edx)
-+
-+ popl %ebx
-+ popl %esi
-+ popl %edi
-+
-+ popl %ebp
-+ ret
-+
-+
-+/*
-+ * int gfx_done (gfx_data_t *gfx_data)
-+ *
-+ * shut down gfx things
-+ *
-+ * return vales:
-+ * always 0
-+ * sets gfx_data->ok
-+ */
-+
-+ENTRY(gfx_done)
-+ pushl %ebp
-+ movl %esp, %ebp
-+
-+ pushl %edi
-+ pushl %esi
-+ pushl %ebx
-+
-+ movl 8(%ebp),%edx
-+ movl %edx,%ebx
-+ andl $0xf,%ebx
-+ shrl $4,%edx
-+
-+ pushl %ebp
-+
-+ call EXT_C(prot_to_real)
-+ .code16
-+
-+ pushw %ds
-+
-+ movw %dx,%ds
-+
-+ lcall *gfx_ofs_jmp_table + 4 * 1 (%bx)
-+
-+ popw %ds
-+
-+ DATA32 call EXT_C(real_to_prot)
-+ .code32
-+
-+ popl %ebp
-+
-+ xorl %eax,%eax
-+ movl 8(%ebp),%edx
-+ movl %eax,gfx_ofs_ok(%edx)
-+
-+ popl %ebx
-+ popl %esi
-+ popl %edi
-+
-+ popl %ebp
-+ ret
-+
-+
-+/*
-+ * int gfx_input (gfx_data_t *gfx_data, int *menu_entry)
-+ *
-+ * let user enter a command line
-+ *
-+ * uses gfx_data->cmdline as buffer
-+ *
-+ * return values:
-+ * 1: abort
-+ * 2: boot
-+ * menu_entry: selected entry
-+ */
-+
-+ENTRY(gfx_input)
-+ pushl %ebp
-+ movl %esp, %ebp
-+
-+ pushl %edi
-+ pushl %esi
-+ pushl %ebx
-+
-+ movl 8(%ebp),%edx
-+ movl %edx,%ebx
-+ leal gfx_ofs_sys_cfg(%edx),%esi
-+ andl $0xf,%ebx
-+ shrl $4,%edx
-+
-+ pushl %ebp
-+
-+ call EXT_C(prot_to_real)
-+ .code16
-+
-+ pushw %ds
-+
-+ movw %dx,%ds
-+
-+ movl gfx_ofs_cmdline(%bx),%edi
-+ movl gfx_ofs_cmdline_len(%bx),%ecx
-+ movl gfx_ofs_timeout(%bx),%eax
-+ imull $18,%eax
-+
-+ lcall *gfx_ofs_jmp_table + 4 * 2 (%bx)
-+
-+ movl %eax,%ecx
-+
-+ popw %ds
-+
-+ DATA32 call EXT_C(real_to_prot)
-+ .code32
-+
-+ popl %ebp
-+
-+ movl 12(%ebp),%edx
-+ movl %ebx,(%edx)
-+
-+ movl %ecx,%eax
-+
-+ popl %ebx
-+ popl %esi
-+ popl %edi
-+
-+ popl %ebp
-+ ret
-+
-+
-+/*
-+ * int gfx_setup_menu (gfx_data_t *gfx_data)
-+ *
-+ * draw boot menu
-+ *
-+ * return values:
-+ * always 0
-+ */
-+
-+/* menu entry descriptor */
-+#define menu_entries 0
-+#define menu_default 2 /* seg:ofs */
-+#define menu_ent_list 6 /* seg:ofs */
-+#define menu_ent_size 10
-+#define menu_arg_list 12 /* seg:ofs */
-+#define menu_arg_size 16
-+#define sizeof_menu_desc 18
-+
-+ENTRY(gfx_setup_menu)
-+ pushl %ebp
-+ movl %esp, %ebp
-+
-+ pushl %edi
-+ pushl %esi
-+ pushl %ebx
-+
-+ movl 8(%ebp),%edx
-+ movl %edx,%ebx
-+ andl $0xf,%ebx
-+ shrl $4,%edx
-+
-+ call EXT_C(prot_to_real)
-+ .code16
-+
-+ pushw %ds
-+
-+ movw %dx,%ds
-+ shll $4,%edx
-+
-+ subw $sizeof_menu_desc,%sp
-+ movw %esp,%ebp
-+
-+ movl gfx_ofs_menu_entries(%bx),%eax
-+ movw %ax,menu_entries(%bp)
-+
-+ movl gfx_ofs_menu_default_entry(%bx),%eax
-+ subl %edx,%eax
-+ movw %ax,menu_default(%bp)
-+ movw %ds,menu_default+2(%bp)
-+
-+ movl gfx_ofs_menu_list(%bx),%eax
-+ subl %edx,%eax
-+ movw %ax,menu_ent_list(%bp)
-+ movw %ds,menu_ent_list+2(%bp)
-+
-+ movl gfx_ofs_menu_entry_len(%bx),%eax
-+ movw %ax,menu_ent_size(%bp)
-+
-+ movl gfx_ofs_args_list(%bx),%eax
-+ subl %edx,%eax
-+ movw %ax,menu_arg_list(%bp)
-+ movw %ds,menu_arg_list+2(%bp)
-+
-+ movl gfx_ofs_args_entry_len(%bx),%eax
-+ movw %ax,menu_arg_size(%bp)
-+
-+ movl %ss,%esi
-+ shll $4,%esi
-+ addl %ebp,%esi
-+
-+ lcall %ds: *gfx_ofs_jmp_table + 4 * 3 (%bx)
-+
-+ addw $sizeof_menu_desc,%sp
-+
-+ popw %ds
-+
-+ DATA32 call EXT_C(real_to_prot)
-+ .code32
-+
-+ xorl %eax,%eax
-+
-+ popl %ebx
-+ popl %esi
-+ popl %edi
-+
-+ popl %ebp
-+ ret
-+
-+
-+/*
-+ *
-+ * end graphics stuff
-+ *
-+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-+ */
-+
-
- /*
- * gateA20(int linear)
---- stage2/builtins.c
-+++ stage2/builtins.c
-@@ -63,6 +63,8 @@
- int fallback_entries[MAX_FALLBACK_ENTRIES];
- /* The number of current entry. */
- int current_entryno;
-+/* graphics file */
-+char graphics_file[64];
- /* The address for Multiboot command-line buffer. */
- static char *mb_cmdline;
- /* The password. */
-@@ -1351,6 +1353,26 @@
- };
-
- \f
-+/* graphics */
-+static int
-+gfxmenu_func (char *arg, int flags)
-+{
-+ memmove(graphics_file, arg, sizeof graphics_file - 1);
-+ graphics_file[sizeof graphics_file - 1] = 0;
-+
-+ return 0;
-+}
-+
-+static struct builtin builtin_gfxmenu =
-+{
-+ "gfxmenu",
-+ gfxmenu_func,
-+ BUILTIN_MENU | BUILTIN_HELP_LIST,
-+ "gfxmenu FILE",
-+ "Use the graphical menu from FILE."
-+};
-+
-+\f
- /* geometry */
- static int
- geometry_func (char *arg, int flags)
-@@ -4874,6 +4896,7 @@
- &builtin_find,
- &builtin_fstest,
- &builtin_geometry,
-+ &builtin_gfxmenu,
- &builtin_halt,
- &builtin_help,
- &builtin_hiddenmenu,
---- stage2/shared.h
-+++ stage2/shared.h
-@@ -374,6 +374,22 @@
- #endif /* WITHOUT_LIBC_STUBS */
-
-
-+/* see typedef gfx_data_t below */
-+#define gfx_ofs_ok 0x00
-+#define gfx_ofs_code_seg 0x04
-+#define gfx_ofs_jmp_table 0x08
-+#define gfx_ofs_sys_cfg 0x38
-+#define gfx_ofs_cmdline 0x6c
-+#define gfx_ofs_cmdline_len 0x70
-+#define gfx_ofs_menu_list 0x74
-+#define gfx_ofs_menu_default_entry 0x78
-+#define gfx_ofs_menu_entries 0x7c
-+#define gfx_ofs_menu_entry_len 0x80
-+#define gfx_ofs_args_list 0x84
-+#define gfx_ofs_args_entry_len 0x88
-+#define gfx_ofs_timeout 0x8c
-+
-+
- #ifndef ASM_FILE
- /*
- * Below this should be ONLY defines and other constructs for C code.
-@@ -595,6 +611,38 @@
- extern int default_entry;
- extern int current_entryno;
-
-+
-+/*
-+ * graphics menu stuff
-+ *
-+ * Note: gfx_data and all data referred to in it must lie within a 64k area.
-+ */
-+typedef struct {
-+ unsigned ok; /* set while we're in graphics mode */
-+ unsigned code_seg; /* code segment of binary graphics code */
-+ unsigned jmp_table[12]; /* link to graphics functions */
-+ unsigned char sys_cfg[52]; /* sys_cfg[0]: identifies boot loader (grub == 2) */
-+ char *cmdline; /* command line returned by gfx_input() */
-+ unsigned cmdline_len; /* length of the above */
-+ char *menu_list; /* list of menu entries, each of fixed length (menu_entry_len) */
-+ char *menu_default_entry; /* the default entry */
-+ unsigned menu_entries; /* number of entries in menu_list */
-+ unsigned menu_entry_len; /* one entry */
-+ char *args_list; /* same structure as menu_list, menu_entries entries */
-+ unsigned args_entry_len; /* one entry */
-+ unsigned timeout; /* in seconds (0: no timeout) */
-+} __attribute__ ((packed)) gfx_data_t;
-+
-+extern gfx_data_t *graphics_data;
-+
-+/* pointer to graphics image data */
-+extern char graphics_file[64];
-+
-+int gfx_init(gfx_data_t *gfx_data);
-+int gfx_done(gfx_data_t *gfx_data);
-+int gfx_input(gfx_data_t *gfx_data, int *menu_entry);
-+int gfx_setup_menu(gfx_data_t *gfx_data);
-+
- /* The constants for password types. */
- typedef enum
- {
---- stage2/stage2.c
-+++ stage2/stage2.c
-@@ -22,6 +22,8 @@
-
- grub_jmp_buf restart_env;
-
-+gfx_data_t *graphics_data;
-+
- #if defined(PRESET_MENU_STRING) || defined(SUPPORT_DISKLESS)
-
- # if defined(PRESET_MENU_STRING)
-@@ -310,6 +312,12 @@
-
- if (! auth && password)
- {
-+ if (*graphics_file)
-+ {
-+ printf ("\
-+ WARNING: graphical menu doesn\'t work\
-+ in conjunction with the password feature\n" );
-+ }
- printf ("\
- Press enter to boot the selected OS or \'p\' to enter a\n\
- password to unlock the next set of features.");
-@@ -753,6 +761,493 @@
- }
-
-
-+
-+#if 0
-+/* for debugging */
-+static void hexdump(unsigned char *buf, unsigned len)
-+{
-+ int i, j = 0;
-+ char s[17];
-+ unsigned addr = (unsigned) buf;
-+
-+ s[16] = 0;
-+ while(len--) {
-+ i = buf[j];
-+ i = i & 0xff;
-+ s[j & 15] = (i >= 0x20 && i <= 0x7e) ? i : '.';
-+ if(!(j & 15)) {
-+ printf("%x ", j + addr);
-+ }
-+ if(!(j & 7) && (j & 15)) printf(" ");
-+ /* stupid grub_printf */
-+ printf("%x", (i >> 4) & 0x0f);
-+ printf("%x ", i & 0x0f);
-+ if(!(++j & 15)) {
-+ printf(" %s\n", s);
-+ }
-+ }
-+
-+ if(j & 15) {
-+ s[j & 15] = 0;
-+ if(!(j & 8)) printf(" ");
-+ i = 1 + 3 * (16 - (j & 15));
-+ while(i--) printf(" ");
-+ printf("%s\n", s);
-+ }
-+}
-+#endif
-+
-+
-+/* kernel + (grub-)module options */
-+#define GFX_CMD_BUF_SIZE 512
-+
-+/* command line separator char */
-+#define GFX_CMD_SEP 1
-+
-+/*
-+ * Go through config entry and find kernel args, if any.
-+ * Put things into buf and return it.
-+ */
-+static char *get_kernel_args(char *cfg, char *buf)
-+{
-+ int i, j;
-+ char *s, *t = "", *p, *t2;
-+
-+ *(p = buf) = 0;
-+
-+ for(j = 0; ; j++) {
-+ s = get_entry(cfg, j, 0);
-+ if(!*s) break;
-+ if(
-+ (!memcmp(s, "kernel", 6) || !memcmp(s, "module", 6)) &&
-+ (s[6] == ' ' || s[6] == '\t')
-+ ) {
-+ t = skip_to(0, s);
-+ t2 = s[0] == 'm' ? strstr(t, "initrd") : NULL;
-+ if(*t) t = skip_to(0, t);
-+ if(t2 && t2 < t) break; /* module is likely a normal initrd -> skip */
-+ i = strlen(t);
-+ if(p - buf + i > GFX_CMD_BUF_SIZE - 2) break;
-+ *p++ = GFX_CMD_SEP;
-+ strcpy(p, t);
-+ p += i;
-+
-+ continue;
-+ }
-+ }
-+
-+ if(*buf) buf++; /* skip initial separator char */
-+
-+ return buf;
-+}
-+
-+
-+/*
-+ * Check header and return code start offset.
-+ */
-+static unsigned magic_ok(unsigned char *buf)
-+{
-+ if(
-+ *(unsigned *) buf == 0x0b2d97f00 && /* magic id */
-+ (buf[4] == 8) /* version 8 */
-+ ) {
-+ return *(unsigned *) (buf + 8);
-+ }
-+
-+ return 0;
-+}
-+
-+
-+/*
-+ * Search cpio archive for gfx file.
-+ */
-+static unsigned find_file(unsigned char *buf, unsigned len, unsigned *gfx_file_start, unsigned *file_len)
-+{
-+ unsigned i, fname_len, code_start = 0;
-+
-+ *gfx_file_start = 0;
-+
-+ for(i = 0; i < len;) {
-+ if((len - i) >= 0x1a && (buf[i] + (buf[i + 1] << 8)) == 0x71c7) {
-+ fname_len = *(unsigned short *) (buf + i + 20);
-+ *file_len = *(unsigned short *) (buf + i + 24) + (*(unsigned short *) (buf + i + 22) << 16);
-+ i += 26 + fname_len;
-+ i = ((i + 1) & ~1);
-+ if((code_start = magic_ok(buf + i))) {
-+ *gfx_file_start = i;
-+ return code_start;
-+ }
-+ i += *file_len;
-+ i = ((i + 1) & ~1);
-+ }
-+ else {
-+ break;
-+ }
-+ }
-+
-+ return code_start;
-+}
-+
-+static inline unsigned char * stack_ptr(void)
-+{
-+ unsigned char * u;
-+
-+ asm("movl %%esp, %0" : "=r" (u));
-+
-+ return u;
-+}
-+
-+static void sleep(int delay)
-+{
-+ int tick, last_tick = currticks();
-+
-+ delay *= 18;
-+
-+ while(delay--) {
-+ while((tick = currticks()) == last_tick) { }
-+ last_tick = tick;
-+ }
-+}
-+
-+static void wait_for_key()
-+{
-+ printf("Press a key to continue...");
-+ getkey();
-+ printf("\r \r");
-+}
-+
-+
-+/*
-+ * Leave that much space on the heap. Everything else goes to the graphics
-+ * functions.
-+ *
-+ * 0x2000 is _not_ enough
-+ */
-+#define MIN_HEAP_SIZE 0x4000
-+#define MIN_GFX_FREE 0x1000
-+
-+#define SC_BOOTLOADER 0
-+#define SC_FAILSAFE 3
-+#define SC_SYSCONFIG_SIZE 4
-+#define SC_BOOTLOADER_SEG 8
-+#define SC_XMEM_0 24
-+#define SC_XMEM_1 26
-+#define SC_XMEM_2 28
-+#define SC_XMEM_3 30
-+#define SC_FILE 32
-+#define SC_ARCHIVE_START 36
-+#define SC_ARCHIVE_END 40
-+#define SC_MEM0_START 44
-+#define SC_MEM0_END 48
-+
-+/*
-+ * Does normally not return.
-+ */
-+static void
-+run_graphics_menu (char *menu_entries, char *config_entries, int num_entries,
-+ char *heap, int entryno)
-+{
-+ unsigned char *buf, *buf_ext;
-+ unsigned buf_size, buf_ext_size, code_start, file_start;
-+ char *s, *t, *t2, *cfg, *new_config, *p;
-+ char *saved_heap;
-+ int i, j, max_len, gfx_file_size, verbose;
-+ int selected_entry;
-+ gfx_data_t *gfx_data;
-+ char *cmd_buf;
-+ unsigned mem0_start, mem0_end, file_len;
-+
-+ /*
-+ * check gfx_data_t struct offsets for consistency; gcc will optimize away
-+ * the whole block
-+ */
-+
-+ /* dummy function to make ld fail */
-+ {
-+ extern void wrong_struct_size(void);
-+ #define gfx_ofs_check(a) if(gfx_ofs_##a != (char *) &gfx_data->a - (char *) gfx_data) wrong_struct_size();
-+ gfx_ofs_check(ok);
-+ gfx_ofs_check(code_seg);
-+ gfx_ofs_check(jmp_table);
-+ gfx_ofs_check(sys_cfg);
-+ gfx_ofs_check(cmdline);
-+ gfx_ofs_check(cmdline_len);
-+ gfx_ofs_check(menu_list);
-+ gfx_ofs_check(menu_default_entry);
-+ gfx_ofs_check(menu_entries);
-+ gfx_ofs_check(menu_entry_len);
-+ gfx_ofs_check(args_list);
-+ gfx_ofs_check(args_entry_len);
-+ gfx_ofs_check(timeout);
-+ #undef gfx_ofs_check
-+ }
-+
-+ if(!num_entries) return;
-+
-+ graphics_data = gfx_data = (gfx_data_t *) heap;
-+ heap += sizeof *gfx_data;
-+ memset(gfx_data, 0, sizeof *gfx_data);
-+
-+ gfx_data->sys_cfg[SC_BOOTLOADER] = 2; /* bootloader: grub */
-+ gfx_data->sys_cfg[SC_SYSCONFIG_SIZE] = 52; /* config data size */
-+ *(unsigned short *) (gfx_data->sys_cfg + SC_BOOTLOADER_SEG) = (unsigned) gfx_data >> 4; /* segment */
-+ gfx_data->sys_cfg[SC_XMEM_0] = 0x21; /* 1MB @ 2MB */
-+ gfx_data->sys_cfg[SC_XMEM_1] = 0x41; /* 1MB @ 4MB */
-+ verbose = (*(unsigned char *) 0x417) & 3 ? 1 : 0; /* SHIFT pressed */
-+ gfx_data->sys_cfg[SC_FAILSAFE] = verbose;
-+
-+ gfx_data->timeout = grub_timeout >= 0 ? grub_timeout : 0;
-+
-+
-+ /* setup command line edit buffer */
-+
-+ gfx_data->cmdline_len = 256;
-+
-+ gfx_data->cmdline = heap;
-+ heap += gfx_data->cmdline_len;
-+ memset(gfx_data->cmdline, 0, gfx_data->cmdline_len);
-+
-+ cmd_buf = heap;
-+ heap += GFX_CMD_BUF_SIZE;
-+
-+ /* setup menu entries */
-+
-+ for(i = max_len = 0; i < num_entries; i++) {
-+ j = strlen(get_entry(menu_entries, i, 0));
-+ if(j > max_len) max_len = j;
-+ }
-+
-+ if(!max_len) return;
-+
-+ gfx_data->menu_entry_len = max_len + 1;
-+ gfx_data->menu_entries = num_entries;
-+
-+ gfx_data->menu_list = heap;
-+ heap += gfx_data->menu_entry_len * gfx_data->menu_entries;
-+
-+ memset(gfx_data->menu_list, 0, gfx_data->menu_entry_len * gfx_data->menu_entries);
-+
-+ for(i = 0; i < (int) gfx_data->menu_entries; i++) {
-+ strcpy(gfx_data->menu_list + i * gfx_data->menu_entry_len, get_entry(menu_entries, i, 0));
-+ }
-+
-+ gfx_data->menu_default_entry = gfx_data->menu_list + entryno * gfx_data->menu_entry_len;
-+
-+
-+ /* setup list of kernel args */
-+
-+ for(i = max_len = 0; i < num_entries; i++) {
-+ s = get_kernel_args(get_entry(config_entries, i, 1), cmd_buf);
-+ j = strlen(s);
-+ if(j > max_len) max_len = j;
-+ }
-+
-+ gfx_data->args_entry_len = max_len + 1;
-+
-+ gfx_data->args_list = heap;
-+ heap += gfx_data->args_entry_len * gfx_data->menu_entries;
-+
-+ memset(gfx_data->args_list, 0, gfx_data->args_entry_len * gfx_data->menu_entries);
-+
-+ for(i = 0; i < (int) gfx_data->menu_entries; i++) {
-+ strcpy(gfx_data->args_list + i* gfx_data->args_entry_len, get_kernel_args(get_entry(config_entries, i, 1), cmd_buf));
-+ }
-+
-+
-+ /* go back here when we no longer need the graphics data */
-+ saved_heap = heap;
-+
-+
-+ /* get memory area to be used by graphics functions */
-+
-+ /* use 1MB starting at 2MB as file buffer */
-+ buf_ext = (unsigned char *) (2 << 20);
-+ buf_ext_size = 1 << 20;
-+
-+ /* must be 16-byte aligned */
-+ buf = (unsigned char *) (((unsigned) heap + 0xf) & ~0xf);
-+
-+ buf_size = stack_ptr() - buf - MIN_HEAP_SIZE;
-+ buf_size &= ~0xf;
-+
-+ mem0_start = (unsigned) buf;
-+ mem0_end = mem0_start + buf_size;
-+
-+ if(verbose) {
-+ printf("low memory 0x%x - 0x%x (%d bytes)\n", mem0_start, mem0_end, buf_size);
-+ wait_for_key();
-+ }
-+
-+ heap += buf_size;
-+
-+ /* read the file */
-+
-+ if(!grub_open(graphics_file)) {
-+ printf("%s: file not found\n", graphics_file);
-+ sleep(5);
-+ heap = saved_heap;
-+ return;
-+ }
-+
-+ gfx_file_size = grub_read(buf_ext, buf_ext_size);
-+
-+ grub_close();
-+
-+ if(gfx_file_size <= 0) {
-+ printf("%s: read error\n", graphics_file);
-+ sleep(5);
-+ heap = saved_heap;
-+ return;
-+ }
-+
-+ if(verbose) {
-+ printf("%s: %d bytes (%d bytes left)\n", graphics_file, gfx_file_size, buf_ext_size - gfx_file_size);
-+ wait_for_key();
-+ }
-+
-+ /* locate file inside cpio archive */
-+ if(!(code_start = find_file(buf_ext, gfx_file_size, &file_start, &file_len))) {
-+ printf("%s: invalid file format\n", graphics_file);
-+ sleep(5);
-+ heap = saved_heap;
-+ return;
-+ }
-+
-+ if(verbose) {
-+ printf("init: start 0x%x, len %d; code offset 0x%x\n", file_start, file_len, code_start);
-+ wait_for_key();
-+ }
-+
-+ if(file_len - code_start + MIN_GFX_FREE > buf_size) {
-+ printf("not enough free memory: %d extra bytes need\n", file_len - code_start + MIN_GFX_FREE - buf_size);
-+ sleep(5);
-+ heap = saved_heap;
-+ return;
-+ }
-+
-+ memcpy((void *) buf, (void *) (buf_ext + file_start + code_start), file_len - code_start);
-+
-+ mem0_start += file_len - code_start;
-+ mem0_start = (mem0_start + 3) & ~3; /* align */
-+
-+ /* init interface to graphics functions */
-+
-+ *(unsigned *) (gfx_data->sys_cfg + SC_FILE) = (unsigned) buf_ext + file_start;
-+ *(unsigned *) (gfx_data->sys_cfg + SC_ARCHIVE_START) = (unsigned) buf_ext;
-+ *(unsigned *) (gfx_data->sys_cfg + SC_ARCHIVE_END) = (unsigned) buf_ext + gfx_file_size;
-+ *(unsigned *) (gfx_data->sys_cfg + SC_MEM0_START) = mem0_start;
-+ *(unsigned *) (gfx_data->sys_cfg + SC_MEM0_END) = mem0_end;
-+
-+ gfx_data->code_seg = (unsigned) buf >> 4;
-+
-+ if(verbose) {
-+ printf("init 0x%x, archive 0x%x - 0x%x, low mem 0x%x - 0x%x\ncode seg 0x%x\n",
-+ (unsigned) buf_ext + file_start,
-+ (unsigned) buf_ext, (unsigned) buf_ext + gfx_file_size,
-+ mem0_start, mem0_end, gfx_data->code_seg
-+ );
-+ wait_for_key();
-+ }
-+
-+ for(i = 0; (unsigned) i < sizeof gfx_data->jmp_table / sizeof *gfx_data->jmp_table; i++) {
-+ gfx_data->jmp_table[i] = (gfx_data->code_seg << 16) + ((unsigned short *) buf)[i];
-+ }
-+
-+ if(verbose) {
-+ for(i = 0; i < 12; i++) {
-+ printf("%d: 0x%x\n", i, gfx_data->jmp_table[i]);
-+ }
-+
-+ for(i = 0; i < gfx_data->menu_entries; i++) {
-+ printf("\"%s\" -- \"%s\"\n",
-+ gfx_data->menu_list + i * gfx_data->menu_entry_len,
-+ gfx_data->args_list + i * gfx_data->args_entry_len
-+ );
-+ }
-+
-+ printf("default: \"%s\"\n", gfx_data->menu_default_entry);
-+ wait_for_key();
-+ }
-+
-+ /* switch to graphics mode */
-+
-+ if(gfx_init(gfx_data)) {
-+ printf("graphics initialization failed\n");
-+ sleep(5);
-+ heap = saved_heap;
-+ return;
-+ }
-+
-+ gfx_setup_menu(gfx_data);
-+
-+ i = gfx_input(gfx_data, &selected_entry);
-+
-+ /* ESC -> show text menu */
-+ if(i == 1) {
-+ gfx_done(gfx_data);
-+ grub_timeout = -1;
-+
-+ heap = saved_heap;
-+ return;
-+ }
-+
-+ gfx_done(gfx_data);
-+
-+ heap = saved_heap; /* free most of the graphics data */
-+
-+ // printf("cmdline: >%s<, entry = %d\n", gfx_data->cmdline, selected_entry);
-+
-+ if(selected_entry < 0 || selected_entry > num_entries) return;
-+
-+
-+ /* create new config with modified kernel option */
-+
-+ cfg = get_entry(config_entries, selected_entry, 1);
-+
-+ new_config = heap;
-+
-+ for(p = gfx_data->cmdline, i = 0; ; i++) {
-+ s = get_entry(cfg, i, 0);
-+ if(!*s) {
-+ if(!i) *heap++ = 0;
-+ *heap++ = 0;
-+ break;
-+ }
-+ /* note: must match get_kernel_args() */
-+ if(
-+ (!memcmp(s, "kernel", 6) || !memcmp(s, "module", 6)) &&
-+ (s[6] == ' ' || s[6] == '\t')
-+ ) {
-+ t = skip_to(0, s);
-+ t2 = s[0] == 'm' ? strstr(t, "initrd") : NULL;
-+ if(*t) t = skip_to(0, t);
-+ if(t2 && t2 < t) { /* module is likely a normal initrd -> skip */
-+ strcpy(heap, s);
-+ heap += strlen(s) + 1;
-+ continue;
-+ }
-+ memmove(heap, s, t - s);
-+ heap += t - s;
-+ *heap++ = ' ';
-+ while(*p && *p != GFX_CMD_SEP) *heap++ = *p++;
-+ *heap++ = 0;
-+ if(*p == GFX_CMD_SEP) p++;
-+ }
-+ else {
-+ strcpy(heap, s);
-+ heap += strlen(s) + 1;
-+ }
-+ }
-+
-+ *heap++ = 0;
-+
-+ // hexdump(new_config, heap - new_config);
-+ // getkey();
-+
-+ run_script(new_config, heap);
-+}
-+
-+
- static int
- get_line_from_config (char *cmdline, int maxlen, int read_from_file)
- {
-@@ -1062,9 +1557,12 @@
- }
- else
- {
-- /* Run menu interface. */
-- run_menu (menu_entries, config_entries, num_entries,
-- menu_entries + menu_len, default_entry);
-+ if (*graphics_file && !password && show_menu && grub_timeout)
-+ {
-+ run_graphics_menu(menu_entries, config_entries, num_entries,menu_entries + menu_len, default_entry);
-+ }
-+ /* Run menu interface. */
-+ run_menu (menu_entries, config_entries, num_entries, menu_entries + menu_len, default_entry);
- }
- }
- }
+++ /dev/null
---- grub-0.95/stage2/builtins.c.orig 2004-05-14 21:30:52.000000000 +0200
-+++ grub-0.95/stage2/builtins.c 2005-03-02 17:01:27.568051824 +0100
-@@ -3884,6 +3884,9 @@
- }
- }
-
-+ /* force buffer cache invalidation after embedding */
-+ buf_drive = -1;
-+
- /* Construct a string that is used by the command "install" as its
- arguments. */
- sprint_device (installed_drive, installed_partition);
+++ /dev/null
-diff -ru ../grub-0.97-save/docs/grub.8 ./docs/grub.8
---- ../grub-0.97-save/docs/grub.8 2005-05-08 04:48:56.000000000 +0200
-+++ ./docs/grub.8 2006-09-18 21:26:18.800377712 +0200
-@@ -15,7 +15,7 @@
- specify stage2 boot_drive [default=0x0]
- .TP
- \fB\-\-config\-file\fR=\fIFILE\fR
--specify stage2 config_file [default=/boot/grub/menu.lst]
-+specify stage2 config_file [default=/boot/grub/grub.conf]
- .TP
- \fB\-\-device\-map\fR=\fIFILE\fR
- use the device map file FILE
-diff -ru ../grub-0.97-save/docs/grub.texi ./docs/grub.texi
---- ../grub-0.97-save/docs/grub.texi 2006-09-16 21:29:53.000000000 +0200
-+++ ./docs/grub.texi 2006-09-18 21:29:54.573575200 +0200
-@@ -687,7 +687,7 @@
- For booting from a CD-ROM, GRUB uses a special Stage 2 called
- @file{stage2_eltorito}. The only GRUB files you need to have in your
- bootable CD-ROM are this @file{stage2_eltorito} and optionally a config file
--@file{menu.lst}. You don't need to use @file{stage1} or @file{stage2},
-+@file{grub.conf}. You don't need to use @file{stage1} or @file{stage2},
- because El Torito is quite different from the standard boot process.
-
- Here is an example of procedures to make a bootable CD-ROM
-@@ -710,7 +710,7 @@
- $ @kbd{cp /usr/share/grub/i386-pc/stage2_eltorito iso/boot/grub}
- @end example
-
--If desired, make the config file @file{menu.lst} under @file{iso/boot/grub}
-+If desired, make the config file @file{grub.conf} under @file{iso/boot/grub}
- (@pxref{Configuration}), and copy any files and directories for the disc to the
- directory @file{iso/}.
-
-@@ -1265,7 +1265,7 @@
- keys) that will do everything to boot an OS.
-
- To enable the menu, you need a configuration file,
--@file{menu.lst} under the boot directory. We'll analyze an example
-+@file{grub.conf} under the boot directory. We'll analyze an example
- file.
-
- The file first contains some general settings, the menu interface
-@@ -1538,7 +1538,7 @@
- foo:ht=1:ha=63655d0334a7:ip=145.71.35.127:\
- :bf=/nbgrub:\
- :tc=.allhost:\
-- :T150="(nd)/tftpboot/menu.lst.foo":
-+ :T150="(nd)/tftpboot/grub.conf.foo":
- @end group
- @end example
-
-@@ -1882,8 +1882,8 @@
-
- An absolute file name resembles a Unix absolute file name, using
- @samp{/} for the directory separator (not @samp{\} as in DOS). One
--example is @samp{(hd0,0)/boot/grub/menu.lst}. This means the file
--@file{/boot/grub/menu.lst} in the first partition of the first hard
-+example is @samp{(hd0,0)/boot/grub/grub.conf}. This means the file
-+@file{/boot/grub/grub.conf} in the first partition of the first hard
- disk. If you omit the device name in an absolute file name, GRUB uses
- GRUB's @dfn{root device} implicitly. So if you set the root device to,
- say, @samp{(hd1,0)} by the command @command{root} (@pxref{root}), then
-@@ -3559,7 +3559,7 @@
-
- @item --config-file=@var{file}
- Read the configuration file @var{file} instead of
--@file{/boot/grub/menu.lst}. The format is the same as the normal GRUB
-+@file{/boot/grub/grub.conf}. The format is the same as the normal GRUB
- syntax. See @ref{Filesystem}, for more information.
-
- @item --boot-drive=@var{drive}
-diff -ru ../grub-0.97-save/grub/asmstub.c ./grub/asmstub.c
---- ../grub-0.97-save/grub/asmstub.c 2006-09-16 21:29:52.000000000 +0200
-+++ ./grub/asmstub.c 2006-09-18 21:31:08.793292088 +0200
-@@ -73,7 +73,7 @@
- unsigned long boot_drive = 0;
- int saved_entryno = 0;
- char version_string[] = VERSION;
--char config_file[128] = "/boot/grub/menu.lst"; /* FIXME: arbitrary */
-+char config_file[128] = "/boot/grub/grub.conf"; /* FIXME: arbitrary */
- unsigned long linux_text_len = 0;
- char *linux_data_tmp_addr = 0;
- char *linux_data_real_addr = 0;
-diff -ru ../grub-0.97-save/stage1/Makefile.am ./stage1/Makefile.am
---- ../grub-0.97-save/stage1/Makefile.am 2006-09-16 21:29:52.000000000 +0200
-+++ ./stage1/Makefile.am 2006-09-18 21:09:46.550222664 +0200
-@@ -1,4 +1,4 @@
--pkglibdir = /usr/lib/grub
-+pkglibdir = /usr/share/grub/i386-pc
- nodist_pkglib_DATA = stage1
-
- CLEANFILES = $(nodist_pkglib_DATA)
-#diff -ru ../grub-0.97-save/stage1/Makefile.in ./stage1/Makefile.in
-#--- ../grub-0.97-save/stage1/Makefile.in 2006-09-16 21:30:10.000000000 +0200
-#+++ ./stage1/Makefile.in 2006-09-18 21:10:36.337653824 +0200
-#@@ -66,7 +66,7 @@
-# ETAGS = etags
-# CTAGS = ctags
-# DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-#-pkglibdir = /usr/lib/grub
-#+pkglibdir = /usr/share/grub/i386-pc
-# ACLOCAL = @ACLOCAL@
-# AMDEP_FALSE = @AMDEP_FALSE@
-# AMDEP_TRUE = @AMDEP_TRUE@
-diff -ru ../grub-0.97-save/stage2/Makefile.am ./stage2/Makefile.am
---- ../grub-0.97-save/stage2/Makefile.am 2006-09-16 21:29:52.000000000 +0200
-+++ ./stage2/Makefile.am 2006-09-18 21:11:46.148041032 +0200
-@@ -27,7 +27,7 @@
- -DUSE_MD5_PASSWORDS=1 -DSUPPORT_SERIAL=1 -DSUPPORT_HERCULES=1
-
- # Stage 2 and Stage 1.5's.
--pkglibdir = /usr/lib/grub
-+pkglibdir = /usr/share/grub/i386-pc
-
- EXTRA_PROGRAMS = nbloader.exec pxeloader.exec diskless.exec
-
-#diff -ru ../grub-0.97-save/stage2/Makefile.in ./stage2/Makefile.in
-#--- ../grub-0.97-save/stage2/Makefile.in 2006-09-16 21:30:12.000000000 +0200
-#+++ ./stage2/Makefile.in 2006-09-18 21:12:09.087553696 +0200
-#@@ -442,7 +442,7 @@
-# DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-#
-# # Stage 2 and Stage 1.5's.
-#-pkglibdir = /usr/lib/grub
-#+pkglibdir = /usr/share/grub/i386-pc
-# ACLOCAL = @ACLOCAL@
-# AMDEP_FALSE = @AMDEP_FALSE@
-# AMDEP_TRUE = @AMDEP_TRUE@
-diff -ru ../grub-0.97-save/stage2/asm.S ./stage2/asm.S
---- ../grub-0.97-save/stage2/asm.S 2006-09-16 21:29:52.000000000 +0200
-+++ ./stage2/asm.S 2006-09-18 21:31:53.404510152 +0200
-@@ -98,7 +98,7 @@
- .string VERSION
- VARIABLE(config_file)
- #ifndef STAGE1_5
-- .string "/boot/grub/menu.lst"
-+ .string "/boot/grub/grub.conf"
- #else /* STAGE1_5 */
- .long 0xffffffff
- .string "/boot/grub/stage2"
-diff -ru ../grub-0.97-save/stage2/builtins.c ./stage2/builtins.c
---- ../grub-0.97-save/stage2/builtins.c 2006-09-16 21:29:52.000000000 +0200
-+++ ./stage2/builtins.c 2006-09-18 21:32:39.562493072 +0200
-@@ -4022,7 +4022,7 @@
-
- /* The prefix was determined. */
- grub_sprintf (stage2, "%s%s", prefix, "/stage2");
-- grub_sprintf (config_filename, "%s%s", prefix, "/menu.lst");
-+ grub_sprintf (config_filename, "%s%s", prefix, "/grub.conf");
- *real_config_filename = 0;
-
- /* Check if stage2 exists. */
+++ /dev/null
-Fread doesn't return -1 on error, so use ferror().
-
---- util/mbchk.c.old Tue Jan 22 18:36:17 2002
-+++ util/mbchk.c Tue Jan 22 18:28:54 2002
-@@ -59,7 +59,9 @@ check_multiboot (const char *filename, F
- int i;
- char buf[8192];
-
-- if (fread (buf, 1, 8192, fp) < 0)
-+ fread (buf, 1, 8192, fp);
-+
-+ if (ferror(fp))
- {
- fprintf (stderr, "%s: Read error.\n", filename);
- return 0;
+++ /dev/null
-This file describes the patches in the patchsets:
-
-001_all_grub-0.97-misc.patch
- Several simple fixes
-
-002_all_grub-0.97-splash.patch
- Port of the SuSE's gfxboot patch
-
-003_all_grub-0.97-dirs.patch
- FHS compilance
-
-004_all_grub-0.97-wildcards.patch
- Port of the SuSE's wildcards patch with custom nice sorting addon
-
-005_all_grub-0.96-PIC.patch:
- a patch to fix PIC issues by psm and Kevin F. Quinn in Gentoo bug #80693
-
-010_all_grub-0.96-bounced-checks.patch:
- Disables testing of FFS and UFS2 images (which always fail). See Gentoo bug
- #71811
-
-020_all_grub-0.96-i2o-raid.patch:
- Support i2o RAID. See Gentoo bug #76143
-
-040_all_grub-0.96-nxstack.patch:
- Fix NX segfaulting on amd64 and x86_64. The patch is by Peter Jones.
- See: http://lists.gnu.org/archive/html/bug-grub/2005-03/msg00011.html
-
-060_all_grub-0.96-netboot-pic.patch
- Fix PIC issues in netboot code. See Gentoo bug #85566
+++ /dev/null
---- grub-0.96/stage2/char_io.c.orig 2005-02-18 09:12:39.163407496 +0100
-+++ grub-0.96/stage2/char_io.c 2005-02-18 09:13:11.431502000 +0100
-@@ -1202,37 +1202,62 @@
- }
- #endif /* ! STAGE1_5 */
-
-+#ifdef GRUB_UTIL
-+# ifdef __PIC__
-+# if defined(HAVE_START_SYMBOL) && defined(HAVE_END_SYMBOL)
-+ extern char start[];
-+ extern char end[];
-+# elif defined(HAVE_USCORE_START_SYMBOL) && defined (HAVE_USCORE_END_SYMBOL)
-+ extern char _start[];
-+ extern char _end[];
-+# endif
-+# endif
-+#endif
- int
- memcheck (int addr, int len)
- {
- #ifdef GRUB_UTIL
-+# ifdef __PIC__
-+# if defined(HAVE_START_SYMBOL) && defined(HAVE_END_SYMBOL)
-+ if (start <= addr && end > addr + len)
-+ return ! errnum;
-+# elif defined(HAVE_USCORE_START_SYMBOL) && defined (HAVE_USCORE_END_SYMBOL)
-+ if (_start <= addr && _end > addr + len)
-+ return ! errnum;
-+# endif
-+# else /* __PIC__ */
- auto int start_addr (void);
- auto int end_addr (void);
-
- auto int start_addr (void)
- {
- int ret;
--# if defined(HAVE_START_SYMBOL)
-+# if defined(HAVE_START_SYMBOL)
- asm volatile ("movl $start, %0" : "=a" (ret));
--# elif defined(HAVE_USCORE_START_SYMBOL)
-+# elif defined(HAVE_USCORE_START_SYMBOL)
- asm volatile ("movl $_start, %0" : "=a" (ret));
--# endif
-+# else
-+ erk! /* function would return undefined data in this case - barf */
-+# endif
- return ret;
- }
-
- auto int end_addr (void)
- {
- int ret;
--# if defined(HAVE_END_SYMBOL)
-+# if defined(HAVE_END_SYMBOL)
- asm volatile ("movl $end, %0" : "=a" (ret));
--# elif defined(HAVE_USCORE_END_SYMBOL)
-+# elif defined(HAVE_USCORE_END_SYMBOL)
- asm volatile ("movl $_end, %0" : "=a" (ret));
--# endif
-+# else
-+ erk! /* function would return undefined data in this case - barf */
-+# endif
- return ret;
- }
-
- if (start_addr () <= addr && end_addr () > addr + len)
- return ! errnum;
-+# endif /* __PIC__ */
- #endif /* GRUB_UTIL */
-
- if ((addr < RAW_ADDR (0x1000))
+++ /dev/null
-Remove tests that the grub maintainers say can be ignored.
-
-http://lists.gnu.org/archive/html/bug-grub/2004-05/msg00076.html
-
---- grub-0.96/stage2/size_test
-+++ grub-0.96/stage2/size_test
-@@ -36,9 +36,9 @@
- }
-
- # The bootloader area of a FFS partition is 14 sectors.
--check ffs_stage1_5 7168
--
--check ufs2_stage1_5 7168
-+#check ffs_stage1_5 7168
-+#
-+#check ufs2_stage1_5 7168
-
- # Stage 1.5 can be installed in the sectors immediately after MBR in the
- # first cylinder, so the size is (63 - 1) sectors.
+++ /dev/null
-diff -ru grub-0.96-orig/lib/device.c grub-0.96/lib/device.c
---- grub-0.96-orig/lib/device.c 2005-02-16 22:33:09.669384408 -0600
-+++ grub-0.96/lib/device.c 2005-02-17 00:47:05.127596672 -0600
-@@ -407,6 +407,12 @@
- {
- sprintf (name, "/dev/ataraid/d%c", unit + '0');
- }
-+
-+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,
-@@ -798,6 +804,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. */
-@@ -858,8 +884,15 @@
- 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 ||
-+ strncmp(dev, "/dev/i2o/", 9) == 0) ? "p" : "",
-+ ((partition >> 16) & 0xFF) + 1);
-+
- /* Open the partition. */
- fd = open (dev, O_RDWR);
- if (fd < 0)
+++ /dev/null
-Patch by the PaX Team to fix PIC/PIE problems.
-
-http://bugs.gentoo.org/show_bug.cgi?id=85566
-
---- netboot/main.c
-+++ netboot/main.c
-@@ -701,7 +701,7 @@
- "adcw %%ax,%0\n\t" /* add carry of previous iteration */
- "loop 1b\n\t"
- "adcw $0,%0" /* add carry of last iteration */
-- : "=b" (*sum), "=S"(start), "=c"(len)
-+ : "=r" (*sum), "=S"(start), "=c"(len)
- : "0"(*sum), "1"(start), "2"(len)
- : "ax", "cc"
- );
+++ /dev/null
---- 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 @@
- }
-
- \f
-+/* 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 @@
-
- \f
- /* 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)
+++ /dev/null
-diff -ru grub-0.97-old/docs/grub.8 grub-0.97/docs/grub.8
---- grub-0.97-old/docs/grub.8 2005-05-08 02:48:56.000000000 +0000
-+++ grub-0.97/docs/grub.8 2006-08-05 13:17:07.868362408 +0000
-@@ -15,7 +15,7 @@
- specify stage2 boot_drive [default=0x0]
- .TP
- \fB\-\-config\-file\fR=\fIFILE\fR
--specify stage2 config_file [default=/boot/grub/menu.lst]
-+specify stage2 config_file [default=/boot/grub/grub.conf]
- .TP
- \fB\-\-device\-map\fR=\fIFILE\fR
- use the device map file FILE
-diff -ru grub-0.97-old/docs/grub.texi grub-0.97/docs/grub.texi
---- grub-0.97-old/docs/grub.texi 2005-05-08 02:59:59.000000000 +0000
-+++ grub-0.97/docs/grub.texi 2006-08-05 13:17:07.875361344 +0000
-@@ -1265,7 +1265,7 @@
- keys) that will do everything to boot an OS.
-
- To enable the menu, you need a configuration file,
--@file{menu.lst} under the boot directory. We'll analyze an example
-+@file{grub.conf} under the boot directory. We'll analyze an example
- file.
-
- The file first contains some general settings, the menu interface
-@@ -1882,8 +1882,8 @@
-
- An absolute file name resembles a Unix absolute file name, using
- @samp{/} for the directory separator (not @samp{\} as in DOS). One
--example is @samp{(hd0,0)/boot/grub/menu.lst}. This means the file
--@file{/boot/grub/menu.lst} in the first partition of the first hard
-+example is @samp{(hd0,0)/boot/grub/grub.conf}. This means the file
-+@file{/boot/grub/grub.conf} in the first partition of the first hard
- disk. If you omit the device name in an absolute file name, GRUB uses
- GRUB's @dfn{root device} implicitly. So if you set the root device to,
- say, @samp{(hd1,0)} by the command @command{root} (@pxref{root}), then
-@@ -3542,7 +3542,7 @@
-
- @item --config-file=@var{file}
- Read the configuration file @var{file} instead of
--@file{/boot/grub/menu.lst}. The format is the same as the normal GRUB
-+@file{/boot/grub/grub.conf}. The format is the same as the normal GRUB
- syntax. See @ref{Filesystem}, for more information.
-
- @item --boot-drive=@var{drive}
-diff -ru grub-0.97-old/grub/asmstub.c grub-0.97/grub/asmstub.c
---- grub-0.97-old/grub/asmstub.c 2005-02-16 20:45:14.000000000 +0000
-+++ grub-0.97/grub/asmstub.c 2006-08-05 13:17:07.866362712 +0000
-@@ -71,7 +71,7 @@
- unsigned long boot_drive = 0;
- int saved_entryno = 0;
- char version_string[] = VERSION;
--char config_file[128] = "/boot/grub/menu.lst"; /* FIXME: arbitrary */
-+char config_file[128] = "/boot/grub/grub.conf"; /* FIXME: arbitrary */
- unsigned long linux_text_len = 0;
- char *linux_data_tmp_addr = 0;
- char *linux_data_real_addr = 0;
-diff -ru grub-0.97-old/stage2/asm.S grub-0.97/stage2/asm.S
---- grub-0.97-old/stage2/asm.S 2004-06-19 16:55:22.000000000 +0000
-+++ grub-0.97/stage2/asm.S 2006-08-05 13:17:07.859363776 +0000
-@@ -98,7 +98,7 @@
- .string VERSION
- VARIABLE(config_file)
- #ifndef STAGE1_5
-- .string "/boot/grub/menu.lst"
-+ .string "/boot/grub/grub.conf"
- #else /* STAGE1_5 */
- .long 0xffffffff
- .string "/boot/grub/stage2"
-diff -ru grub-0.97-old/stage2/builtins.c grub-0.97/stage2/builtins.c
---- grub-0.97-old/stage2/builtins.c 2005-02-15 21:58:23.000000000 +0000
-+++ grub-0.97/stage2/builtins.c 2006-08-05 13:17:07.864363016 +0000
-@@ -3973,7 +3973,7 @@
-
- /* The prefix was determined. */
- grub_sprintf (stage2, "%s%s", prefix, "/stage2");
-- grub_sprintf (config_filename, "%s%s", prefix, "/menu.lst");
-+ grub_sprintf (config_filename, "%s%s", prefix, "/grub.conf");
- *real_config_filename = 0;
-
- /* Check if stage2 exists. */
+++ /dev/null
-diff -Nur grub-0.97-splash/docs/grub.texi grub-0.97-dirs/docs/grub.texi
---- grub-0.97-splash/docs/grub.texi 2005-08-21 20:29:22.000000000 +0300
-+++ grub-0.97-dirs/docs/grub.texi 2005-08-21 20:31:12.000000000 +0300
-@@ -479,13 +479,13 @@
- if, by any chance, your hard drive becomes unusable (unbootable).
-
- GRUB comes with boot images, which are normally put in the directory
--@file{/usr/lib/grub/i386-pc}. If you do not use grub-install, then
-+@file{/usr/share/grub/i386-pc}. If you do not use grub-install, then
- you need to copy the files @file{stage1}, @file{stage2}, and
- @file{*stage1_5} to the directory @file{/boot/grub}, and run the
- @command{grub-set-default} (@pxref{Invoking grub-set-default}) if you
- intend to use @samp{default saved} (@pxref{default}) in your
- configuration file. Hereafter, the directory where GRUB images are
--initially placed (normally @file{/usr/lib/grub/i386-pc}) will be
-+initially placed (normally @file{/usr/share/grub/i386-pc}) will be
- called the @dfn{image directory}, and the directory where the boot
- loader needs to find them (usually @file{/boot/grub}) will be called
- the @dfn{boot directory}.
-@@ -513,7 +513,7 @@
-
- @example
- @group
--# @kbd{cd /usr/lib/grub/i386-pc}
-+# @kbd{cd /usr/share/grub/i386-pc}
- # @kbd{dd if=stage1 of=/dev/fd0 bs=512 count=1}
- 1+0 records in
- 1+0 records out
-@@ -707,7 +707,7 @@
- Copy the file @file{stage2_eltorito}:
-
- @example
--$ @kbd{cp /usr/lib/grub/i386-pc/stage2_eltorito iso/boot/grub}
-+$ @kbd{cp /usr/share/grub/i386-pc/stage2_eltorito iso/boot/grub}
- @end example
-
- If desired, make the config file @file{menu.lst} under @file{iso/boot/grub}
-diff -Nur grub-0.97-splash/Makefile.am grub-0.97-dirs/Makefile.am
---- grub-0.97-splash/Makefile.am 2005-08-21 20:29:14.000000000 +0300
-+++ grub-0.97-dirs/Makefile.am 2005-08-21 20:31:12.000000000 +0300
-@@ -2,3 +2,4 @@
- AUTOMAKE_OPTIONS = 1.7 gnu
- SUBDIRS = netboot stage2 stage1 lib grub util docs
- EXTRA_DIST = BUGS MAINTENANCE
-+pkgdatadir=$(datadir)
-diff -Nur grub-0.97-splash/stage1/Makefile.am grub-0.97-dirs/stage1/Makefile.am
---- grub-0.97-splash/stage1/Makefile.am 2005-08-21 20:29:14.000000000 +0300
-+++ grub-0.97-dirs/stage1/Makefile.am 2005-08-21 20:31:12.000000000 +0300
-@@ -1,4 +1,4 @@
--pkglibdir = $(libdir)/$(PACKAGE)/$(host_cpu)-$(host_vendor)
-+pkglibdir = /usr/share/grub/i386-pc
- nodist_pkglib_DATA = stage1
-
- CLEANFILES = $(nodist_pkglib_DATA)
-diff -Nur grub-0.97-splash/stage2/Makefile.am grub-0.97-dirs/stage2/Makefile.am
---- grub-0.97-splash/stage2/Makefile.am 2005-08-21 20:29:14.000000000 +0300
-+++ grub-0.97-dirs/stage2/Makefile.am 2005-08-21 20:31:12.000000000 +0300
-@@ -27,7 +27,7 @@
- -DUSE_MD5_PASSWORDS=1 -DSUPPORT_SERIAL=1 -DSUPPORT_HERCULES=1
-
- # Stage 2 and Stage 1.5's.
--pkglibdir = $(libdir)/$(PACKAGE)/$(host_cpu)-$(host_vendor)
-+pkglibdir = /usr/share/grub/i386-pc
-
- EXTRA_PROGRAMS = nbloader.exec pxeloader.exec diskless.exec
-
-diff -Nur grub-0.97-splash/util/grub-install.in grub-0.97-dirs/util/grub-install.in
---- grub-0.97-splash/util/grub-install.in 2005-08-21 20:29:14.000000000 +0300
-+++ grub-0.97-dirs/util/grub-install.in 2005-08-21 20:31:12.000000000 +0300
-@@ -27,7 +27,7 @@
- host_cpu=@host_cpu@
- host_os=@host_os@
- host_vendor=@host_vendor@
--pkglibdir=${libdir}/${PACKAGE}/${host_cpu}-${host_vendor}
-+pkglibdir=/usr/share/grub/i386-pc
-
- grub_shell=${sbindir}/grub
- grub_set_default=${sbindir}/grub-set-default
+++ /dev/null
-diff -Nur grub-0.97-ori/lib/device.c grub-0.97-misc/lib/device.c
---- grub-0.97-ori/lib/device.c 2005-03-28 02:14:25.000000000 +0300
-+++ grub-0.97-misc/lib/device.c 2005-08-21 20:22:30.000000000 +0300
-@@ -831,9 +831,11 @@
- is_disk_device (char **map, int drive)
- {
- struct stat st;
-+ int retval;
-
- assert (map[drive] != 0);
-- assert (stat (map[drive], &st) == 0);
-+ retval = stat (map[drive], &st);
-+ assert (retval == 0);
- /* For now, disk devices under Linux are all block devices. */
- return S_ISBLK (st.st_mode);
- }
-diff -Nur grub-0.97-ori/stage2/boot.c grub-0.97-misc/stage2/boot.c
---- grub-0.97-ori/stage2/boot.c 2004-03-30 14:44:08.000000000 +0300
-+++ grub-0.97-misc/stage2/boot.c 2005-08-21 20:22:30.000000000 +0300
-@@ -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 -Nur grub-0.97-ori/stage2/builtins.c grub-0.97-misc/stage2/builtins.c
---- grub-0.97-ori/stage2/builtins.c 2005-02-15 23:58:23.000000000 +0200
-+++ grub-0.97-misc/stage2/builtins.c 2005-08-21 20:22:30.000000000 +0300
-@@ -1842,9 +1842,23 @@
- #ifdef GRUB_UTIL
- else if (grub_memcmp ("--stage2=", arg, sizeof ("--stage2=") - 1) == 0)
- {
-+ int fd;
- stage2_os_file = arg + sizeof ("--stage2=") - 1;
- arg = skip_to (0, arg);
- nul_terminate (stage2_os_file);
-+
-+#if defined(__linux__) && defined (FSYS_REISERFS)
-+ if ((fd=open(stage2_os_file, O_RDONLY)) >= 0)
-+ {
-+ struct statfs buf;
-+ /* see if the file sits on a reiserfs,
-+ and try do defragment it if so. */
-+ fstatfs(fd, &buf);
-+ if (buf.f_type == REISERFS_SUPER_MAGIC)
-+ ioctl (fd, REISERFS_IOC_UNPACK, 1);
-+ }
-+#endif /* __linux__ && FSYS_REISERFS */
-+
- }
- #endif /* GRUB_UTIL */
- else
-diff -Nur grub-0.97-ori/stage2/filesys.h grub-0.97-misc/stage2/filesys.h
---- grub-0.97-ori/stage2/filesys.h 2004-05-14 22:36:43.000000000 +0300
-+++ grub-0.97-misc/stage2/filesys.h 2005-08-21 20:22:30.000000000 +0300
-@@ -73,6 +73,16 @@
- int reiserfs_read (char *buf, int len);
- int reiserfs_dir (char *dirname);
- int reiserfs_embed (int *start_sector, int needed_sectors);
-+#if defined(__linux__) && defined (GRUB_UTIL)
-+#include <sys/types.h>
-+#include <sys/stat.h>
-+#include <sys/ioctl.h>
-+#include <sys/statfs.h>
-+#include <fcntl.h>
-+/* from <linux/reiserfs_fs.h> */
-+#define REISERFS_SUPER_MAGIC 0x52654973
-+#define REISERFS_IOC_UNPACK _IOW(0xCD,1,long)
-+#endif
- #else
- #define FSYS_REISERFS_NUM 0
- #endif
-diff -Nur grub-0.97-ori/util/mbchk.c grub-0.97-misc/util/mbchk.c
---- grub-0.97-ori/util/mbchk.c 2003-10-19 18:36:45.000000000 +0300
-+++ grub-0.97-misc/util/mbchk.c 2005-08-21 20:22:30.000000000 +0300
-@@ -59,7 +59,9 @@
- int i;
- char buf[8192];
-
-- if (fread (buf, 1, 8192, fp) < 0)
-+ fread (buf, 1, 8192, fp);
-+
-+ if (ferror(fp))
- {
- fprintf (stderr, "%s: Read error.\n", filename);
- return 0;
+++ /dev/null
-diff -Nur grub-0.97-misc/docs/grub.texi grub-0.97-splash/docs/grub.texi
---- grub-0.97-misc/docs/grub.texi 2005-08-21 20:22:18.000000000 +0300
-+++ grub-0.97-splash/docs/grub.texi 2005-08-21 20:29:22.000000000 +0300
-@@ -2118,6 +2118,7 @@
- * default:: Set the default entry
- * fallback:: Set the fallback entry
- * hiddenmenu:: Hide the menu interface
-+* gfxmenu:: Use graphical menu interface
- * timeout:: Set the timeout
- * title:: Start a menu entry
- @end menu
-@@ -2150,6 +2151,15 @@
- @end deffn
-
-
-+@node gfxmenu
-+@subsection gfxmenu
-+
-+@deffn Command gfxmenu file
-+Use the graphical menu interface. The graphics data are taken from
-+@var{file} and must be created using 'mkbootmsg' from the gfxboot package.
-+@end deffn
-+
-+
- @node hiddenmenu
- @subsection hiddenmenu
-
-diff -Nur grub-0.97-misc/grub/asmstub.c grub-0.97-splash/grub/asmstub.c
---- grub-0.97-misc/grub/asmstub.c 2005-08-21 20:22:18.000000000 +0300
-+++ grub-0.97-splash/grub/asmstub.c 2005-08-21 20:29:22.000000000 +0300
-@@ -480,6 +480,32 @@
- return 0;
- }
-
-+/* graphical menu functions . */
-+int
-+gfx_init (gfx_data_t *gfx_data)
-+{
-+ return 0;
-+}
-+
-+int
-+gfx_done (gfx_data_t *gfx_data)
-+{
-+ return 0;
-+}
-+
-+int
-+gfx_input (gfx_data_t *gfx_data, int *menu_entry)
-+{
-+ return 0;
-+}
-+
-+int
-+gfx_setup_menu (gfx_data_t *gfx_data)
-+{
-+ return 0;
-+}
-+
-+
- /* low-level timing info */
- int
- getrtsecs (void)
-diff -Nur grub-0.97-misc/stage2/asm.S grub-0.97-splash/stage2/asm.S
---- grub-0.97-misc/stage2/asm.S 2005-08-21 20:22:18.000000000 +0300
-+++ grub-0.97-splash/stage2/asm.S 2005-08-21 20:29:22.000000000 +0300
-@@ -1610,6 +1610,301 @@
- popl %ebp
- ret
-
-+
-+/*
-+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-+ *
-+ * graphical menu functions
-+ *
-+ */
-+
-+/*
-+ * int gfx_init (gfx_data_t *gfx_data)
-+ *
-+ * init gfx things
-+ *
-+ * return vales:
-+ * 0: ok
-+ * 1: failed
-+ * sets gfx_data->ok
-+ */
-+
-+ENTRY(gfx_init)
-+ pushl %ebp
-+ movl %esp, %ebp
-+
-+ pushl %edi
-+ pushl %esi
-+ pushl %ebx
-+
-+ movl 8(%ebp),%edx
-+ movl %edx,%edi
-+ andl $0xf,%edi
-+ shrl $4,%edx
-+
-+ pushl %ebp
-+
-+ call EXT_C(prot_to_real)
-+ .code16
-+
-+ pushw %ds
-+
-+ movw %dx,%ds
-+ leal gfx_ofs_sys_cfg(%di),%esi
-+ movl gfx_ofs_mem_file(%di),%eax
-+ movl gfx_ofs_mem_cur(%di),%ebx
-+ movl gfx_ofs_mem_max(%di),%ecx
-+ movw %ds,%dx
-+
-+ /* basically just a lcall, but we need %edi */
-+ pushw %cs
-+ pushw $gfx_init_50
-+ pushl gfx_ofs_jmp_table + 4 * 0 (%di)
-+
-+ movl gfx_ofs_mem_align(%di),%edi
-+
-+ lret
-+
-+gfx_init_50:
-+ movl $0,%ebx
-+ adcl $0,%ebx
-+
-+ popw %ds
-+
-+ DATA32 call EXT_C(real_to_prot)
-+ .code32
-+
-+ popl %ebp
-+
-+ movl %ebx,%eax
-+ negl %ebx
-+ incl %ebx
-+ movl 8(%ebp),%edx
-+ movl %ebx,gfx_ofs_ok(%edx)
-+
-+ popl %ebx
-+ popl %esi
-+ popl %edi
-+
-+ popl %ebp
-+ ret
-+
-+
-+/*
-+ * int gfx_done (gfx_data_t *gfx_data)
-+ *
-+ * shut down gfx things
-+ *
-+ * return vales:
-+ * always 0
-+ * sets gfx_data->ok
-+ */
-+
-+ENTRY(gfx_done)
-+ pushl %ebp
-+ movl %esp, %ebp
-+
-+ pushl %edi
-+ pushl %esi
-+ pushl %ebx
-+
-+ movl 8(%ebp),%edx
-+ movl %edx,%ebx
-+ andl $0xf,%ebx
-+ shrl $4,%edx
-+
-+ pushl %ebp
-+
-+ call EXT_C(prot_to_real)
-+ .code16
-+
-+ pushw %ds
-+
-+ movw %dx,%ds
-+
-+ lcall *gfx_ofs_jmp_table + 4 * 1 (%bx)
-+
-+ popw %ds
-+
-+ DATA32 call EXT_C(real_to_prot)
-+ .code32
-+
-+ popl %ebp
-+
-+ xorl %eax,%eax
-+ movl 8(%ebp),%edx
-+ movl %eax,gfx_ofs_ok(%edx)
-+
-+ popl %ebx
-+ popl %esi
-+ popl %edi
-+
-+ popl %ebp
-+ ret
-+
-+
-+/*
-+ * int gfx_input (gfx_data_t *gfx_data, int *menu_entry)
-+ *
-+ * let user enter a command line
-+ *
-+ * uses gfx_data->cmdline as buffer
-+ *
-+ * return values:
-+ * 1: abort
-+ * 2: boot
-+ * menu_entry: selected entry
-+ */
-+
-+ENTRY(gfx_input)
-+ pushl %ebp
-+ movl %esp, %ebp
-+
-+ pushl %edi
-+ pushl %esi
-+ pushl %ebx
-+
-+ movl 8(%ebp),%edx
-+ movl %edx,%ebx
-+ andl $0xf,%ebx
-+ shrl $4,%edx
-+
-+ pushl %ebp
-+
-+ call EXT_C(prot_to_real)
-+ .code16
-+
-+ pushw %ds
-+
-+ movw %dx,%ds
-+ shll $4,%edx
-+ movl gfx_ofs_cmdline(%bx),%edi
-+ subl %edx,%edi
-+ movw gfx_ofs_cmdline_len(%bx),%cx
-+ movw gfx_ofs_timeout(%bx),%ax
-+ imulw $18,%ax
-+
-+ pushl %ebp
-+ lcall *gfx_ofs_jmp_table + 4 * 2 (%bx)
-+ popl %ebp
-+ movl %eax,%ecx
-+
-+ popw %ds
-+
-+ DATA32 call EXT_C(real_to_prot)
-+ .code32
-+
-+ popl %ebp
-+
-+ movl 12(%ebp),%edx
-+ movl %ebx,(%edx)
-+
-+ movl %ecx,%eax
-+
-+ popl %ebx
-+ popl %esi
-+ popl %edi
-+
-+ popl %ebp
-+ ret
-+
-+
-+/*
-+ * int gfx_setup_menu (gfx_data_t *gfx_data)
-+ *
-+ * draw boot menu
-+ *
-+ * return values:
-+ * always 0
-+ */
-+
-+/* menu entry descriptor */
-+#define menu_entries 0
-+#define menu_default 2 /* seg:ofs */
-+#define menu_ent_list 6 /* seg:ofs */
-+#define menu_ent_size 10
-+#define menu_arg_list 12 /* seg:ofs */
-+#define menu_arg_size 16
-+#define sizeof_menu_desc 18
-+
-+ENTRY(gfx_setup_menu)
-+ pushl %ebp
-+ movl %esp, %ebp
-+
-+ pushl %edi
-+ pushl %esi
-+ pushl %ebx
-+
-+ movl 8(%ebp),%edx
-+ movl %edx,%ebx
-+ andl $0xf,%ebx
-+ shrl $4,%edx
-+
-+ call EXT_C(prot_to_real)
-+ .code16
-+
-+ pushw %ds
-+
-+ movw %dx,%ds
-+ shll $4,%edx
-+
-+ subw $sizeof_menu_desc,%sp
-+ movw %sp,%bp
-+
-+ movl gfx_ofs_menu_entries(%bx),%eax
-+ movw %ax,menu_entries(%bp)
-+
-+ movl gfx_ofs_menu_default_entry(%bx),%eax
-+ subl %edx,%eax
-+ movw %ax,menu_default(%bp)
-+ movw %ds,menu_default+2(%bp)
-+
-+ movl gfx_ofs_menu_list(%bx),%eax
-+ subl %edx,%eax
-+ movw %ax,menu_ent_list(%bp)
-+ movw %ds,menu_ent_list+2(%bp)
-+
-+ movl gfx_ofs_menu_entry_len(%bx),%eax
-+ movw %ax,menu_ent_size(%bp)
-+
-+ movl gfx_ofs_args_list(%bx),%eax
-+ subl %edx,%eax
-+ movw %ax,menu_arg_list(%bp)
-+ movw %ds,menu_arg_list+2(%bp)
-+
-+ movl gfx_ofs_args_entry_len(%bx),%eax
-+ movw %ax,menu_arg_size(%bp)
-+
-+ movw %bp,%si
-+ pushw %ss
-+ popw %es
-+
-+ lcall %ds: *gfx_ofs_jmp_table + 4 * 3 (%bx)
-+
-+ addw $sizeof_menu_desc,%sp
-+
-+ popw %ds
-+
-+ DATA32 call EXT_C(real_to_prot)
-+ .code32
-+
-+ xorl %eax,%eax
-+
-+ popl %ebx
-+ popl %esi
-+ popl %edi
-+
-+ popl %ebp
-+ ret
-+
-+
-+/*
-+ *
-+ * end graphics stuff
-+ *
-+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-+ */
-+
-
- /*
- * gateA20(int linear)
-diff -Nur grub-0.97-misc/stage2/builtins.c grub-0.97-splash/stage2/builtins.c
---- grub-0.97-misc/stage2/builtins.c 2005-08-21 20:22:30.000000000 +0300
-+++ grub-0.97-splash/stage2/builtins.c 2005-08-21 20:29:22.000000000 +0300
-@@ -63,6 +63,8 @@
- int fallback_entries[MAX_FALLBACK_ENTRIES];
- /* The number of current entry. */
- int current_entryno;
-+/* graphics file */
-+char graphics_file[64];
- /* The address for Multiboot command-line buffer. */
- static char *mb_cmdline;
- /* The password. */
-@@ -1331,6 +1333,26 @@
- };
-
- \f
-+/* graphics */
-+static int
-+gfxmenu_func (char *arg, int flags)
-+{
-+ memmove(graphics_file, arg, sizeof graphics_file - 1);
-+ graphics_file[sizeof graphics_file - 1] = 0;
-+
-+ return 0;
-+}
-+
-+static struct builtin builtin_gfxmenu =
-+{
-+ "gfxmenu",
-+ gfxmenu_func,
-+ BUILTIN_MENU | BUILTIN_HELP_LIST,
-+ "gfxmenu FILE",
-+ "Use the graphical menu from FILE."
-+};
-+
-+\f
- /* geometry */
- static int
- geometry_func (char *arg, int flags)
-@@ -4837,6 +4859,7 @@
- &builtin_find,
- &builtin_fstest,
- &builtin_geometry,
-+ &builtin_gfxmenu,
- &builtin_halt,
- &builtin_help,
- &builtin_hiddenmenu,
-diff -Nur grub-0.97-misc/stage2/shared.h grub-0.97-splash/stage2/shared.h
---- grub-0.97-misc/stage2/shared.h 2005-08-21 20:22:18.000000000 +0300
-+++ grub-0.97-splash/stage2/shared.h 2005-08-21 20:29:22.000000000 +0300
-@@ -374,6 +374,27 @@
- #endif /* WITHOUT_LIBC_STUBS */
-
-
-+/* see typedef gfx_data_t below */
-+#define gfx_ofs_ok 0x00
-+#define gfx_ofs_mem_start 0x04
-+#define gfx_ofs_mem_cur 0x08
-+#define gfx_ofs_mem_max 0x0c
-+#define gfx_ofs_code_seg 0x10
-+#define gfx_ofs_jmp_table 0x14
-+#define gfx_ofs_sys_cfg 0x44
-+#define gfx_ofs_cmdline 0x64
-+#define gfx_ofs_cmdline_len 0x68
-+#define gfx_ofs_menu_list 0x6c
-+#define gfx_ofs_menu_default_entry 0x70
-+#define gfx_ofs_menu_entries 0x74
-+#define gfx_ofs_menu_entry_len 0x78
-+#define gfx_ofs_args_list 0x7c
-+#define gfx_ofs_args_entry_len 0x80
-+#define gfx_ofs_timeout 0x84
-+#define gfx_ofs_mem_file 0x88
-+#define gfx_ofs_mem_align 0x8c
-+
-+
- #ifndef ASM_FILE
- /*
- * Below this should be ONLY defines and other constructs for C code.
-@@ -595,6 +616,41 @@
- extern int default_entry;
- extern int current_entryno;
-
-+
-+/*
-+ * graphics menu stuff
-+ *
-+ * Note: gfx_data and all data referred to in it must lie within a 64k area.
-+ */
-+typedef struct {
-+ unsigned ok; /* set while we're in graphics mode */
-+ unsigned mem_start, mem_cur, mem_max;
-+ unsigned code_seg; /* code segment of binary graphics code */
-+ unsigned jmp_table[12]; /* link to graphics functions */
-+ unsigned char sys_cfg[32]; /* sys_cfg[0]: identifies boot loader (grub == 2) */
-+ char *cmdline; /* command line returned by gfx_input() */
-+ unsigned cmdline_len; /* length of the above */
-+ char *menu_list; /* list of menu entries, each of fixed length (menu_entry_len) */
-+ char *menu_default_entry; /* the default entry */
-+ unsigned menu_entries; /* number of entries in menu_list */
-+ unsigned menu_entry_len; /* one entry */
-+ char *args_list; /* same structure as menu_list, menu_entries entries */
-+ unsigned args_entry_len; /* one entry */
-+ unsigned timeout; /* in seconds (0: no timeout) */
-+ unsigned mem_file; /* aligned gfx file start */
-+ unsigned mem_align; /* aligned cpio file start */
-+} __attribute__ ((packed)) gfx_data_t;
-+
-+extern gfx_data_t *graphics_data;
-+
-+/* pointer to graphics image data */
-+extern char graphics_file[64];
-+
-+int gfx_init(gfx_data_t *gfx_data);
-+int gfx_done(gfx_data_t *gfx_data);
-+int gfx_input(gfx_data_t *gfx_data, int *menu_entry);
-+int gfx_setup_menu(gfx_data_t *gfx_data);
-+
- /* The constants for password types. */
- typedef enum
- {
-diff -Nur grub-0.97-misc/stage2/stage2.c grub-0.97-splash/stage2/stage2.c
---- grub-0.97-misc/stage2/stage2.c 2005-08-21 20:22:18.000000000 +0300
-+++ grub-0.97-splash/stage2/stage2.c 2005-08-21 20:29:22.000000000 +0300
-@@ -22,6 +22,8 @@
-
- grub_jmp_buf restart_env;
-
-+gfx_data_t *graphics_data;
-+
- #if defined(PRESET_MENU_STRING) || defined(SUPPORT_DISKLESS)
-
- # if defined(PRESET_MENU_STRING)
-@@ -310,6 +312,12 @@
-
- if (! auth && password)
- {
-+ if (*graphics_file)
-+ {
-+ printf ("\
-+ WARNING: graphical menu doesn\'t work\
-+ in conjunction with the password feature\n" );
-+ }
- printf ("\
- Press enter to boot the selected OS or \'p\' to enter a\n\
- password to unlock the next set of features.");
-@@ -753,6 +761,413 @@
- }
-
-
-+
-+#if 0
-+/* for debugging */
-+static void hexdump(unsigned char *buf, unsigned len)
-+{
-+ int i, j = 0;
-+ char s[17];
-+ unsigned addr = (unsigned) buf;
-+
-+ s[16] = 0;
-+ while(len--) {
-+ i = buf[j];
-+ i = i & 0xff;
-+ s[j & 15] = (i >= 0x20 && i <= 0x7e) ? i : '.';
-+ if(!(j & 15)) {
-+ printf("%x ", j + addr);
-+ }
-+ if(!(j & 7) && (j & 15)) printf(" ");
-+ /* stupid grub_printf */
-+ printf("%x", (i >> 4) & 0x0f);
-+ printf("%x ", i & 0x0f);
-+ if(!(++j & 15)) {
-+ printf(" %s\n", s);
-+ }
-+ }
-+
-+ if(j & 15) {
-+ s[j & 15] = 0;
-+ if(!(j & 8)) printf(" ");
-+ i = 1 + 3 * (16 - (j & 15));
-+ while(i--) printf(" ");
-+ printf("%s\n", s);
-+ }
-+}
-+#endif
-+
-+/*
-+ * Go through config entry and find kernel args, if any.
-+ */
-+static char *get_kernel_args(char *cfg)
-+{
-+ int j;
-+ char *s, *t = "";
-+
-+ for(j = 0; ; j++) {
-+ s = get_entry(cfg, j, 0);
-+ if(!*s) break;
-+ if(!memcmp(s, "kernel", 6) && (s[6] == ' ' || s[6] == '\t')) {
-+ t = skip_to(0, s);
-+ if(*t) t = skip_to(0, t);
-+ break;
-+ }
-+ }
-+
-+ return t;
-+}
-+
-+
-+/*
-+ * Check header and return code start offset.
-+ */
-+static unsigned magic_ok(unsigned char *buf)
-+{
-+ if(
-+ *(unsigned *) buf == 0x0b2d97f00 && /* magic id */
-+ (buf[4] == 5 || buf[4] == 6) /* version 5 or 6 */
-+ ) {
-+ return *(unsigned *) (buf + 8);
-+ }
-+
-+ return 0;
-+}
-+
-+
-+/*
-+ * Search cpio archive for gfx file.
-+ */
-+static unsigned find_file(unsigned char *buf, unsigned len, unsigned *gfx_file_start)
-+{
-+ unsigned i, fname_len, flen, code_start = 0;
-+
-+ *gfx_file_start = 0;
-+
-+ for(i = 0; i < len;) {
-+ if((len - i) >= 0x1a && (buf[i] + (buf[i + 1] << 8)) == 0x71c7) {
-+ fname_len = *(unsigned short *) (buf + i + 20);
-+ flen = *(unsigned short *) (buf + i + 24) + (*(unsigned short *) (buf + i + 22) << 16);
-+ i += 26 + fname_len;
-+ i = ((i + 1) & ~1);
-+ if((code_start = magic_ok(buf + i))) {
-+ *gfx_file_start = i;
-+ return code_start;
-+ }
-+ i += flen;
-+ i = ((i + 1) & ~1);
-+ }
-+ else {
-+ break;
-+ }
-+ }
-+
-+ return code_start;
-+}
-+
-+
-+/*
-+ * Leave that much space on the heap. Everything else goes to the graphics
-+ * functions.
-+ *
-+ * 0x2000 is _not_ enough
-+ */
-+#define MIN_HEAP_SIZE 0x4000
-+
-+/* gfx code needs at least this much free memory */
-+#define MIN_GFX_FREE 0xc000
-+
-+/*
-+ * Does normally not return.
-+ */
-+static void
-+run_graphics_menu (char *menu_entries, char *config_entries, int num_entries,
-+ char *heap, int entryno)
-+{
-+ unsigned char *buf;
-+ unsigned u, buf_size, code_start, file_start;
-+ char *s, *t, *cfg, *new_config;
-+ char *saved_heap;
-+ int i, j, max_len;
-+ int selected_entry;
-+ gfx_data_t *gfx_data;
-+
-+ /*
-+ * check gfx_data_t struct offsets for consistency; gcc will optimize away
-+ * the whole block
-+ */
-+
-+ /* dummy function to make ld fail */
-+ {
-+ extern void wrong_struct_size(void);
-+ #define gfx_ofs_check(a) if(gfx_ofs_##a != (char *) &gfx_data->a - (char *) gfx_data) wrong_struct_size();
-+ gfx_ofs_check(ok);
-+ gfx_ofs_check(mem_start);
-+ gfx_ofs_check(mem_cur);
-+ gfx_ofs_check(mem_max);
-+ gfx_ofs_check(code_seg);
-+ gfx_ofs_check(jmp_table);
-+ gfx_ofs_check(sys_cfg);
-+ gfx_ofs_check(cmdline);
-+ gfx_ofs_check(cmdline_len);
-+ gfx_ofs_check(menu_list);
-+ gfx_ofs_check(menu_default_entry);
-+ gfx_ofs_check(menu_entries);
-+ gfx_ofs_check(menu_entry_len);
-+ gfx_ofs_check(args_list);
-+ gfx_ofs_check(args_entry_len);
-+ gfx_ofs_check(timeout);
-+ gfx_ofs_check(mem_file);
-+ gfx_ofs_check(mem_align);
-+ #undef gfx_ofs_check
-+ }
-+
-+ if(!num_entries) return;
-+
-+ graphics_data = gfx_data = (gfx_data_t *) heap;
-+ heap += sizeof *gfx_data;
-+ memset(gfx_data, 0, sizeof *gfx_data);
-+
-+ gfx_data->sys_cfg[0] = 2; /* bootloader: grub */
-+ gfx_data->timeout = grub_timeout >= 0 ? grub_timeout : 0;
-+
-+
-+ /* setup command line edit buffer */
-+
-+ gfx_data->cmdline_len = 256;
-+
-+ gfx_data->cmdline = heap;
-+ heap += gfx_data->cmdline_len;
-+ memset(gfx_data->cmdline, 0, gfx_data->cmdline_len);
-+
-+
-+ /* setup menu entries */
-+
-+ for(i = max_len = 0; i < num_entries; i++) {
-+ j = strlen(get_entry(menu_entries, i, 0));
-+ if(j > max_len) max_len = j;
-+ }
-+
-+ if(!max_len) return;
-+
-+ gfx_data->menu_entry_len = max_len + 1;
-+ gfx_data->menu_entries = num_entries;
-+
-+ gfx_data->menu_list = heap;
-+ heap += gfx_data->menu_entry_len * gfx_data->menu_entries;
-+
-+ memset(gfx_data->menu_list, 0, gfx_data->menu_entry_len * gfx_data->menu_entries);
-+
-+ for(i = 0; i < (int) gfx_data->menu_entries; i++) {
-+ strcpy(gfx_data->menu_list + i * gfx_data->menu_entry_len, get_entry(menu_entries, i, 0));
-+ }
-+
-+ gfx_data->menu_default_entry = gfx_data->menu_list + entryno * gfx_data->menu_entry_len;
-+
-+
-+ /* setup list of kernel args */
-+
-+ for(i = max_len = 0; i < num_entries; i++) {
-+ s = get_kernel_args(get_entry(config_entries, i, 1));
-+ j = strlen(s);
-+ if(j > max_len) max_len = j;
-+ }
-+
-+ gfx_data->args_entry_len = max_len + 1;
-+
-+ gfx_data->args_list = heap;
-+ heap += gfx_data->args_entry_len * gfx_data->menu_entries;
-+
-+ memset(gfx_data->args_list, 0, gfx_data->args_entry_len * gfx_data->menu_entries);
-+
-+ for(i = 0; i < (int) gfx_data->menu_entries; i++) {
-+ strcpy(gfx_data->args_list + i* gfx_data->args_entry_len, get_kernel_args(get_entry(config_entries, i, 1)));
-+ }
-+
-+
-+ /* go back here when we no longer need the graphics data */
-+ saved_heap = heap;
-+
-+
-+ /* get memory area to be used by graphics functions */
-+
-+ buf = (unsigned char *) (((unsigned) heap + 0xf) & ~0xf);
-+
-+ buf_size = (unsigned char *) &buf - buf - MIN_HEAP_SIZE;
-+ buf_size &= ~0xf;
-+
-+ /* too small */
-+ if(buf_size < 0x10000) return;
-+
-+ gfx_data->mem_start = (unsigned) buf;
-+ gfx_data->mem_max = gfx_data->mem_start + buf_size;
-+
-+#if 0
-+ printf("graphics menu\n");
-+ printf(
-+ "heap = 0x%x, buf = 0x%x (0x%x bytes), graphics_file = %s\n",
-+ heap, gfx_data->mem_start, buf_size, graphics_file
-+ );
-+ getkey();
-+#endif
-+
-+ heap += buf_size;
-+
-+
-+ /* read the file */
-+
-+ if(!grub_open(graphics_file)) {
-+ printf("graphics file \"%s\" missing, press a key to continue...\n", graphics_file);
-+ getkey();
-+ return;
-+ }
-+
-+ i = grub_read(buf, buf_size);
-+
-+ grub_close();
-+
-+ if(i <= 0) {
-+ printf("error reading \"%s\", press a key to continue...\n", graphics_file);
-+ getkey();
-+ return;
-+ }
-+
-+ /* besides the file, we need some working memory, too */
-+ if(i + MIN_GFX_FREE + 0x0f >= (int) buf_size) {
-+ printf("file \"%s\" too large, press a key to continue...\n", graphics_file);
-+ getkey();
-+ return;
-+ }
-+
-+ gfx_data->mem_cur = gfx_data->mem_start + ((i + 0x0f + 3) & ~3); /* align it */
-+
-+#if 0
-+ printf("image: %d bytes (%d bytes left)\n", i, gfx_data->mem_max - gfx_data->mem_cur);
-+ getkey();
-+#endif
-+
-+
-+ /* locate file inside cpio archive */
-+ if(!(code_start = find_file(buf, i, &file_start))) {
-+ printf("\"%s\" has wrong format, press a key to continue...\n", graphics_file);
-+ getkey();
-+ return;
-+ }
-+
-+
-+ /* align it */
-+ u = (-(code_start + gfx_data->mem_start + file_start)) & 0x0f;
-+ gfx_data->mem_align = gfx_data->mem_start + u;
-+ gfx_data->mem_file = gfx_data->mem_align + file_start;
-+ if(u) {
-+ memcpy((void *) gfx_data->mem_align, (void *) gfx_data->mem_start, i);
-+ }
-+
-+ /* init interface to graphics functions */
-+
-+ code_start += gfx_data->mem_file;
-+
-+#if 0
-+ printf("code_start: 0x%x, file_start: 0x%x, mem_align = 0x%x, mem_file = 0x%x\n",
-+ code_start, file_start, gfx_data->mem_align, gfx_data->mem_file
-+ );
-+ getkey();
-+#endif
-+
-+ gfx_data->code_seg = code_start >> 4;
-+
-+#if 0
-+ printf("code start = 0x%x, code_seg = 0x%x\n", code_start, gfx_data->code_seg);
-+#endif
-+
-+ for(i = 0; (unsigned) i < sizeof gfx_data->jmp_table / sizeof *gfx_data->jmp_table; i++) {
-+ gfx_data->jmp_table[i] = (gfx_data->code_seg << 16) + ((unsigned short *) code_start)[i];
-+ }
-+
-+#if 0
-+ for(i = 0; i < 12; i++) {
-+ printf("%d: 0x%x\n", i, gfx_data->jmp_table[i]);
-+ }
-+
-+ for(i = 0; i < gfx_data->menu_entries; i++) {
-+ printf(">%s< - >%s<\n",
-+ gfx_data->menu_list + i * gfx_data->menu_entry_len,
-+ gfx_data->args_list + i * gfx_data->args_entry_len
-+ );
-+ }
-+
-+ printf("def: >%s<\n", gfx_data->menu_default_entry);
-+#endif
-+
-+
-+ /* switch to graphics mode */
-+
-+ if(gfx_init(gfx_data)) {
-+#if 0
-+ printf("gfx_init failed\n");
-+ getkey();
-+#endif
-+ return;
-+ }
-+
-+ gfx_setup_menu(gfx_data);
-+
-+ i = gfx_input(gfx_data, &selected_entry);
-+
-+ /* ESC -> show text menu */
-+ if(i == 1) {
-+ gfx_done(gfx_data);
-+ grub_timeout = -1;
-+
-+ return;
-+ }
-+
-+ gfx_done(gfx_data);
-+
-+ heap = saved_heap; /* free most of the graphics data */
-+
-+ // printf("cmdline: >%s<, entry = %d\n", gfx_data->cmdline, selected_entry);
-+
-+ if(selected_entry < 0 || selected_entry > num_entries) return;
-+
-+
-+ /* create new config with modified kernel option */
-+
-+ cfg = get_entry(config_entries, selected_entry, 1);
-+
-+ new_config = heap;
-+
-+ for(i = 0; ; i++) {
-+ s = get_entry(cfg, i, 0);
-+ if(!*s) {
-+ if(!i) *heap++ = 0;
-+ *heap++ = 0;
-+ break;
-+ }
-+ if(!memcmp(s, "kernel", 6) && (s[6] == ' ' || s[6] == '\t')) {
-+ t = skip_to(0, s);
-+ if(*t) t = skip_to(0, t);
-+ memmove(heap, s, t - s);
-+ heap += t - s;
-+ *heap++ = ' ';
-+ strcpy(heap, gfx_data->cmdline);
-+ heap += strlen(gfx_data->cmdline) + 1;
-+ }
-+ else {
-+ strcpy(heap, s);
-+ heap += strlen(s) + 1;
-+ }
-+ }
-+
-+ *heap++ = 0;
-+
-+ // hexdump(new_config, heap - new_config);
-+ // getkey();
-+
-+ run_script(new_config, heap);
-+}
-+
-+
- static int
- get_line_from_config (char *cmdline, int maxlen, int read_from_file)
- {
-@@ -1059,9 +1474,12 @@
- }
- else
- {
-- /* Run menu interface. */
-- run_menu (menu_entries, config_entries, num_entries,
-- menu_entries + menu_len, default_entry);
-+ if (*graphics_file && !password && show_menu && grub_timeout)
-+ {
-+ run_graphics_menu(menu_entries, config_entries, num_entries,menu_entries + menu_len, default_entry);
-+ }
-+ /* Run menu interface. */
-+ run_menu (menu_entries, config_entries, num_entries, menu_entries + menu_len, default_entry);
- }
- }
- }
+++ /dev/null
-diff -ur grub-0.97/util/grub-install.in grub-0.97-old/util/grub-install.in
---- grub-0.97/util/grub-install.in 2006-08-05 16:46:33.505226176 +0200
-+++ grub-0.97-old/util/grub-install.in 2004-07-24 20:57:31.000000000 +0200
-@@ -447,6 +447,10 @@
- rm -f $img_file
- rm -f $log_file
-
-+if ! test -e ${grubdir}/grub.conf ; then
-+ test -e ${grubdir}/menu.lst && ln -s ./menu.lst ${grubdir}/grub.conf
-+fi
-+
- # Create a safe temporary file.
- test -n "$mklog" && log_file=`$mklog`
-
+++ /dev/null
-diff -Nur grub-0.97-dirs/docs/grub.texi grub-0.97-wildcards/docs/grub.texi
---- grub-0.97-dirs/docs/grub.texi 2005-08-21 20:31:12.000000000 +0300
-+++ grub-0.97-wildcards/docs/grub.texi 2005-08-21 20:32:45.000000000 +0300
-@@ -2121,6 +2121,7 @@
- * gfxmenu:: Use graphical menu interface
- * timeout:: Set the timeout
- * title:: Start a menu entry
-+* wildcard:: Define a wildcard boot entry
- @end menu
-
-
-@@ -2190,6 +2191,42 @@
- @end deffn
-
-
-+@node wildcard
-+@subsection wildcard
-+
-+@deffn Command wildcard pathname
-+Treat this boot entry as a wildcard entry: The
-+wildcard, title, kernel, and initrd commands (see @ref{Menu-specific
-+commands} and @ref{Command-line and menu entry commands}) each have an
-+asterisk (*) in their value. A filename match is performed on the
-+@var{pathname} of the wildcard command. For each match, the entire boot
-+entry is duplicated. The part of the filename whcih matches the asterisk
-+in the wildcard command replaces the asterisks in the title, kernel, and
-+initrd commands. For example, with the files vmlinuz-2.6.5-1 and
-+vmlinuz-2.6.8-8 below (hd0,7)/boot, the following entry in the stage 2
-+configuration file:
-+
-+@example
-+title Linux-*
-+ wildcard (hd0,7)/boot/vmlinuz-*
-+ kernel (hd0,7)/boot/vmlinuz-* root=/dev/hda8
-+ initrd (hd0,7)/boot/initrd-*
-+@end example
-+
-+would expand as follows:
-+
-+@example
-+title Linux-2.6.5-1
-+ wildcard (hd0,7)/boot/vmlinuz-2.6.5-1
-+ kernel (hd0,7)/boot/vmlinuz-2.6.5-1 root=/dev/hda8
-+ initrd (hd0,7)/boot/initrd-2.6.5-1
-+title Linux-2.6.8-8
-+ wildcard (hd0,7)/boot/vmlinuz-2.6.8-8
-+ kernel (hd0,7)/boot/vmlinuz-2.6.8-8 root=/dev/hda8
-+ initrd (hd0,7)/boot/initrd-2.6.8-8
-+@end example
-+@end deffn
-+
- @node General commands
- @section The list of general commands
-
-diff -Nur grub-0.97-dirs/netboot/fsys_tftp.c grub-0.97-wildcards/netboot/fsys_tftp.c
---- grub-0.97-dirs/netboot/fsys_tftp.c 2005-08-21 20:31:02.000000000 +0300
-+++ grub-0.97-wildcards/netboot/fsys_tftp.c 2005-08-21 20:32:45.000000000 +0300
-@@ -409,7 +409,7 @@
- /* Check if the file DIRNAME really exists. Get the size and save it in
- FILEMAX. */
- int
--tftp_dir (char *dirname)
-+tftp_dir (char *dirname, void (*handle)(char *))
- {
- int ch;
-
-@@ -418,7 +418,7 @@
- #endif
-
- /* In TFTP, there is no way to know what files exist. */
-- if (print_possibilities)
-+ if (handle)
- return 1;
-
- /* Don't know the size yet. */
-diff -Nur grub-0.97-dirs/stage2/builtins.c grub-0.97-wildcards/stage2/builtins.c
---- grub-0.97-dirs/stage2/builtins.c 2005-08-21 20:31:02.000000000 +0300
-+++ grub-0.97-wildcards/stage2/builtins.c 2005-08-21 20:32:45.000000000 +0300
-@@ -4828,6 +4828,49 @@
- };
-
- \f
-+/* wildcard */
-+ static int
-+wildcard_func (char *arg, int flags)
-+{
-+#ifdef DEBUG_WILDCARD
-+ char *w = wildcard (arg);
-+
-+ if (w)
-+ {
-+ while (*w)
-+ {
-+ grub_printf("%s ", w);
-+ w += strlen (w) + 1;
-+ }
-+ grub_printf("\n");
-+ return 1;
-+ }
-+ else
-+ print_error();
-+#endif
-+
-+ /* This special command is interpreted in the config file parser. */
-+ return 0;
-+}
-+
-+static struct builtin builtin_wildcard =
-+ {
-+ "wildcard",
-+ wildcard_func,
-+#ifndef DEBUG_WILDCARD
-+ BUILTIN_MENU,
-+#else
-+ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
-+ "wildcard GLOB",
-+ "Declare this menu entry as a wildcard entry. GLOB is a path containing"
-+ " one asterisk. All files matching this expression are looked up; the"
-+ " menu entry is duplicated for each match with asterisks in other"
-+ " commands replaced by the string matching the asterisk in the wildcard"
-+ " command."
-+#endif
-+};
-+
-+\f
- /* The table of builtin commands. Sorted in dictionary order. */
- struct builtin *builtin_table[] =
- {
-@@ -4917,5 +4960,6 @@
- &builtin_unhide,
- &builtin_uppermem,
- &builtin_vbeprobe,
-+ &builtin_wildcard,
- 0
- };
-diff -Nur grub-0.97-dirs/stage2/disk_io.c grub-0.97-wildcards/stage2/disk_io.c
---- grub-0.97-dirs/stage2/disk_io.c 2005-08-21 20:31:02.000000000 +0300
-+++ grub-0.97-wildcards/stage2/disk_io.c 2005-08-21 20:32:45.000000000 +0300
-@@ -36,7 +36,6 @@
- void (*disk_read_func) (int, int, int) = NULL;
-
- #ifndef STAGE1_5
--int print_possibilities;
-
- static int do_completion;
- static int unique;
-@@ -1479,7 +1478,7 @@
- if (! is_completion)
- grub_printf (" Possible files are:");
-
-- dir (buf);
-+ dir (buf, print_a_completion);
-
- if (is_completion && *unique_string)
- {
-@@ -1498,7 +1497,7 @@
- *ptr = '/';
- *(ptr + 1) = 0;
-
-- dir (buf);
-+ dir (buf, print_a_completion);
-
- /* Restore the original unique value. */
- unique = 1;
-@@ -1626,12 +1625,7 @@
- if (!errnum && fsys_type == NUM_FSYS)
- errnum = ERR_FSYS_MOUNT;
-
--# ifndef STAGE1_5
-- /* set "dir" function to open a file */
-- print_possibilities = 0;
--# endif
--
-- if (!errnum && (*(fsys_table[fsys_type].dir_func)) (filename))
-+ if (!errnum && (*(fsys_table[fsys_type].dir_func)) (filename, NULL))
- {
- #ifndef NO_DECOMPRESSION
- return gunzip_test_header ();
-@@ -1752,7 +1746,7 @@
- }
-
- int
--dir (char *dirname)
-+dir (char *dirname, void (*handle)(char *))
- {
- #ifndef NO_DECOMPRESSION
- compressed_file = 0;
-@@ -1761,19 +1755,18 @@
- if (!(dirname = setup_part (dirname)))
- return 0;
-
-+ errnum = 0;
- if (*dirname != '/')
- errnum = ERR_BAD_FILENAME;
--
-- if (fsys_type == NUM_FSYS)
-+ else if (fsys_type == NUM_FSYS)
- errnum = ERR_FSYS_MOUNT;
--
-- if (errnum)
-- return 0;
--
-- /* set "dir" function to list completions */
-- print_possibilities = 1;
--
-- return (*(fsys_table[fsys_type].dir_func)) (dirname);
-+ else
-+ {
-+ fsys_table[fsys_type].dir_func (dirname, handle);
-+ if (errnum == ERR_FILE_NOT_FOUND)
-+ errnum = 0;
-+ }
-+ return errnum == 0;
- }
- #endif /* STAGE1_5 */
-
-diff -Nur grub-0.97-dirs/stage2/filesys.h grub-0.97-wildcards/stage2/filesys.h
---- grub-0.97-dirs/stage2/filesys.h 2005-08-21 20:31:02.000000000 +0300
-+++ grub-0.97-wildcards/stage2/filesys.h 2005-08-21 20:32:45.000000000 +0300
-@@ -24,7 +24,7 @@
- #define FSYS_FFS_NUM 1
- int ffs_mount (void);
- int ffs_read (char *buf, int len);
--int ffs_dir (char *dirname);
-+int ffs_dir (char *dirname, void (*handle)(char *));
- int ffs_embed (int *start_sector, int needed_sectors);
- #else
- #define FSYS_FFS_NUM 0
-@@ -34,7 +34,7 @@
- #define FSYS_UFS2_NUM 1
- int ufs2_mount (void);
- int ufs2_read (char *buf, int len);
--int ufs2_dir (char *dirname);
-+int ufs2_dir (char *dirname, void (*handle)(char *));
- int ufs2_embed (int *start_sector, int needed_sectors);
- #else
- #define FSYS_UFS2_NUM 0
-@@ -44,7 +44,7 @@
- #define FSYS_FAT_NUM 1
- int fat_mount (void);
- int fat_read (char *buf, int len);
--int fat_dir (char *dirname);
-+int fat_dir (char *dirname, void (*handle)(char *));
- #else
- #define FSYS_FAT_NUM 0
- #endif
-@@ -53,7 +53,7 @@
- #define FSYS_EXT2FS_NUM 1
- int ext2fs_mount (void);
- int ext2fs_read (char *buf, int len);
--int ext2fs_dir (char *dirname);
-+int ext2fs_dir (char *dirname, void (*handle)(char *));
- #else
- #define FSYS_EXT2FS_NUM 0
- #endif
-@@ -62,7 +62,7 @@
- #define FSYS_MINIX_NUM 1
- int minix_mount (void);
- int minix_read (char *buf, int len);
--int minix_dir (char *dirname);
-+int minix_dir (char *dirname, void (*handle)(char *));
- #else
- #define FSYS_MINIX_NUM 0
- #endif
-@@ -71,7 +71,7 @@
- #define FSYS_REISERFS_NUM 1
- int reiserfs_mount (void);
- int reiserfs_read (char *buf, int len);
--int reiserfs_dir (char *dirname);
-+int reiserfs_dir (char *dirname, void (*handle)(char *));
- int reiserfs_embed (int *start_sector, int needed_sectors);
- #if defined(__linux__) && defined (GRUB_UTIL)
- #include <sys/types.h>
-@@ -91,7 +91,7 @@
- #define FSYS_VSTAFS_NUM 1
- int vstafs_mount (void);
- int vstafs_read (char *buf, int len);
--int vstafs_dir (char *dirname);
-+int vstafs_dir (char *dirname, void (*handle)(char *));
- #else
- #define FSYS_VSTAFS_NUM 0
- #endif
-@@ -100,7 +100,7 @@
- #define FSYS_JFS_NUM 1
- int jfs_mount (void);
- int jfs_read (char *buf, int len);
--int jfs_dir (char *dirname);
-+int jfs_dir (char *dirname, void (*handle)(char *));
- int jfs_embed (int *start_sector, int needed_sectors);
- #else
- #define FSYS_JFS_NUM 0
-@@ -110,7 +110,7 @@
- #define FSYS_XFS_NUM 1
- int xfs_mount (void);
- int xfs_read (char *buf, int len);
--int xfs_dir (char *dirname);
-+int xfs_dir (char *dirname, void (*handle)(char *));
- #else
- #define FSYS_XFS_NUM 0
- #endif
-@@ -119,7 +119,7 @@
- #define FSYS_TFTP_NUM 1
- int tftp_mount (void);
- int tftp_read (char *buf, int len);
--int tftp_dir (char *dirname);
-+int tftp_dir (char *dirname, void (*handle)(char *));
- void tftp_close (void);
- #else
- #define FSYS_TFTP_NUM 0
-@@ -129,7 +129,7 @@
- #define FSYS_ISO9660_NUM 1
- int iso9660_mount (void);
- int iso9660_read (char *buf, int len);
--int iso9660_dir (char *dirname);
-+int iso9660_dir (char *dirname, void (*handle)(char *));
- #else
- #define FSYS_ISO9660_NUM 0
- #endif
-@@ -160,16 +160,10 @@
- char *name;
- int (*mount_func) (void);
- int (*read_func) (char *buf, int len);
-- int (*dir_func) (char *dirname);
-+ int (*dir_func) (char *dirname, void (*print_one)(char *));
- void (*close_func) (void);
- int (*embed_func) (int *start_sector, int needed_sectors);
- };
-
--#ifdef STAGE1_5
--# define print_possibilities 0
--#else
--extern int print_possibilities;
--#endif
--
- extern int fsmax;
- extern struct fsys_entry fsys_table[NUM_FSYS + 1];
-diff -Nur grub-0.97-dirs/stage2/fsys_ext2fs.c grub-0.97-wildcards/stage2/fsys_ext2fs.c
---- grub-0.97-dirs/stage2/fsys_ext2fs.c 2005-08-21 20:31:02.000000000 +0300
-+++ grub-0.97-wildcards/stage2/fsys_ext2fs.c 2005-08-21 20:32:45.000000000 +0300
-@@ -495,7 +495,7 @@
- * side effects: messes up GROUP_DESC buffer area
- */
- int
--ext2fs_dir (char *dirname)
-+ext2fs_dir (char *dirname, void (*handle)(char *))
- {
- int current_ino = EXT2_ROOT_INO; /* start at the root */
- int updir_ino = current_ino; /* the parent of the current directory */
-@@ -521,7 +521,6 @@
- #ifdef E2DEBUG
- unsigned char *i;
- #endif /* E2DEBUG */
--
- /* loop invariants:
- current_ino = inode to lookup
- dirname = pointer to filename component we are cur looking up within
-@@ -713,18 +712,9 @@
- give up */
- if (loc >= INODE->i_size)
- {
-- if (print_possibilities < 0)
-- {
--# if 0
-- putchar ('\n');
--# endif
-- }
-- else
-- {
-- errnum = ERR_FILE_NOT_FOUND;
-- *rest = ch;
-- }
-- return (print_possibilities < 0);
-+ errnum = ERR_FILE_NOT_FOUND;
-+ *rest = ch;
-+ return 0;
- }
-
- /* else, find the (logical) block component of our location */
-@@ -765,20 +755,15 @@
- str_chk = substring (dirname, dp->name);
-
- # ifndef STAGE1_5
-- if (print_possibilities && ch != '/'
-- && (!*dirname || str_chk <= 0))
-- {
-- if (print_possibilities > 0)
-- print_possibilities = -print_possibilities;
-- print_a_completion (dp->name);
-- }
-+ if (handle && ch != '/' && (!*dirname || str_chk <= 0))
-+ handle (dp->name);
- # endif
-
- dp->name[dp->name_len] = saved_c;
- }
-
- }
-- while (!dp->inode || (str_chk || (print_possibilities && ch != '/')));
-+ while (!dp->inode || (str_chk || (handle && ch != '/')));
-
- current_ino = dp->inode;
- *(dirname = rest) = ch;
-diff -Nur grub-0.97-dirs/stage2/fsys_fat.c grub-0.97-wildcards/stage2/fsys_fat.c
---- grub-0.97-dirs/stage2/fsys_fat.c 2005-08-21 20:31:02.000000000 +0300
-+++ grub-0.97-wildcards/stage2/fsys_fat.c 2005-08-21 20:32:45.000000000 +0300
-@@ -289,7 +289,7 @@
- }
-
- int
--fat_dir (char *dirname)
-+fat_dir (char *dirname, void (*handle)(char *))
- {
- char *rest, ch, dir_buf[FAT_DIRENTRY_LENGTH];
- char *filename = (char *) NAME_BUF;
-@@ -345,7 +345,7 @@
- *rest = 0;
-
- # ifndef STAGE1_5
-- if (print_possibilities && ch != '/')
-+ if (handle && ch != '/')
- do_possibilities = 1;
- # endif
-
-@@ -356,16 +356,6 @@
- {
- if (!errnum)
- {
--# ifndef STAGE1_5
-- if (print_possibilities < 0)
-- {
--#if 0
-- putchar ('\n');
--#endif
-- return 1;
-- }
--# endif /* STAGE1_5 */
--
- errnum = ERR_FILE_NOT_FOUND;
- *rest = ch;
- }
-@@ -460,11 +450,7 @@
- {
- print_filename:
- if (substring (dirname, filename) <= 0)
-- {
-- if (print_possibilities > 0)
-- print_possibilities = -print_possibilities;
-- print_a_completion (filename);
-- }
-+ handle (filename);
- continue;
- }
- # endif /* STAGE1_5 */
-diff -Nur grub-0.97-dirs/stage2/fsys_ffs.c grub-0.97-wildcards/stage2/fsys_ffs.c
---- grub-0.97-dirs/stage2/fsys_ffs.c 2005-08-21 20:31:02.000000000 +0300
-+++ grub-0.97-wildcards/stage2/fsys_ffs.c 2005-08-21 20:32:45.000000000 +0300
-@@ -180,7 +180,7 @@
-
-
- int
--ffs_dir (char *dirname)
-+ffs_dir (char *dirname, void (*handle)(char *))
- {
- char *rest, ch;
- int block, off, loc, map, ino = ROOTINO;
-@@ -236,13 +236,6 @@
- {
- if (loc >= INODE->i_size)
- {
--#if 0
-- putchar ('\n');
--#endif
--
-- if (print_possibilities < 0)
-- return 1;
--
- errnum = ERR_FILE_NOT_FOUND;
- *rest = ch;
- return 0;
-@@ -267,18 +260,13 @@
- loc += dp->d_reclen;
-
- #ifndef STAGE1_5
-- if (dp->d_ino && print_possibilities && ch != '/'
-+ if (dp->d_ino && handle && ch != '/'
- && (!*dirname || substring (dirname, dp->d_name) <= 0))
-- {
-- if (print_possibilities > 0)
-- print_possibilities = -print_possibilities;
--
-- print_a_completion (dp->d_name);
-- }
-+ handle (dp->d_name);
- #endif /* STAGE1_5 */
- }
- while (!dp->d_ino || (substring (dirname, dp->d_name) != 0
-- || (print_possibilities && ch != '/')));
-+ || (handle && ch != '/')));
-
- /* only get here if we have a matching directory entry */
-
-diff -Nur grub-0.97-dirs/stage2/fsys_iso9660.c grub-0.97-wildcards/stage2/fsys_iso9660.c
---- grub-0.97-dirs/stage2/fsys_iso9660.c 2005-08-21 20:31:02.000000000 +0300
-+++ grub-0.97-wildcards/stage2/fsys_iso9660.c 2005-08-21 20:32:45.000000000 +0300
-@@ -133,7 +133,7 @@
- }
-
- int
--iso9660_dir (char *dirname)
-+iso9660_dir (char *dirname, void (*handle)(char *))
- {
- struct iso_directory_record *idr;
- RR_ptr_t rr_ptr;
-@@ -346,7 +346,7 @@
- if (name_len >= pathlen
- && !memcmp(name, dirname, pathlen))
- {
-- if (dirname[pathlen] == '/' || !print_possibilities)
-+ if (dirname[pathlen] == '/' || !handle)
- {
- /*
- * DIRNAME is directory component of pathname,
-@@ -377,11 +377,9 @@
- else /* Completion */
- {
- #ifndef STAGE1_5
-- if (print_possibilities > 0)
-- print_possibilities = -print_possibilities;
- memcpy(NAME_BUF, name, name_len);
- NAME_BUF[name_len] = '\0';
-- print_a_completion (NAME_BUF);
-+ handle (NAME_BUF);
- #endif
- }
- }
-@@ -390,7 +388,7 @@
- size -= ISO_SECTOR_SIZE;
- } /* size>0 */
-
-- if (dirname[pathlen] == '/' || print_possibilities >= 0)
-+ if (dirname[pathlen] == '/' || handle)
- {
- errnum = ERR_FILE_NOT_FOUND;
- return 0;
-diff -Nur grub-0.97-dirs/stage2/fsys_jfs.c grub-0.97-wildcards/stage2/fsys_jfs.c
---- grub-0.97-dirs/stage2/fsys_jfs.c 2005-08-21 20:31:02.000000000 +0300
-+++ grub-0.97-wildcards/stage2/fsys_jfs.c 2005-08-21 20:32:45.000000000 +0300
-@@ -270,7 +270,7 @@
- }
-
- int
--jfs_dir (char *dirname)
-+jfs_dir (char *dirname, void (*handle)(char *))
- {
- char *ptr, *rest, ch;
- ldtentry_t *de;
-@@ -357,12 +357,9 @@
-
- cmp = (!*dirname) ? -1 : substring (dirname, namebuf);
- #ifndef STAGE1_5
-- if (print_possibilities && ch != '/'
-- && cmp <= 0) {
-- if (print_possibilities > 0)
-- print_possibilities = -print_possibilities;
-- print_a_completion (namebuf);
-- } else
-+ if (handle && ch != '/' && cmp <= 0)
-+ handle (namebuf);
-+ else
- #endif
- if (cmp == 0) {
- parent_inum = inum;
-@@ -372,9 +369,6 @@
- }
- de = next_dentry ();
- if (de == NULL) {
-- if (print_possibilities < 0)
-- return 1;
--
- errnum = ERR_FILE_NOT_FOUND;
- *rest = ch;
- return 0;
-diff -Nur grub-0.97-dirs/stage2/fsys_minix.c grub-0.97-wildcards/stage2/fsys_minix.c
---- grub-0.97-dirs/stage2/fsys_minix.c 2005-08-21 20:31:02.000000000 +0300
-+++ grub-0.97-wildcards/stage2/fsys_minix.c 2005-08-21 20:32:45.000000000 +0300
-@@ -294,7 +294,7 @@
- inode of the file we were trying to look up
- side effects: none yet */
- int
--minix_dir (char *dirname)
-+minix_dir (char *dirname, void (*handle)(char *))
- {
- int current_ino = MINIX_ROOT_INO; /* start at the root */
- int updir_ino = current_ino; /* the parent of the current directory */
-@@ -457,18 +457,9 @@
- give up */
- if (loc >= INODE->i_size)
- {
-- if (print_possibilities < 0)
-- {
--#if 0
-- putchar ('\n');
--#endif
-- }
-- else
-- {
-- errnum = ERR_FILE_NOT_FOUND;
-- *rest = ch;
-- }
-- return (print_possibilities < 0);
-+ errnum = ERR_FILE_NOT_FOUND;
-+ *rest = ch;
-+ return 0;
- }
-
- /* else, find the (logical) block component of our location */
-@@ -510,20 +501,15 @@
- str_chk = substring (dirname, dp->name);
-
- # ifndef STAGE1_5
-- if (print_possibilities && ch != '/'
-- && (!*dirname || str_chk <= 0))
-- {
-- if (print_possibilities > 0)
-- print_possibilities = -print_possibilities;
-- print_a_completion (dp->name);
-- }
-+ if (handle && ch != '/' && (!*dirname || str_chk <= 0))
-+ handle (dp->name);
- # endif
-
- dp->name[namelen] = saved_c;
- }
-
- }
-- while (!dp->inode || (str_chk || (print_possibilities && ch != '/')));
-+ while (!dp->inode || (str_chk || (handle && ch != '/')));
-
- current_ino = dp->inode;
- *(dirname = rest) = ch;
-diff -Nur grub-0.97-dirs/stage2/fsys_reiserfs.c grub-0.97-wildcards/stage2/fsys_reiserfs.c
---- grub-0.97-dirs/stage2/fsys_reiserfs.c 2005-08-21 20:31:02.000000000 +0300
-+++ grub-0.97-wildcards/stage2/fsys_reiserfs.c 2005-08-21 20:32:45.000000000 +0300
-@@ -991,7 +991,7 @@
- * the size of the file.
- */
- int
--reiserfs_dir (char *dirname)
-+reiserfs_dir (char *dirname, void (*handle)(char *))
- {
- struct reiserfs_de_head *de_head;
- char *rest, ch;
-@@ -1123,7 +1123,7 @@
- *rest = 0;
-
- # ifndef STAGE1_5
-- if (print_possibilities && ch != '/')
-+ if (handle && ch != '/')
- do_possibilities = 1;
- # endif /* ! STAGE1_5 */
-
-@@ -1170,10 +1170,8 @@
- {
- if (cmp <= 0)
- {
-- if (print_possibilities > 0)
-- print_possibilities = -print_possibilities;
- *name_end = 0;
-- print_a_completion (filename);
-+ handle (filename);
- *name_end = tmp;
- }
- }
-@@ -1189,12 +1187,6 @@
- num_entries--;
- }
- }
--
--# ifndef STAGE1_5
-- if (print_possibilities < 0)
-- return 1;
--# endif /* ! STAGE1_5 */
--
- errnum = ERR_FILE_NOT_FOUND;
- *rest = ch;
- return 0;
-diff -Nur grub-0.97-dirs/stage2/fsys_ufs2.c grub-0.97-wildcards/stage2/fsys_ufs2.c
---- grub-0.97-dirs/stage2/fsys_ufs2.c 2005-08-21 20:31:02.000000000 +0300
-+++ grub-0.97-wildcards/stage2/fsys_ufs2.c 2005-08-21 20:32:45.000000000 +0300
-@@ -204,7 +204,7 @@
- }
-
- int
--ufs2_dir (char *dirname)
-+ufs2_dir (char *dirname, void (*handle)(char *))
- {
- char *rest, ch;
- int block, off, loc, ino = ROOTINO;
-@@ -261,9 +261,6 @@
- {
- if (loc >= INODE_UFS2->di_size)
- {
-- if (print_possibilities < 0)
-- return 1;
--
- errnum = ERR_FILE_NOT_FOUND;
- *rest = ch;
- return 0;
-@@ -288,18 +285,13 @@
- loc += dp->d_reclen;
-
- #ifndef STAGE1_5
-- if (dp->d_ino && print_possibilities && ch != '/'
-+ if (dp->d_ino && handle && ch != '/'
- && (!*dirname || substring (dirname, dp->d_name) <= 0))
-- {
-- if (print_possibilities > 0)
-- print_possibilities = -print_possibilities;
--
-- print_a_completion (dp->d_name);
-- }
-+ handle (dp->d_name);
- #endif /* STAGE1_5 */
- }
- while (!dp->d_ino || (substring (dirname, dp->d_name) != 0
-- || (print_possibilities && ch != '/')));
-+ || (handle && ch != '/')));
-
- /* only get here if we have a matching directory entry */
-
-diff -Nur grub-0.97-dirs/stage2/fsys_vstafs.c grub-0.97-wildcards/stage2/fsys_vstafs.c
---- grub-0.97-dirs/stage2/fsys_vstafs.c 2005-08-21 20:31:02.000000000 +0300
-+++ grub-0.97-wildcards/stage2/fsys_vstafs.c 2005-08-21 20:32:45.000000000 +0300
-@@ -115,7 +115,7 @@
- }
-
- int
--vstafs_dir (char *dirname)
-+vstafs_dir (char *dirname, void (*handle)(char *))
- {
- char *fn, ch;
- struct dir_entry *d;
-@@ -146,14 +146,9 @@
- continue;
-
- #ifndef STAGE1_5
-- if (print_possibilities && ch != '/'
-+ if (handle && ch != '/'
- && (! *dirname || strcmp (dirname, d->name) <= 0))
-- {
-- if (print_possibilities > 0)
-- print_possibilities = -print_possibilities;
--
-- printf (" %s", d->name);
-- }
-+ handle(d->name);
- #endif
- if (! grub_strcmp (dirname, d->name))
- {
-@@ -168,12 +163,6 @@
- *(dirname = fn) = ch;
- if (! d)
- {
-- if (print_possibilities < 0)
-- {
-- putchar ('\n');
-- return 1;
-- }
--
- errnum = ERR_FILE_NOT_FOUND;
- return 0;
- }
-diff -Nur grub-0.97-dirs/stage2/fsys_xfs.c grub-0.97-wildcards/stage2/fsys_xfs.c
---- grub-0.97-dirs/stage2/fsys_xfs.c 2005-08-21 20:31:02.000000000 +0300
-+++ grub-0.97-wildcards/stage2/fsys_xfs.c 2005-08-21 20:32:45.000000000 +0300
-@@ -534,7 +534,7 @@
- }
-
- int
--xfs_dir (char *dirname)
-+xfs_dir (char *dirname, void (*handle)(char *))
- {
- xfs_ino_t ino, parent_ino, new_ino;
- xfs_fsize_t di_size;
-@@ -595,11 +595,9 @@
- for (;;) {
- cmp = (!*dirname) ? -1 : substring (dirname, name);
- #ifndef STAGE1_5
-- if (print_possibilities && ch != '/' && cmp <= 0) {
-- if (print_possibilities > 0)
-- print_possibilities = -print_possibilities;
-- print_a_completion (name);
-- } else
-+ if (handle && ch != '/' && cmp <= 0)
-+ handle (name);
-+ else
- #endif
- if (cmp == 0) {
- parent_ino = ino;
-@@ -610,9 +608,6 @@
- }
- name = next_dentry (&new_ino);
- if (name == NULL) {
-- if (print_possibilities < 0)
-- return 1;
--
- errnum = ERR_FILE_NOT_FOUND;
- *rest = ch;
- return 0;
-diff -Nur grub-0.97-dirs/stage2/shared.h grub-0.97-wildcards/stage2/shared.h
---- grub-0.97-dirs/stage2/shared.h 2005-08-21 20:31:02.000000000 +0300
-+++ grub-0.97-wildcards/stage2/shared.h 2005-08-21 20:32:45.000000000 +0300
-@@ -1012,9 +1012,11 @@
- /* Close a file. */
- void grub_close (void);
-
--/* List the contents of the directory that was opened with GRUB_OPEN,
-- printing all completions. */
--int dir (char *dirname);
-+/* List the contents of DIRECTORY. */
-+int dir (char *dirname, void (*handle)(char *));
-+
-+/* Wildcard expand the last pathname component of GLOB. */
-+char *wildcard (char *glob, int *len);
-
- int set_bootdev (int hdbias);
-
-diff -Nur grub-0.97-dirs/stage2/stage2.c grub-0.97-wildcards/stage2/stage2.c
---- grub-0.97-dirs/stage2/stage2.c 2005-08-21 20:31:02.000000000 +0300
-+++ grub-0.97-wildcards/stage2/stage2.c 2005-08-21 20:33:24.000000000 +0300
-@@ -1243,6 +1243,230 @@
- }
-
-
-+char *wildcard_prefix, *wildcard_suffix;
-+char wildcard_matches[1024], *end_wildcard_matches;
-+
-+static void wildcard_handler(char *name);
-+
-+/* Match one directory entry against the current wildcard. If the entry
-+ matches, store it in WILDCARD_MATCHES. Silently ignore entries that
-+ don't fit into WILDCARD_MATCHES anymore. */
-+static void
-+wildcard_handler(char *name)
-+{
-+ char *n = name, *p = wildcard_prefix;
-+
-+ while (*p && *p == *n)
-+ {
-+ p++;
-+ n++;
-+ }
-+ if (*p)
-+ return; /* prefix mismatch */
-+
-+ p = name + grub_strlen (name) - grub_strlen (wildcard_suffix);
-+ /* [n .. p) is the part matching the asterisk */
-+
-+ if (p < n || grub_strcmp (p, wildcard_suffix) != 0)
-+ return; /* suffix mismatch */
-+
-+ /* store this match */
-+ if (p - n + 1 > sizeof (wildcard_matches) -
-+ (end_wildcard_matches - wildcard_matches))
-+ return; /* out of space */
-+ while (n < p)
-+ *end_wildcard_matches++ = *n++;
-+ *end_wildcard_matches++ = 0;
-+}
-+
-+/* Wildcard expand the GLOB argument. Return NULL upon failure, or
-+ a list of 0-terminated expansions, terminated by a zero-length string. */
-+char *
-+wildcard (char *glob, int *len)
-+{
-+ char path[128], *p;
-+ int ret;
-+
-+ end_wildcard_matches = wildcard_matches;
-+ if (grub_strlen (glob) + 1 > sizeof (path)) {
-+ errnum = ERR_FILELENGTH;
-+ return NULL; /* cannot handle pathnames this long */
-+ }
-+ grub_strcpy (path, glob);
-+ p = path;
-+ while (*p)
-+ p++;
-+ wildcard_suffix = p;
-+ while (p > path && *p != '/')
-+ p--;
-+ if (*p != '/')
-+ {
-+ errnum = ERR_BAD_FILETYPE;
-+ return NULL; /* Cannot wildcard device names */
-+ }
-+ *(++p) = 0;
-+ wildcard_prefix = glob + (p - path);
-+ for (p = wildcard_prefix;; p++)
-+ {
-+ if (*p == 0)
-+ {
-+ /* We cannot do exact matches: this cannot be represented in the
-+ result list. */
-+ return NULL;
-+ }
-+ else if (*p == '*')
-+ {
-+ *p++ = 0;
-+ wildcard_suffix = p;
-+ break;
-+ }
-+ }
-+
-+ ret = dir (path, wildcard_handler);
-+ /* restore original argument */
-+ wildcard_prefix[grub_strlen (wildcard_prefix)] = '*';
-+ if (!ret)
-+ return NULL;
-+ *len = end_wildcard_matches - wildcard_matches;
-+ return wildcard_matches;
-+}
-+
-+static int inplace_sort_nextint(char **p);
-+
-+static int inplace_sort_nextint(char **p)
-+{
-+ int i = 0;
-+
-+ while (**p && **p < '0' && **p > '9') *p++;
-+ if (!**p) return -1;
-+ while (**p && **p >= '0' && **p <= '9')
-+ {
-+ i = i * 10 + **p - '0';
-+ *p++;
-+ }
-+ return i;
-+}
-+
-+static int inplace_sort_strcmp(char *l, char *r);
-+
-+static int
-+inplace_sort_strcmp(char *l, char *r)
-+{
-+ char *lp = l;
-+ char *rp = r;
-+ int li, ri;
-+
-+ do
-+ {
-+ li = inplace_sort_nextint(&lp);
-+ ri = inplace_sort_nextint(&rp);
-+ if (li > ri) return 1;
-+ if (ri > li) return -1;
-+ }
-+ while (li != -1 || ri != -1);
-+ return 0;
-+}
-+
-+#define skip(str) ((str) + grub_strlen (str) + 1)
-+
-+static void inplace_sort (char *str, int len);
-+
-+static void
-+inplace_sort (char *str, int len)
-+{
-+ int m, n = 0;
-+ char *s, *t;
-+
-+ /* we use x as temporary storage */
-+ char *x = str + len;
-+
-+ for (s = str; s < x; s = skip (s))
-+ n++;
-+
-+ for (; n >= 2; n--)
-+ {
-+ s = str;
-+ t = skip (s);
-+
-+ for (m = n; m >= 2; m--)
-+ {
-+ if (inplace_sort_strcmp (s, t) < 0)
-+ {
-+ int ls = skip (s) - s;
-+ int lt = skip (t) - t;
-+
-+ memcpy (x, s, ls);
-+ grub_memmove (s + ls, s + lt, t - (s + ls));
-+ memcpy (s, t, lt);
-+ t = t + lt - ls;
-+ memcpy (t, x, ls);
-+ }
-+ s = t;
-+ t = skip (t);
-+ }
-+ }
-+}
-+
-+#undef skip
-+
-+static int this_config_len (const char *config);
-+static int
-+this_config_len (const char *config)
-+{
-+ const char *c = config;
-+ while (*c)
-+ {
-+ while (*c)
-+ c++;
-+ c++;
-+ }
-+ c++;
-+ return c - config;
-+}
-+
-+static const char * expand_asterisks (const char *str, int *len,
-+ const char *subst);
-+
-+/* Expand all asterisks (*) in a menu entry or commands section with its
-+ substitution. Use a backslash as escape character. */
-+static const char *
-+expand_asterisks (const char *str, int *len, const char *subst)
-+{
-+ static char buffer[1024];
-+ char *b = buffer, escaped = 0;
-+ const char *end = str + *len;
-+
-+ while (str < end)
-+ {
-+ if (*str == '*' && !escaped)
-+ {
-+ if (b - buffer + grub_strlen (subst) > sizeof (buffer))
-+ {
-+ errnum = ERR_FILELENGTH;
-+ return NULL;
-+ }
-+ grub_strcpy (b, subst);
-+ b += grub_strlen (subst);
-+ }
-+ else if (*str == '\\' && !escaped)
-+ escaped = 1;
-+ else
-+ {
-+ escaped = 0;
-+ if (b - buffer + 1 > sizeof (buffer))
-+ {
-+ errnum = ERR_FILELENGTH;
-+ return NULL;
-+ }
-+ *b++ = *str;
-+ }
-+ str++;
-+ }
-+ *len = b - buffer;
-+
-+ return buffer;
-+}
-+
- /* This is the starting function in C. */
- void
- cmain (void)
-@@ -1262,6 +1486,97 @@
- menu_entries = (char *) MENU_BUF;
- init_config ();
- }
-+
-+ auto void expand_wildcard_entries (void);
-+ void expand_wildcard_entries (void)
-+ {
-+ char *config_entry = config_entries;
-+ char *menu_entry = menu_entries;
-+
-+ while (*menu_entry)
-+ {
-+ char *command = config_entry;
-+
-+ do
-+ {
-+ char *c = command;
-+ const char *w = "wildcard";
-+
-+ while (*w && *c == *w)
-+ {
-+ c++;
-+ w++;
-+ }
-+ if (*w == 0 && (*c == ' ' || *c == '\t' || *c == '='))
-+ {
-+ int len, wlen;
-+
-+ /* This is a wildcard command. Advance to the argument. */
-+ while (*c == ' ' || *c == '\t' || *c == '=')
-+ c++;
-+
-+ /* Expand wildcard entry. */
-+ w = wildcard (c, &wlen);
-+ if (w)
-+ inplace_sort (w, wlen);
-+
-+ /* Remove the wildcard command from the command section;
-+ it has no meaning beyond the wildcard expansion just
-+ performed. */
-+ len = grub_strlen (command) + 1;
-+ grub_memmove (command, command + len,
-+ config_len - (command - config_entries));
-+ config_len -= len;
-+
-+ while (w && wlen)
-+ {
-+ /* Insert expansion before the wildcard entry in the
-+ list of entry names. */
-+ len = grub_strlen (menu_entry) + 1;
-+ const char *x = expand_asterisks (menu_entry, &len, w);
-+ grub_memmove (menu_entry + len, menu_entry,
-+ menu_len - (menu_entry - menu_entries));
-+ memcpy (menu_entry, x, len);
-+ menu_entry += len;
-+ menu_len += len;
-+
-+ /* Insert expansion before the wildcard command section
-+ in the list of command sections. */
-+ len = this_config_len (config_entry);
-+ x = expand_asterisks (config_entry, &len, w);
-+ grub_memmove (config_entry + len, config_entry,
-+ config_len - (config_entry -
-+ config_entries));
-+ memcpy (config_entry, x, len);
-+ config_entry += len;
-+ config_len += len;
-+
-+ num_entries++;
-+ wlen -= grub_strlen (w) + 1;
-+ w += grub_strlen (w) + 1;
-+ }
-+
-+ /* Remove the wildcard command section; it has just
-+ been expanded. */
-+ len = grub_strlen (menu_entry) + 1;
-+ grub_memmove (menu_entry, menu_entry + len,
-+ menu_len - (menu_entry - menu_entries));
-+ menu_len -= len;
-+
-+ len = this_config_len(config_entry);
-+ grub_memmove (config_entry, config_entry + len,
-+ config_len - (config_entry - config_entries));
-+ config_len -= len;
-+
-+ num_entries--;
-+ }
-+ command += grub_strlen (command) + 1;
-+ }
-+ while (*command);
-+ menu_entry += grub_strlen (menu_entry) + 1;
-+ config_entry += this_config_len(config_entry);
-+ }
-+ }
-
- /* Initialize the environment for restarting Stage 2. */
- grub_setjmp (restart_env);
-@@ -1414,8 +1729,16 @@
- config_len = prev_config_len;
- }
-
-+ if (is_preset)
-+ close_preset_menu ();
-+ else
-+ grub_close ();
-+
- menu_entries[menu_len++] = 0;
- config_entries[config_len++] = 0;
-+
-+ expand_wildcard_entries();
-+
- grub_memmove (config_entries + config_len, menu_entries,
- menu_len);
- menu_entries = config_entries + config_len;
-@@ -1456,11 +1779,6 @@
- else
- default_entry = 0;
- }
--
-- if (is_preset)
-- close_preset_menu ();
-- else
-- grub_close ();
- }
- while (is_preset);
- }