@$(PREBUILD)
@rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar zxf $(DIR_DL)/$(DL_FILE)
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.97-disk_geometry-1.patch
- cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.95-graphics.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.90-append.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.90-symlinkmenulst.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.91-splashimagehelp.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.93-configfile.patch
+ cd $(DIR_APP) && patch -Np0 < $(DIR_SRC)/src/patches/grub-0.93-endedit.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.93-graphics-bootterm.patch
- cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.95-xpmjunk.patch
- cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.95-splash-error-term.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.93-special-device-names.patch
- cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.95-moreraid.patch
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.94-i2o.patch
- cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.97_grub-install_virtio.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.95-graphics.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.95-hiddenmenu-tweak.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.95-md.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.95-md-rework.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.95-md-mbr.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.95-moreraid.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.95-nonmbr.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.95-odirect.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.95-recheck-bad.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.95-staticcurses.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.95-xpmjunk.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.97-cmdline-size.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.97-datadir.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.97-dmraid.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.97-dmraid-partition-names.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.97-install.in.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.97-mactel-kbd.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.97-mpath.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.97-nxstack.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.97-nx-multiinstall.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.97-once.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.95-splash-error-term.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.94-installcopyonly.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.97-prototypes.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.97-stderr.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.97-bz429187-cciss.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.97-dmraid-recheck-bad.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.97-mdadm-path.patch
+
+ # XXX Does not work anymore
+ #cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.97_grub-install_virtio.patch
cd $(DIR_APP) && perl -pi -e 's,/usr/lib/grub/i386-pc,/usr/share/grub/i386-pc,' docs/grub.texi
cd $(DIR_APP) && sed -i 's/AM_INIT_AUTOMAKE/&\nAM_PROG_AS/' configure.ac
# grub files
mkdir -vp /boot/grub
- cp -v /usr/lib/grub/i386-pc/stage{1,2} /boot/grub
+ cp -v /usr/share/grub/i386-pc/stage{1,2} /boot/grub
for i in $(DIR_SRC)/config/grub/*; do \
[ -f $$i ] && cp -f $$i /boot/grub; \
done
--- /dev/null
+--- grub-0.90/stage2/stage2.c.append Thu Dec 20 08:20:48 2001
++++ grub-0.90/stage2/stage2.c Thu Dec 20 17:01:20 2001
+@@ -500,7 +500,8 @@
+ if (config_entries)
+ printf ("\
+ Press enter to boot the selected OS, \'e\' to edit the\n\
+- commands before booting, or \'c\' for a command-line.");
++ commands before booting, \'a\' to modify the kernel arguments\n\
++ before booting, or \'c\' for a command-line.");
+ else
+ printf ("\
+ Press \'b\' to boot, \'e\' to edit the selected command in the\n\
+@@ -787,6 +788,98 @@
+ enter_cmdline (heap, 0);
+ goto restart;
+ }
++ if (config_entries && c == 'a')
++ {
++ int new_num_entries = 0, i = 0, j;
++ int needs_padding, amount;
++ char *new_heap;
++ char * entries;
++ char * entry_copy;
++ char * append_line;
++ char * start;
++
++ entry_copy = new_heap = heap;
++ cur_entry = get_entry (config_entries, first_entry + entryno,
++ 1);
++
++ do
++ {
++ while ((*(new_heap++) = cur_entry[i++]) != 0);
++ new_num_entries++;
++ }
++ while (config_entries && cur_entry[i]);
++
++ /* this only needs to be done if config_entries is non-NULL,
++ but it doesn't hurt to do it always */
++ *(new_heap++) = 0;
++
++ new_heap = heap + NEW_HEAPSIZE + 1;
++
++ entries = entry_copy;
++ while (*entries)
++ {
++ if ((strstr(entries, "kernel") == entries) &&
++ isspace(entries[6]))
++ break;
++
++ while (*entries) entries++;
++ entries++;
++ }
++
++ if (!*entries)
++ goto restart;
++
++ start = entries + 6;
++
++ /* skip the white space */
++ while (*start && isspace(*start)) start++;
++ /* skip the kernel name */
++ while (*start && !isspace(*start)) start++;
++
++ /* skip the white space */
++ needs_padding = (!*start || !isspace(*start));
++ while (*start && isspace(*start)) start++;
++
++ append_line = new_heap;
++ grub_strcpy(append_line, start);
++
++ cls();
++ print_cmdline_message (CMDLINE_EDIT_MODE);
++
++ if (get_cmdline(PACKAGE " append> ",
++ append_line, NEW_HEAPSIZE + 1,
++ 0, 1))
++ goto restart;
++
++ /* have new args; append_line points to the
++ new args and start points to the old
++ args */
++
++ i = grub_strlen(start);
++ j = grub_strlen(append_line);
++
++ if (i > (j + needs_padding))
++ amount = i;
++ else
++ amount = j + needs_padding;
++
++ /* align rest of commands properly */
++ memmove (start + j + needs_padding, start + i,
++ ((int) append_line) - ((int) start) - (amount));
++
++ if (needs_padding)
++ *start = ' ';
++
++ /* copy command to correct area */
++ memmove (start + needs_padding, append_line, j);
++
++ /* set up this entry to boot */
++ config_entries = NULL;
++ cur_entry = entry_copy;
++ heap = new_heap;
++
++ break;
++ }
+ #ifdef GRUB_UTIL
+ if (c == 'q')
+ {
--- /dev/null
+Only in grub: ChangeLog~
+diff -ur grub-0.90/util/grub-install.in grub/util/grub-install.in
+--- grub-0.90/util/grub-install.in Wed Sep 5 15:50:06 2001
++++ grub/util/grub-install.in Wed Sep 5 15:50:24 2001
+@@ -320,6 +320,10 @@
+ exit 1
+ fi
+
++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 -x /bin/mktemp && log_file=`/bin/mktemp /tmp/grub-install.log.XXXXXX`
+
+Only in grub/util: grub-install.in.orig
--- /dev/null
+--- grub-0.93/stage2/asm.S.config 2002-12-02 18:18:56.000000000 -0500
++++ grub-0.93/stage2/asm.S 2002-12-28 22:01:24.000000000 -0500
+@@ -97,7 +97,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"
+--- grub-0.93/stage2/builtins.c.config 2002-12-03 23:41:57.000000000 -0500
++++ grub-0.93/stage2/builtins.c 2002-12-28 22:01:24.000000000 -0500
+@@ -3838,7 +3838,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. */
+--- grub-0.93/grub/asmstub.c.config 2002-12-02 18:20:45.000000000 -0500
++++ grub-0.93/grub/asmstub.c 2002-12-28 22:01:24.000000000 -0500
+@@ -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;
+--- grub-0.93/docs/grub.8.config 2002-12-07 22:17:59.000000000 -0500
++++ grub-0.93/docs/grub.8 2002-12-28 22:01:24.000000000 -0500
+@@ -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
+--- grub-0.93/docs/grub.texi.config 2002-12-02 17:35:28.000000000 -0500
++++ grub-0.93/docs/grub.texi 2002-12-28 22:01:24.000000000 -0500
+@@ -989,7 +989,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
+@@ -1596,8 +1596,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
+@@ -3249,7 +3249,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}
--- /dev/null
+Index: stage2/cmdline.c
+===================================================================
+RCS file: /cvsroot/grub/grub/stage2/cmdline.c,v
+retrieving revision 1.27
+diff -u -r1.27 cmdline.c
+--- stage2/cmdline.c 3 Dec 2002 00:02:53 -0000 1.27
++++ stage2/cmdline.c 6 Jan 2003 05:33:33 -0000
+@@ -48,12 +48,17 @@
+
+ /* Print a helpful message for the command-line interface. */
+ void
+-print_cmdline_message (int forever)
++print_cmdline_message (int type)
+ {
+ printf (" [ Minimal BASH-like line editing is supported. For the first word, TAB\n"
+ " lists possible command completions. Anywhere else TAB lists the possible\n"
+- " completions of a device/filename.%s ]\n",
+- (forever ? "" : " ESC at any time exits."));
++ " completions of a device/filename.");
++ if (type == CMDLINE_NORMAL_MODE)
++ printf(" ESC at any time exits.");
++ if (type == CMDLINE_EDIT_MODE)
++ printf(" ESC at any time cancels. ENTER \n"
++ " at any time accepts your changes.");
++ printf("]\n");
+ }
+
+ /* Find the builtin whose command name is COMMAND and return the
+@@ -128,7 +133,7 @@
+ print_network_configuration ();
+ grub_putchar ('\n');
+ #endif
+- print_cmdline_message (forever);
++ print_cmdline_message (forever ? CMDLINE_FOREVER_MODE : CMDLINE_NORMAL_MODE);
+
+ while (1)
+ {
+Index: stage2/shared.h
+===================================================================
+RCS file: /cvsroot/grub/grub/stage2/shared.h,v
+retrieving revision 1.90
+diff -u -r1.90 shared.h
+--- stage2/shared.h 3 Dec 2002 00:02:53 -0000 1.90
++++ stage2/shared.h 6 Jan 2003 05:33:33 -0000
+@@ -843,9 +843,15 @@
+ void init_config (void);
+ char *skip_to (int after_equal, char *cmdline);
+ struct builtin *find_command (char *command);
+-void print_cmdline_message (int forever);
+ void enter_cmdline (char *heap, int forever);
+ int run_script (char *script, char *heap);
++
++/* the flags for the cmdline message */
++#define CMDLINE_FOREVER_MODE 0x0
++#define CMDLINE_NORMAL_MODE 0x1
++#define CMDLINE_EDIT_MODE 0x2
++
++void print_cmdline_message (int type);
+ #endif
+
+ /* C library replacement functions with identical semantics. */
+Index: stage2/stage2.c
+===================================================================
+RCS file: /cvsroot/grub/grub/stage2/stage2.c,v
+retrieving revision 1.42
+diff -u -r1.42 stage2.c
+--- stage2/stage2.c 4 Dec 2002 00:55:45 -0000 1.42
++++ stage2/stage2.c 6 Jan 2003 05:33:33 -0000
+@@ -655,7 +655,7 @@
+ else
+ {
+ cls ();
+- print_cmdline_message (0);
++ print_cmdline_message (CMDLINE_EDIT_MODE);
+
+ new_heap = heap + NEW_HEAPSIZE + 1;
+
--- /dev/null
+--- grub-0.94/util/grub-install.in.copyonly 2004-02-02 16:33:29.172127985 -0500
++++ grub-0.94/util/grub-install.in 2004-02-02 16:34:26.027454320 -0500
+@@ -40,6 +40,7 @@
+ force_lba=
+ recheck=no
+ debug=no
++justcopy=no
+
+ # look for secure tempfile creation wrappers on this platform
+ if test -x /bin/tempfile; then
+@@ -221,6 +222,17 @@
+ echo "$tmp_fname"
+ }
+
++copy_images() {
++ # 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 \
++ ${pkgdatadir}/stage1 ${pkgdatadir}/stage2 ${pkgdatadir}/*stage1_5; do
++ cp -f $file ${grubdir} || exit 1
++ done
++}
++
+ # Check the arguments.
+ for option in "$@"; do
+ case "$option" in
+@@ -240,6 +252,8 @@
+ force_lba="--force-lba" ;;
+ --recheck)
+ recheck=yes ;;
++ --just-copy)
++ justcopy=yes ;;
+ # This is an undocumented feature...
+ --debug)
+ debug=yes ;;
+@@ -258,12 +272,6 @@
+ esac
+ done
+
+-if test "x$install_device" = x; then
+- echo "install_device not specified." 1>&2
+- usage
+- exit 1
+-fi
+-
+ # If the debugging feature is enabled, print commands.
+ if test $debug = yes; then
+ set -x
+@@ -286,6 +294,18 @@
+ grubdir=${bootdir}/grub
+ device_map=${grubdir}/device.map
+
++# if they just want the images copied, copy the images and then exit
++if test $justcopy = yes; then
++ copy_images
++ exit 0
++fi
++
++if test "x$install_device" = x; then
++ echo "install_device not specified." 1>&2
++ usage
++ exit 1
++fi
++
+ # Check if GRUB is installed.
+ # This is necessary, because the user can specify "grub --read-only".
+ set $grub_shell dummy
+@@ -317,14 +337,7 @@
+ test -d "$bootdir" || mkdir "$bootdir" || exit 1
+ test -d "$grubdir" || mkdir "$grubdir" || exit 1
+
+-# 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 \
+- ${pkgdatadir}/stage1 ${pkgdatadir}/stage2 ${pkgdatadir}/*stage1_5; do
+- cp -f $file ${grubdir} || exit 1
+-done
++copy_images
+
+ # If --recheck is specified, remove the device map, if present.
+ if test $recheck = yes; then
--- /dev/null
+--- grub-0.95/stage2/stage2.c.hidden 2004-09-30 16:39:38.028893664 -0400
++++ grub-0.95/stage2/stage2.c 2004-09-30 16:42:07.981097464 -0400
+@@ -235,6 +235,8 @@
+ char *cur_entry = 0;
+ struct term_entry *prev_term = NULL;
+
++ cls();
++
+ /*
+ * Main loop for menu UI.
+ */
+@@ -262,14 +264,16 @@
+ /* Get current time. */
+ while ((time1 = getrtsecs ()) == 0xFF)
+ ;
++ grub_printf("\rPress any key to enter the menu\n\n\n");
+
+ while (1)
+ {
+ /* Check if ESC is pressed. */
+- if (checkkey () != -1 && ASCII_CHAR (getkey ()) == '\e')
++ if (checkkey () != -1)
+ {
+ grub_timeout = -1;
+ show_menu = 1;
++ getkey ();
+ break;
+ }
+
+@@ -288,7 +292,8 @@
+ grub_timeout--;
+
+ /* Print a message. */
+- grub_printf ("\rPress `ESC' to enter the menu... %d ",
++ grub_printf ("\rBooting %s in %d seconds...",
++ get_entry(menu_entries, first_entry + entryno, 0),
+ grub_timeout);
+ }
+ }
--- /dev/null
+--- grub-0.95/util/grub-install.in.md-mbr 2005-02-20 17:56:48.000000000 -0500
++++ grub-0.95/util/grub-install.in 2005-02-20 17:57:12.000000000 -0500
+@@ -444,7 +444,7 @@
+ /dev/*)
+ install_device=`resolve_symlink "$install_device"`
+ for install_drive in `find_real_devs $install_device` ; do
+- install_drive=`convert $install_drive`
++ install_drive=`convert $install_drive | sed 's/,[0-9]*)/)/'`
+ if [ "x$install_drive" = "x" ]; then
+ exit 1
+ fi
--- /dev/null
+--- grub-0.95/util/grub-install.in.md2 2005-01-03 14:49:18.133866107 -0500
++++ grub-0.95/util/grub-install.in 2005-01-03 16:35:44.923732271 -0500
+@@ -35,6 +35,7 @@
+ rootdir=
+ grub_prefix=/boot/grub
+
++install_drives=
+ install_device=
+ no_floppy=
+ force_lba=
+@@ -272,6 +273,30 @@
+ done
+ }
+
++
++dump_boot_block () {
++ sync
++ $grub_shell --batch $no_floppy --device-map=$device_map <<EOF >$log_file
++dump ${root_drive}${tmp} ${img_file}
++quit
++EOF
++}
++
++
++install_boot_block () {
++ # Before all invocations of the grub shell, call sync to make sure
++ # the raw device is in sync with any bufferring in filesystems.
++ sync
++
++ # Now perform the installation.
++ $grub_shell --batch $no_floppy --device-map=$device_map <<EOF >>$log_file
++root $1
++setup $force_lba --stage2=$grubdir/stage2 --prefix=$grub_prefix $2
++quit
++EOF
++}
++
++
+ # Check the arguments.
+ for option in "$@"; do
+ case "$option" in
+@@ -416,28 +441,32 @@
+ # Check for INSTALL_DEVICE.
+ case "$install_device" in
+ /dev/*)
+- # If we are running md on a Linux box, just use the first physical device
+- # at this point.
+ install_device=`resolve_symlink "$install_device"`
+- install_device=`find_real_devs $install_device | awk '{print $1}'`
+-
+- install_drive=`convert "$install_device"`
+- # I don't know why, but some shells wouldn't die if exit is
+- # called in a function.
+- if test "x$install_drive" = x; then
++ for install_drive in `find_real_devs $install_device` ; do
++ install_drive=`convert $install_drive`
++ if [ "x$install_drive" = "x" ]; then
++ exit 1
++ fi
++ install_drives="${install_drives} ${install_drive}"
++ done
++ unset install_drive
++
++ if test "x$install_drives" = x ; then
+ exit 1
+ fi ;;
+ \([hf]d[0-9]*\))
+- install_drive="$install_device" ;;
++ install_drives="$install_device" ;;
+ [hf]d[0-9]*)
+ # The GRUB format with no parenthesis.
+- install_drive="($install_device)" ;;
++ install_drives="($install_device)" ;;
+ *)
+ echo "Format of install_device not recognized." 1>&2
+ usage
+ exit 1 ;;
+ esac
+
++unset install_device
++
+ # Get the root drive.
+ root_device=`find_device ${rootdir}`
+ bootdir_device=`find_device ${bootdir}`
+@@ -465,41 +494,39 @@
+ test -n "$mkimg" && img_file=`$mkimg`
+ test -n "$mklog" && log_file=`$mklog`
+
+-for real_device in `find_real_devs $root_device`; do
+- # Convert the root deviceto a GRUB drive.
+- root_drive=`convert "$real_device"`
+- if [ "x$root_drive" = x ]; then
+- exit 1
+- fi
++# There's not a real root device, so just pick the first
++if is_raid1_device $root_device ; then
++ root_device=`find_real_devs $root_device | awk '{print $1}'`
++fi
+
+- for file in ${grubdir}/stage1 ${grubdir}/stage2 ${grubdir}/*stage1_5; do
+- count=5
+- tmp=`echo $file | sed "s|^${grubdir}|${grub_prefix}|"`
+- while test $count -gt 0; do
+- sync
+- $grub_shell --batch $no_floppy --device-map=$device_map \
+- <<EOF >$log_file
+-dump ${root_drive}${tmp} ${img_file}
+-quit
+-EOF
+- if grep "Error [0-9]*: " $log_file >/dev/null; then
+- :
+- elif cmp $file $img_file >/dev/null; then
+- break
+- fi
+- sleep 1
+- count=`expr $count - 1`
+- done
+- if test $count -eq 0; then
+- echo "The file $file not read correctly." 1>&2
+- exit 1
+- fi
+- done
++# Convert the root deviceto a GRUB drive.
++root_drive=`convert "$root_device"`
++if [ "x$root_drive" = x ]; then
++ exit 1
++fi
+
+- rm -f $img_file
+- rm -f $log_file
++for file in ${grubdir}/stage1 ${grubdir}/stage2 ${grubdir}/*stage1_5; do
++ count=5
++ tmp=`echo $file | sed "s|^${grubdir}|${grub_prefix}|"`
++ while test $count -gt 0; do
++ dump_boot_block $root_drive $img_file
++ if grep "Error [0-9]*: " $log_file >/dev/null; then
++ :
++ elif cmp $file $img_file >/dev/null; then
++ break
++ fi
++ sleep 1
++ count=`expr $count - 1`
++ done
++ if test $count -eq 0; then
++ echo "The file $file not read correctly." 1>&2
++ exit 1
++ fi
+ done
+
++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
+@@ -507,24 +534,13 @@
+ # Create a safe temporary file.
+ test -n "$mklog" && log_file=`$mklog`
+
+-for real_device in `find_real_devs $root_device`; do
++for install_drive in $install_drives; do
+ # Convert the root deviceto a GRUB drive.
+- root_drive=`convert "$real_device"`
++ root_drive=`convert "$root_device"`
+ if [ "x$root_drive" = x ]; then
+ exit 1
+ fi
+-
+- # Before all invocations of the grub shell, call sync to make sure
+- # the raw device is in sync with any bufferring in filesystems.
+- sync
+-
+- # Now perform the installation.
+- $grub_shell --batch $no_floppy --device-map=$device_map <<EOF >>$log_file
+-root $root_drive
+-setup $force_lba --stage2=$grubdir/stage2 --prefix=$grub_prefix $root_drive
+-quit
+-EOF
+-
++ install_boot_block $root_drive $install_drive
+ done
+
+ if grep "Error [0-9]*: " $log_file >/dev/null ; then
--- /dev/null
+--- grub-0.95/util/grub-install.in.support_md 2004-12-17 17:50:45.000000000 -0500
++++ grub-0.95/util/grub-install.in 2004-12-19 19:19:20.509409160 -0500
+@@ -207,6 +207,43 @@
+ echo "$tmp_fname"
+ }
+
++# Usage: is_raid1_device devicename
++# Returns 0 if devicename is a raid1 md device, 1 if it is not.
++is_raid1_device () {
++ case "$host_os" in
++ linux*)
++ level=`mdadm --query --detail $1 2>/dev/null | \
++ awk '/Raid Level :/ {print $4}'`
++ if [ "$level" = "raid1" ]; then
++ return 0
++ fi
++ ;;
++ esac
++ return 1
++}
++
++# Usage: find_real_devs device
++# Returns space separated list of devices for linux if device is
++# a raid1 device. In all other cases, the provided value is returned.
++find_real_devs () {
++ source_device=$1
++ case "$host_os" in
++ linux*)
++ if is_raid1_device $source_device ; then
++ list=""
++ for device in `mdadm --query --detail "${source_device}" | \
++ awk '/\/dev\/[^(md)]/ {print $7}'` ; do
++ list="$list $device"
++ done
++ echo $list
++ return 0
++ fi
++ ;;
++ esac
++ echo $source_device
++ return 0
++}
++
+ # Usage: find_device file
+ # Find block device on which the file resides.
+ find_device () {
+@@ -219,7 +256,7 @@
+ exit 1
+ fi
+
+- tmp_fname=`resolve_symlink $tmp_fname`
++ tmp_fname=`resolve_symlink $tmp_fname`
+
+ echo "$tmp_fname"
+ }
+@@ -379,7 +416,11 @@
+ # Check for INSTALL_DEVICE.
+ case "$install_device" in
+ /dev/*)
++ # If we are running md on a Linux box, just use the first physical device
++ # at this point.
+ install_device=`resolve_symlink "$install_device"`
++ install_device=`find_real_devs $install_device | awk '{print $1}'`
++
+ install_drive=`convert "$install_device"`
+ # I don't know why, but some shells wouldn't die if exit is
+ # called in a function.
+@@ -408,14 +449,7 @@
+ grub_prefix="/grub"
+ fi
+
+-# Convert the root device to a GRUB drive.
+-root_drive=`convert "$root_device"`
+-if test "x$root_drive" = x; then
+- exit 1
+-fi
+-
+-# Check if the root directory exists in the same device as the grub
+-# directory.
++# Check if the root directory exists in the same device as the grub directory.
+ grubdir_device=`find_device ${grubdir}`
+
+ if test "x$grubdir_device" != "x$root_device"; then
+@@ -431,30 +465,40 @@
+ test -n "$mkimg" && img_file=`$mkimg`
+ test -n "$mklog" && log_file=`$mklog`
+
+-for file in ${grubdir}/stage1 ${grubdir}/stage2 ${grubdir}/*stage1_5; do
+- count=5
+- tmp=`echo $file | sed "s|^${grubdir}|${grub_prefix}|"`
+- while test $count -gt 0; do
+- $grub_shell --batch $no_floppy --device-map=$device_map <<EOF >$log_file
++for real_device in `find_real_devs $root_device`; do
++ # Convert the root deviceto a GRUB drive.
++ root_drive=`convert "$real_device"`
++ if [ "x$root_drive" = x ]; then
++ exit 1
++ fi
++
++ for file in ${grubdir}/stage1 ${grubdir}/stage2 ${grubdir}/*stage1_5; do
++ count=5
++ tmp=`echo $file | sed "s|^${grubdir}|${grub_prefix}|"`
++ while test $count -gt 0; do
++ sync
++ $grub_shell --batch $no_floppy --device-map=$device_map \
++ <<EOF >$log_file
+ dump ${root_drive}${tmp} ${img_file}
+ quit
+ EOF
+- if grep "Error [0-9]*: " $log_file >/dev/null; then
+- :
+- elif cmp $file $img_file >/dev/null; then
+- break
++ if grep "Error [0-9]*: " $log_file >/dev/null; then
++ :
++ elif cmp $file $img_file >/dev/null; then
++ break
++ fi
++ sleep 1
++ count=`expr $count - 1`
++ done
++ if test $count -eq 0; then
++ echo "The file $file not read correctly." 1>&2
++ exit 1
+ fi
+- sleep 1
+- count=`expr $count - 1`
+ done
+- if test $count -eq 0; then
+- echo "The file $file not read correctly." 1>&2
+- exit 1
+- fi
+-done
+
+-rm -f $img_file
+-rm -f $log_file
++ rm -f $img_file
++ rm -f $log_file
++done
+
+ if ! test -e ${grubdir}/grub.conf ; then
+ test -e ${grubdir}/menu.lst && ln -s ./menu.lst ${grubdir}/grub.conf
+@@ -463,21 +507,33 @@
+ # Create a safe temporary file.
+ test -n "$mklog" && log_file=`$mklog`
+
+-# Before all invocations of the grub shell, call sync to make sure
+-# the raw device is in sync with any bufferring in filesystems.
+-sync
++for real_device in `find_real_devs $root_device`; do
++ # Convert the root deviceto a GRUB drive.
++ root_drive=`convert "$real_device"`
++ if [ "x$root_drive" = x ]; then
++ exit 1
++ fi
++
++ # Before all invocations of the grub shell, call sync to make sure
++ # the raw device is in sync with any bufferring in filesystems.
++ sync
+
+-# Now perform the installation.
+-$grub_shell --batch $no_floppy --device-map=$device_map <<EOF >$log_file
++ # Now perform the installation.
++ $grub_shell --batch $no_floppy --device-map=$device_map <<EOF >>$log_file
+ root $root_drive
+-setup $force_lba --stage2=$grubdir/stage2 --prefix=$grub_prefix $install_drive
++setup $force_lba --stage2=$grubdir/stage2 --prefix=$grub_prefix $root_drive
+ quit
+ EOF
+
+-if grep "Error [0-9]*: " $log_file >/dev/null || test $debug = yes; then
++done
++
++if grep "Error [0-9]*: " $log_file >/dev/null ; then
+ cat $log_file 1>&2
+ exit 1
+ fi
++if test $debug = yes; then
++ cat $log_file 1>&2
++fi
+
+ rm -f $log_file
+
--- /dev/null
+--- grub-0.95/util/grub-install.in.nonmbr 2005-03-16 10:02:50.000000000 -0500
++++ grub-0.95/util/grub-install.in 2005-03-16 10:02:13.000000000 -0500
+@@ -444,7 +444,10 @@
+ /dev/*)
+ install_device=`resolve_symlink "$install_device"`
+ for install_drive in `find_real_devs $install_device` ; do
+- install_drive=`convert $install_drive | sed 's/,[0-9]*)/)/'`
++ install_drive=`convert $install_drive`
++ if is_raid1_device $install_device; then
++ install_drive=`echo $install_drive | sed 's/,[0-9]*)/)/'`
++ fi
+ if [ "x$install_drive" = "x" ]; then
+ exit 1
+ fi
--- /dev/null
+--- grub-0.95/grub/asmstub.c.odirect 2004-11-30 16:58:06.577019488 -0500
++++ grub-0.95/grub/asmstub.c 2004-11-30 16:59:56.057375944 -0500
+@@ -53,6 +53,9 @@
+ # ifndef BLKFLSBUF
+ # define BLKFLSBUF _IO (0x12,97) /* flush buffer cache */
+ # endif /* ! BLKFLSBUF */
++# ifndef O_DIRECT
++# define O_DIRECT 040000
++# endif /* ! O_DIRECT */
+ #endif /* __linux__ */
+
+ /* We want to prevent any circularararity in our stubs, as well as
+@@ -764,7 +767,7 @@
+ {
+ /* The unpartitioned device name: /dev/XdX */
+ char *devname = device_map[drive];
+- char buf[512];
++ char * buf, * buf_unaligned;
+
+ if (! devname)
+ return -1;
+@@ -775,13 +778,13 @@
+
+ /* Open read/write, or read-only if that failed. */
+ if (! read_only)
+- disks[drive].flags = open (devname, O_RDWR);
++ disks[drive].flags = open (devname, O_RDWR | O_DIRECT);
+
+ if (disks[drive].flags == -1)
+ {
+ if (read_only || errno == EACCES || errno == EROFS || errno == EPERM)
+ {
+- disks[drive].flags = open (devname, O_RDONLY);
++ disks[drive].flags = open (devname, O_RDONLY | O_DIRECT);
+ if (disks[drive].flags == -1)
+ {
+ assign_device_name (drive, 0);
+@@ -795,6 +798,10 @@
+ }
+ }
+
++ buf_unaligned = malloc((512 * sizeof(char)) + 4095);
++ buf = (char *) (((unsigned long)buf_unaligned + 4096 - 1) &
++ (~(4096-1)));
++
+ /* Attempt to read the first sector. */
+ if (read (disks[drive].flags, buf, 512) != 512)
+ {
+@@ -806,6 +813,7 @@
+
+ if (disks[drive].flags != -1)
+ get_drive_geometry (&disks[drive], device_map, drive);
++ free(buf_unaligned);
+ }
+
+ if (disks[drive].flags == -1)
+@@ -827,24 +835,34 @@
+ nread (int fd, char *buf, size_t len)
+ {
+ int size = len;
++ char * buf_unaligned, * buff, * obuff;
++ int ret;
++
++ buf_unaligned = malloc((len * sizeof(char)) + 4095);
++ obuff = buff = (char *) (((unsigned long)buf_unaligned + 4096 - 1) &
++ (~(4096-1)));
++
+
+ while (len)
+ {
+- int ret = read (fd, buf, len);
++ ret = read (fd, buff, len);
+
+ if (ret <= 0)
+ {
+ if (errno == EINTR)
+ continue;
+ else
+- return ret;
++ break;
+ }
+
+ len -= ret;
+- buf += ret;
++ buff += ret;
+ }
+
+- return size;
++ if (!len) ret = size;
++
++ buf = memcpy(buf, obuff, size);
++ return ret;
+ }
+
+ /* Write LEN bytes from BUF to FD. Return less than or equal to zero if an
+@@ -853,10 +871,18 @@
+ nwrite (int fd, char *buf, size_t len)
+ {
+ int size = len;
++ char * buf_unaligned, * buff;
++
++ buf_unaligned = malloc((len * sizeof(char)) + 4095);
++ buff = (char *) (((unsigned long)buf_unaligned + 4096 - 1) &
++ (~(4096-1)));
+
+ while (len)
+ {
+- int ret = write (fd, buf, len);
++ int ret;
++
++ memcpy(buff, buf, len);
++ ret = write (fd, buff, len);
+
+ if (ret <= 0)
+ {
--- /dev/null
+--- grub-0.95/docs/grub.texi.recheck-bad 2005-07-25 17:55:57.000000000 -0400
++++ grub-0.95/docs/grub.texi 2005-07-25 17:58:00.000000000 -0400
+@@ -3417,8 +3417,9 @@
+
+ @item --recheck
+ Recheck the device map, even if @file{/boot/grub/device.map} already
+-exists. You should use this option whenever you add/remove a disk
+-into/from your computer.
++exists.
++
++This option is unreliable and its use is strongly discouraged.
+ @end table
+
+
+--- grub-0.95/util/grub-install.in.recheck-bad 2005-07-25 17:58:19.000000000 -0400
++++ grub-0.95/util/grub-install.in 2005-07-25 18:05:14.000000000 -0400
+@@ -68,6 +68,8 @@
+ --force-lba force GRUB to use LBA mode even for a buggy
+ BIOS
+ --recheck probe a device map even if it already exists
++ This flag is unreliable and its use is
++ strongly discouraged.
+
+ INSTALL_DEVICE can be a GRUB device name or a system device filename.
+
+@@ -328,7 +330,7 @@
+
+ # If --recheck is specified, remove the device map, if present.
+ if test $recheck = yes; then
+- rm -f $device_map
++ mv $device_map ${device_map}.backup
+ fi
+
+ # Create the device map file if it is not present.
+@@ -357,7 +359,22 @@
+ tmp=`sed -n '/^([fh]d[0-9]*)/s/\(^(.*)\).*/\1/p' $device_map \
+ | sort | uniq -d | sed -n 1p`
+ if test -n "$tmp"; then
+- echo "The drive $tmp is defined multiple times in the device map $device_map" 1>&2
++ echo "The drive $tmp is defined multiple times in the new device map." 1>&2
++ if test $recheck = yes; then
++ echo "Reverting to backed up copy." 1>&2
++ mv ${device_map}.backup $device_map
++ fi
++ exit 1
++fi
++
++# Make sure device.map has at least one hd device
++grep -q "^(hd[0-9]\+)" $device_map
++if [ "x$?" != "x0" ]; then
++ echo "No suitable drive was found in the generated device map." 1>&2
++ if test $recheck = yes; then
++ echo "Reverting to backed up copy." 1>&2
++ mv ${device_map}.backup $device_map
++ fi
+ exit 1
+ fi
+
+--- grub-0.95/docs/grub-install.8.recheck-bad 2004-06-13 13:44:59.000000000 -0400
++++ grub-0.95/docs/grub-install.8 2005-07-25 18:15:02.000000000 -0400
+@@ -30,6 +30,8 @@
+ .TP
+ \fB\-\-recheck\fR
+ probe a device map even if it already exists
++
++This option is unreliable and its use is strongly discouraged.
+ .PP
+ INSTALL_DEVICE can be a GRUB device name or a system device filename.
+ .SH "REPORTING BUGS"
+--- grub-0.95/docs/grub.info.recheck-bad 2004-05-11 08:22:54.000000000 -0400
++++ grub-0.95/docs/grub.info 2005-07-25 18:16:09.000000000 -0400
+@@ -3373,9 +3373,9 @@
+
+ `--recheck'
+ Recheck the device map, even if `/boot/grub/device.map' already
+- exists. You should use this option whenever you add/remove a disk
+- into/from your computer.
++ exists.
+
++ This option is unreliable and its use is strongly discouraged.
+ \1f
+ File: grub.info, Node: Invoking grub-md5-crypt, Next: Invoking grub-terminfo, Prev: Invoking grub-install, Up: Top
+
--- /dev/null
+--- grub-0.95/configure.ac.static 2004-06-13 13:38:17.000000000 -0400
++++ grub-0.95/configure.ac 2004-06-18 17:35:23.513374336 -0400
+@@ -207,9 +207,9 @@
+
+ # Unless the user specify --without-curses, check for curses.
+ if test "x$with_curses" != "xno"; then
+- AC_CHECK_LIB(ncurses, wgetch, [GRUB_LIBS="$GRUB_LIBS -lncurses"
++ AC_CHECK_LIB(ncurses, wgetch, [GRUB_LIBS="$GRUB_LIBS -Wl,-Bstatic -lncurses -Wl,-Bdynamic"
+ AC_DEFINE(HAVE_LIBCURSES, 1, [Define if you have a curses library])],
+- [AC_CHECK_LIB(curses, wgetch, [GRUB_LIBS="$GRUB_LIBS -lcurses"
++ [AC_CHECK_LIB(curses, wgetch, [GRUB_LIBS="$GRUB_LIBS -Wl,-Bstatic -lcurses -Wl,-Bdynamic"
+ AC_DEFINE(HAVE_LIBCURSES, 1, [Define if you have a curses library])])])
+ fi
+
--- /dev/null
+diff -up grub-0.97/util/grub-install.in.cciss grub-0.97/util/grub-install.in
+--- grub-0.97/util/grub-install.in.cciss 2008-02-04 14:30:31.000000000 -0500
++++ grub-0.97/util/grub-install.in 2008-02-07 18:34:14.000000000 -0500
+@@ -100,25 +100,56 @@ convert () {
+ # Break the device name into the disk part and the partition part.
+ case "$host_os" in
+ linux*)
++ # formats that need to be handled (disk name -> partition name):
++ # floppies: /dev/fd0
++ # normal sd/hd devices: /dev/hda -> /dev/hda3
++ # md: /dev/md0 -> /dev/md0p0
++ # ide raid devs: /dev/ide/host0/bus0/target0/lun0/disc
++ # -> /dev/ide/host0/bus0/target0/lun0/part1
++ # cciss: /dev/cciss/c0d0 -> /dev/cciss/c0d0p1
++ # mpath devs: /dev/mapper/mpath0 -> /dev/mapper/mpath0p1
++ # /dev/mapper/lalala -> /dev/mapper/lalalap1
++ # dmraid devs: /dev/mapper/via_abcdef -> /dev/mapper/via_abcdefp1
++ # /dev/mapper/isw_Volume0_abcdef -> /dev/mapper/isw_Volume0_abcdefp1
++ # the known list (to me) is (X means we should handle it):
++ # X asr_[unfettered crap]
++ # hpt[0-9]+x_[0-9]+-[0-9]+
++ # X hpt[0-9]+x_[0-9]+
++ # hpt[0-9]+x_SPARE
++ # isw_[a-z]+_[a-z]+[0-9]+
++ # X isw_[a-z]+
++ # jm_[0-9]+-[0-9]+
++ # X jm_[0-9]+
++ # lsi_[0-9]+-[0-9]+
++ # X lsi_[0-9]+
++ # nvidia_[a-z]+-[0-9]+
++ # X nvidia_[a-z]+
++ # pdc_[a-z]+-[0-9]+
++ # X pdc_[a-z]+
++ # sil_[0-9]+-[0-9]+
++ # X sil_[0-9]+
++ # via_[a-z]+-[0-9]+
++ # X via_[a-z]+
++ #
++ # more?
+ tmp_disk=`echo "$1" | grep -v '/mapper/control$' |
+- grep -v '/mapper/[[:alnum:]]\+-[[:alnum:]]\+$' | uniq |
++ grep -v '/mapper/[[:alnum:]_]\+-[[:digit:]]\+$' | uniq |
+ sed -e 's%\([sh]d[a-z]\)[0-9]*$%\1%' \
+- -e 's%\(d[0-9]*\)p[0-9]*$%\1%' \
+- -e 's%\(fd[0-9]*\)$%\1%' \
+- -e 's%/part[0-9]*$%/disc%' \
+- -e 's%\(c[0-7]d[0-9]*\).*$%\1%' \
+- -e 's%\(/mapper/[[:alpha:]]\+[[:digit:]]\+\)p[[:digit:]]\+$%\1%' \
+- -e 's%\(/mapper/[[:alpha:]]\+_[[:alpha:]]\+\)[[:digit:]]\+$%\1%'`
++ -e 's%\(/c[0-9]\+d[0-9]\+\).*$%\1%' \
++ -e 's%\(fd[0-9]*\)$%\1%' \
++ -e 's%/part[0-9]*$%/disc%' \
++ -e 's%\(/mapper/[[:alnum:]_-]\+\)\+p[[:digit:]]\+$%\1%'\
++ -e 's%\(/mapper/[[:alnum:]]\+\(_[[:alnum:]]\+\)\+\)\p[[:digit:]]\+$%\1%'`
+ tmp_part=`echo "$1" | grep -v '/mapper/control$' |
+- grep -v '/mapper/[[:alnum:]]\+-[[:alnum:]]\+$' | uniq |
++ grep -v '/mapper/[[:alnum:]_]\+-[[:digit:]]\+$' | uniq |
+ sed -e 's%.*/[sh]d[a-z]\([0-9]*\)$%\1%' \
+- -e 's%.*d[0-9]*p%%' \
+- -e 's%.*/fd[0-9]*$%%' \
+- -e 's%.*/floppy/[0-9]*$%%' \
+- -e 's%.*/\(disc\|part\([0-9]*\)\)$%\2%' \
+- -e 's%.*c[0-7]d[0-9]*p%%' \
+- -e 's%.*/mapper/[[:alpha:]]\+[[:digit:]]\+p\([[:digit:]]\+\)$%\1%' \
+- -e 's%.*/mapper/[[:alpha:]]\+_[[:alpha:]]\+\([[:digit:]]\+\)$%\1%' |
++ -e 's%.*/c[0-9]\+d[0-9]\+p\([[:digit:]]\+\)%\1%' \
++ -e 's%.*/c[0-9]\+d[0-9]\+$%%' \
++ -e 's%.*/fd[0-9]\+$%%' \
++ -e 's%.*/floppy/[0-9]*$%%' \
++ -e 's%.*/\(disc\|part\([0-9]*\)\)$%\2%' \
++ -e 's%.*/mapper/[[:alpha:]]\+[[:digit:]]\+p\([[:digit:]]\+\)$%\1%' \
++ -e 's%.*/mapper/[[:alnum:]]\+\(_[[:alpha:]]\+[[:digit:]]*\)\+p\([[:digit:]]\+\)$%\2%' |
+ grep -v '.*/mapper/.*'`
+ ;;
+ gnu*)
--- /dev/null
+diff --git a/stage2/boot.c b/stage2/boot.c
+index bf442e1..a6872e0 100644
+--- a/stage2/boot.c
++++ b/stage2/boot.c
+@@ -241,6 +241,7 @@ load_image (char *kernel, char *arg, kernel_t suggested_type,
+ }
+
+ if (lh->version >= 0x0202)
++ /* version 0x0202 and higher can handle 4096 */
+ lh->cmd_line_ptr = linux_data_real_addr + LINUX_CL_OFFSET;
+ else
+ {
+@@ -403,8 +404,10 @@ load_image (char *kernel, char *arg, kernel_t suggested_type,
+ {
+ char *src = skip_to (0, arg);
+ char *dest = linux_data_tmp_addr + LINUX_CL_OFFSET;
+-
+- while (dest < linux_data_tmp_addr + LINUX_CL_END_OFFSET && *src)
++ unsigned long cl_end_offset = lh->version < 0x0202 ?
++ LINUX_CL_END_OFFSET : LINUX_CL_END_OFFSET_202;
++
++ while (dest < linux_data_tmp_addr + cl_end_offset && *src)
+ *(dest++) = *(src++);
+
+ /* Old Linux kernels have problems determining the amount of
+diff --git a/stage2/shared.h b/stage2/shared.h
+index d05644b..c052480 100644
+--- a/stage2/shared.h
++++ b/stage2/shared.h
+@@ -160,10 +160,13 @@ extern void *grub_scratch_mem;
+ #define LINUX_VID_MODE_ASK 0xFFFD
+
+ #define LINUX_CL_OFFSET 0x9000
+-#define LINUX_CL_END_OFFSET 0x90FF
+-#define LINUX_SETUP_MOVE_SIZE 0x9100
+ #define LINUX_CL_MAGIC 0xA33F
+
++#define LINUX_CL_END_OFFSET 0x90FF
++#define LINUX_CL_END_OFFSET_202 0x9FFF /* version 0x0202 or higher */
++#define LINUX_SETUP_MOVE_SIZE 0xA000 /* where am I putting it? */
++
++
+ /*
+ * General disk stuff
+ */
--- /dev/null
+--- grub-0.97/stage1/Makefile.am.datadir 2005-12-14 11:07:01.000000000 -0500
++++ grub-0.97/stage1/Makefile.am 2005-12-14 11:07:21.000000000 -0500
+@@ -1,7 +1,7 @@
+-pkglibdir = $(libdir)/$(PACKAGE)/$(host_cpu)-$(host_vendor)
+-nodist_pkglib_DATA = stage1
++pkgdatadir = $(datadir)/$(PACKAGE)/$(host_cpu)-$(host_vendor)
++nodist_pkgdata_DATA = stage1
+
+-CLEANFILES = $(nodist_pkglib_DATA)
++CLEANFILES = $(nodist_pkgdata_DATA)
+
+ # We can't use builtins or standard includes.
+ AM_CCASFLAGS = $(STAGE1_CFLAGS) -fno-builtin -nostdinc
+--- grub-0.97/stage1/Makefile.in.datadir 2005-05-07 22:42:36.000000000 -0400
++++ grub-0.97/stage1/Makefile.in 2005-12-14 11:08:13.000000000 -0500
+@@ -1,8 +1,8 @@
+-# Makefile.in generated by automake 1.9.4 from Makefile.am.
++# Makefile.in generated by automake 1.9.6 from Makefile.am.
+ # @configure_input@
+
+ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+-# 2003, 2004 Free Software Foundation, Inc.
++# 2003, 2004, 2005 Free Software Foundation, Inc.
+ # This Makefile.in is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+ # with or without modifications, as long as this notice is preserved.
+@@ -15,8 +15,6 @@
+ @SET_MAKE@
+
+
+-SOURCES = $(stage1_exec_SOURCES)
+-
+ srcdir = @srcdir@
+ top_srcdir = @top_srcdir@
+ VPATH = @srcdir@
+@@ -67,13 +65,13 @@
+ *) f=$$p;; \
+ esac;
+ am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+-am__installdirs = "$(DESTDIR)$(pkglibdir)"
+-nodist_pkglibDATA_INSTALL = $(INSTALL_DATA)
+-DATA = $(nodist_pkglib_DATA)
++am__installdirs = "$(DESTDIR)$(pkgdatadir)"
++nodist_pkgdataDATA_INSTALL = $(INSTALL_DATA)
++DATA = $(nodist_pkgdata_DATA)
+ ETAGS = etags
+ CTAGS = ctags
+ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+-pkglibdir = $(libdir)/$(PACKAGE)/$(host_cpu)-$(host_vendor)
++pkgdatadir = $(datadir)/$(PACKAGE)/$(host_cpu)-$(host_vendor)
+ ACLOCAL = @ACLOCAL@
+ AMDEP_FALSE = @AMDEP_FALSE@
+ AMDEP_TRUE = @AMDEP_TRUE@
+@@ -102,6 +100,8 @@
+ EGREP = @EGREP@
+ EXEEXT = @EXEEXT@
+ FSYS_CFLAGS = @FSYS_CFLAGS@
++GRAPHICS_SUPPORT_FALSE = @GRAPHICS_SUPPORT_FALSE@
++GRAPHICS_SUPPORT_TRUE = @GRAPHICS_SUPPORT_TRUE@
+ GRUB_CFLAGS = @GRUB_CFLAGS@
+ GRUB_LIBS = @GRUB_LIBS@
+ HERCULES_SUPPORT_FALSE = @HERCULES_SUPPORT_FALSE@
+@@ -172,6 +172,7 @@
+ infodir = @infodir@
+ install_sh = @install_sh@
+ libdir = @libdir@
++datadir = @datadir@
+ libexecdir = @libexecdir@
+ localstatedir = @localstatedir@
+ mandir = @mandir@
+@@ -183,8 +184,8 @@
+ sharedstatedir = @sharedstatedir@
+ sysconfdir = @sysconfdir@
+ target_alias = @target_alias@
+-nodist_pkglib_DATA = stage1
+-CLEANFILES = $(nodist_pkglib_DATA)
++nodist_pkgdata_DATA = stage1
++CLEANFILES = $(nodist_pkgdata_DATA)
+
+ # We can't use builtins or standard includes.
+ AM_CCASFLAGS = $(STAGE1_CFLAGS) -fno-builtin -nostdinc
+@@ -242,22 +243,22 @@
+ .S.obj:
+ $(CCASCOMPILE) -c `$(CYGPATH_W) '$<'`
+ uninstall-info-am:
+-install-nodist_pkglibDATA: $(nodist_pkglib_DATA)
++install-nodist_pkgdataDATA: $(nodist_pkgdata_DATA)
+ @$(NORMAL_INSTALL)
+- test -z "$(pkglibdir)" || $(mkdir_p) "$(DESTDIR)$(pkglibdir)"
+- @list='$(nodist_pkglib_DATA)'; for p in $$list; do \
++ test -z "$(pkgdatadir)" || $(mkdir_p) "$(DESTDIR)$(pkgdatadir)"
++ @list='$(nodist_pkgdata_DATA)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+- echo " $(nodist_pkglibDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(pkglibdir)/$$f'"; \
+- $(nodist_pkglibDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(pkglibdir)/$$f"; \
++ echo " $(nodist_pkgdataDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(pkgdatadir)/$$f'"; \
++ $(nodist_pkgdataDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(pkgdatadir)/$$f"; \
+ done
+
+-uninstall-nodist_pkglibDATA:
++uninstall-nodist_pkgdataDATA:
+ @$(NORMAL_UNINSTALL)
+- @list='$(nodist_pkglib_DATA)'; for p in $$list; do \
++ @list='$(nodist_pkgdata_DATA)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+- echo " rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \
+- rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \
++ echo " rm -f '$(DESTDIR)$(pkgdatadir)/$$f'"; \
++ rm -f "$(DESTDIR)$(pkgdatadir)/$$f"; \
+ done
+
+ ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+@@ -339,7 +340,7 @@
+ check: check-am
+ all-am: Makefile $(PROGRAMS) $(DATA)
+ installdirs:
+- for dir in "$(DESTDIR)$(pkglibdir)"; do \
++ for dir in "$(DESTDIR)$(pkgdatadir)"; do \
+ test -z "$$dir" || $(mkdir_p) "$$dir"; \
+ done
+ install: install-am
+@@ -388,7 +389,7 @@
+
+ install-data-am:
+
+-install-exec-am: install-nodist_pkglibDATA
++install-exec-am: install-nodist_pkgdataDATA
+
+ install-info: install-info-am
+
+@@ -412,19 +413,19 @@
+
+ ps-am:
+
+-uninstall-am: uninstall-info-am uninstall-nodist_pkglibDATA
++uninstall-am: uninstall-info-am uninstall-nodist_pkgdataDATA
+
+ .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-noinstPROGRAMS ctags distclean distclean-compile \
+ distclean-generic distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-exec install-exec-am install-info \
+- install-info-am install-man install-nodist_pkglibDATA \
++ install-info-am install-man install-nodist_pkgdataDATA \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-info-am \
+- uninstall-nodist_pkglibDATA
++ uninstall-nodist_pkgdataDATA
+
+ .exec:
+ $(OBJCOPY) -O binary $< $@
+--- grub-0.97/util/grub-install.in.datadir 2005-12-14 11:00:21.000000000 -0500
++++ grub-0.97/util/grub-install.in 2005-12-14 11:00:21.000000000 -0500
+@@ -21,13 +21,13 @@
+ prefix=@prefix@
+ exec_prefix=@exec_prefix@
+ sbindir=@sbindir@
+-libdir=@libdir@
++datadir=@datadir@
+ PACKAGE=@PACKAGE@
+ VERSION=@VERSION@
+ host_cpu=@host_cpu@
+ host_os=@host_os@
+ host_vendor=@host_vendor@
+-pkglibdir=${libdir}/${PACKAGE}/${host_cpu}-${host_vendor}
++pkgdatadir=${datadir}/${PACKAGE}/${host_cpu}-${host_vendor}
+
+ grub_shell=${sbindir}/grub
+ mdadm=${sbindir}/mdadm
+@@ -388,17 +388,17 @@
+ exit 1
+ fi
+
+-if test -f "$pkglibdir/stage1"; then
++if test -f "$pkgdatadir/stage1"; then
+ :
+ else
+- echo "${pkglibdir}/stage1: Not found." 1>&2
++ echo "${pkgdatadir}/stage1: Not found." 1>&2
+ exit 1
+ fi
+
+-if test -f "$pkglibdir/stage2"; then
++if test -f "$pkgdatadir/stage2"; then
+ :
+ else
+- echo "${pkglibdir}/stage2: Not found." 1>&2
++ echo "${pkgdatadir}/stage2: Not found." 1>&2
+ exit 1
+ fi
+
+--- grub-0.97/stage2/Makefile.am.datadir 2005-12-14 11:03:54.000000000 -0500
++++ grub-0.97/stage2/Makefile.am 2005-12-14 11:05:04.000000000 -0500
+@@ -27,12 +27,12 @@
+ -DUSE_MD5_PASSWORDS=1 -DSUPPORT_SERIAL=1 -DSUPPORT_HERCULES=1
+
+ # Stage 2 and Stage 1.5's.
+-pkglibdir = $(libdir)/$(PACKAGE)/$(host_cpu)-$(host_vendor)
++pkgdatadir = $(datadir)/$(PACKAGE)/$(host_cpu)-$(host_vendor)
+
+ EXTRA_PROGRAMS = nbloader.exec pxeloader.exec diskless.exec
+
+ if DISKLESS_SUPPORT
+-pkglib_DATA = stage2 stage2_eltorito e2fs_stage1_5 fat_stage1_5 \
++pkgdata_DATA = stage2 stage2_eltorito e2fs_stage1_5 fat_stage1_5 \
+ ffs_stage1_5 iso9660_stage1_5 jfs_stage1_5 minix_stage1_5 \
+ reiserfs_stage1_5 ufs2_stage1_5 vstafs_stage1_5 xfs_stage1_5 \
+ nbgrub pxegrub
+@@ -43,7 +43,7 @@
+ reiserfs_stage1_5.exec ufs2_stage1_5.exec vstafs_stage1_5.exec \
+ xfs_stage1_5.exec nbloader.exec pxeloader.exec diskless.exec
+ else
+-pkglib_DATA = stage2 stage2_eltorito e2fs_stage1_5 fat_stage1_5 \
++pkgdata_DATA = stage2 stage2_eltorito e2fs_stage1_5 fat_stage1_5 \
+ ffs_stage1_5 iso9660_stage1_5 jfs_stage1_5 minix_stage1_5 \
+ reiserfs_stage1_5 ufs2_stage1_5 vstafs_stage1_5 xfs_stage1_5
+ noinst_DATA = pre_stage2 start start_eltorito
+@@ -112,7 +112,7 @@
+ BUILT_SOURCES = stage2_size.h
+ endif
+
+-CLEANFILES = $(pkglib_DATA) $(noinst_DATA) $(BUILT_SOURCES)
++CLEANFILES = $(pkgdata_DATA) $(noinst_DATA) $(BUILT_SOURCES)
+
+ stage2_size.h: pre_stage2
+ -rm -f stage2_size.h
--- /dev/null
+--- grub-0.97/lib/device.c.dmraid-partition-names 2006-02-13 18:53:59.000000000 -0500
++++ grub-0.97/lib/device.c 2006-02-13 18:56:04.000000000 -0500
+@@ -1106,6 +1106,7 @@
+ /* Compaq smart and others */
+ (strncmp(dev, "/dev/ida/", 9) == 0 ||
+ strncmp(dev, "/dev/ataraid/", 13) == 0 ||
++ strncmp(dev, "/dev/mapper/", 12) == 0 ||
+ strncmp(dev, "/dev/cciss/", 11) == 0 ||
+ strncmp(dev, "/dev/rd/", 8) == 0) ? "p" : "",
+ ((partition >> 16) & 0xFF) + 1);
--- /dev/null
+--- grub-0.97/util/grub-install.in.dmraid-recheck-bad 2006-01-13 17:04:26.000000000 -0500
++++ grub-0.97/util/grub-install.in 2006-01-13 17:05:00.000000000 -0500
+@@ -415,6 +415,14 @@
+ grubdir=${bootdir}/grub
+ device_map=${grubdir}/device.map
+
++if [ "$recheck" == "yes" ]; then
++ if grep 'mapper' ${device_map} >/dev/null; then
++ echo 'grub-install does not support reprobing of device.map when' 1>&2
++ echo 'using a device-mapper based boot device.' 1>&2
++ exit 1
++ fi
++fi
++
+ # if they just want the images copied, copy the images and then exit
+ if test $justcopy = yes; then
+ copy_images
--- /dev/null
+--- grub-0.97/util/grub-install.in.dmraid 2006-01-13 16:40:24.000000000 -0500
++++ grub-0.97/util/grub-install.in 2006-01-13 16:40:37.000000000 -0500
+@@ -101,17 +101,24 @@
+ # Break the device name into the disk part and the partition part.
+ case "$host_os" in
+ linux*)
+- tmp_disk=`echo "$1" | sed -e 's%\([sh]d[a-z]\)[0-9]*$%\1%' \
++ tmp_disk=`echo "$1" | grep -v '/mapper/control$' |
++ grep -v '/mapper/[[:alnum:]]\+-[[:alnum:]]\+$' | uniq |
++ sed -e 's%\([sh]d[a-z]\)[0-9]*$%\1%' \
+ -e 's%\(d[0-9]*\)p[0-9]*$%\1%' \
+ -e 's%\(fd[0-9]*\)$%\1%' \
+ -e 's%/part[0-9]*$%/disc%' \
+- -e 's%\(c[0-7]d[0-9]*\).*$%\1%'`
+- tmp_part=`echo "$1" | sed -e 's%.*/[sh]d[a-z]\([0-9]*\)$%\1%' \
++ -e 's%\(c[0-7]d[0-9]*\).*$%\1%' \
++ -e 's%\(/mapper/[[:alpha:]]\+_[[:alpha:]]\+\)[[:digit:]]\+$%\1%'`
++ tmp_part=`echo "$1" | grep -v '/mapper/control$' |
++ grep -v '/mapper/[[:alnum:]]\+-[[:alnum:]]\+$' | uniq |
++ sed -e 's%.*/[sh]d[a-z]\([0-9]*\)$%\1%' \
+ -e 's%.*d[0-9]*p%%' \
+ -e 's%.*/fd[0-9]*$%%' \
+ -e 's%.*/floppy/[0-9]*$%%' \
+ -e 's%.*/\(disc\|part\([0-9]*\)\)$%\2%' \
+- -e 's%.*c[0-7]d[0-9]*p%%'`
++ -e 's%.*c[0-7]d[0-9]*p%%' \
++ -e 's%.*/mapper/[[:alpha:]]\+_[[:alpha:]]\+\([[:digit:]]\+\)$%\1%' |
++ grep -v '.*/mapper/.*'`
+ ;;
+ gnu*)
+ tmp_disk=`echo "$1" | sed 's%\([sh]d[0-9]*\).*%\1%'`
+@@ -253,6 +260,43 @@
+ return 0
+ }
+
++# Usage: stat_device file
++# Find major:minor of a device node.
++stat_device() {
++ majmin=`stat -c "%t:%T" "$1" 2>/dev/null`
++ if test -z "$majmin"; then
++ echo "Could not find device for $1" 2>&1
++ exit 1
++ fi
++
++ echo "$majmin"
++}
++
++# Usage: find_mapper_device file
++# Find a file in /dev/mapper with the same major:minor as the specified node.
++find_mapper_device() {
++ if [ -b "$1" ]; then
++ dev="$1"
++ else
++ mntpnt=`echo "$1" | sed 's,/,\\\\/,g'`
++ dev=`awk '($2 ~ /'$mntpnt'/) { print $1 }' /etc/mtab`
++ fi
++ if test -z "$dev"; then
++ echo "Could not find device for $1" 2>&1
++ exit 1
++ fi
++
++ majmin=`stat_device $dev`
++ for x in /dev/mapper/* ; do
++ devmajmin=`stat_device "$x"`
++ if [ "$majmin" == "$devmajmin" ]; then
++ echo "$x"
++ return 0
++ fi
++ done
++ return 1
++}
++
+ # Usage: find_device file
+ # Find block device on which the file resides.
+ find_device () {
+@@ -265,9 +309,14 @@
+ exit 1
+ fi
+
+- tmp_fname=`resolve_symlink $tmp_fname`
++ ret_fname=`resolve_symlink $tmp_fname`
++ tmp_fname=`find_mapper_device $ret_fname`
++ if test -n "$tmp_fname"; then
++ ret_fname="$tmp_fname"
++ fi
+
+- echo "$tmp_fname"
++ echo "$ret_fname"
++ return 0
+ }
+
+ copy_images() {
--- /dev/null
+--- grub-0.97/util/grub-install.in.install 2005-12-12 18:15:45.000000000 -0500
++++ grub-0.97/util/grub-install.in 2005-12-12 18:18:11.000000000 -0500
+@@ -324,6 +324,15 @@
+ test -d "$bootdir" || mkdir "$bootdir" || exit 1
+ test -d "$grubdir" || mkdir "$grubdir" || exit 1
+
++# 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 \
++ ${pkgdatadir}/stage1 ${pkgdatadir}/stage2 ${pkgdatadir}/*stage1_5; do
++ cp -f $file ${grubdir} || exit 1
++done
++
+ # If --recheck is specified, remove the device map, if present.
+ if test $recheck = yes; then
+ rm -f $device_map
+@@ -406,15 +415,6 @@
+ 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
+-
+ # Make a default file.
+ ${grub_set_default} --root-directory=${rootdir} default
+
--- /dev/null
+--- grub-0.97/stage2/asm.S.mactel-kbd 2006-06-12 17:00:10.000000000 -0400
++++ grub-0.97/stage2/asm.S 2006-06-12 17:03:38.000000000 -0400
+@@ -1651,7 +1651,30 @@
+ jnz 3f
+ ret
+
+-3: /* use keyboard controller */
++3: /*
++ * try to switch gateA20 using PORT92, the "Fast A20 and Init"
++ * register
++ */
++ mov $0x92, %dx
++ inb %dx, %al
++ /* skip the port92 code if it's unimplemented (read returns 0xff) */
++ cmpb $0xff, %al
++ jz 6f
++
++ /* set or clear bit1, the ALT_A20_GATE bit */
++ movb 4(%esp), %ah
++ testb %ah, %ah
++ jz 4f
++ orb $2, %al
++ jmp 5f
++4: and $0xfd, %al
++
++ /* clear the INIT_NOW bit; don't accidently reset the machine */
++5: and $0xfe, %al
++ outb %al, %dx
++
++
++6: /* use keyboard controller */
+ pushl %eax
+
+ call gloop1
+@@ -1661,9 +1684,12 @@
+
+ gloopint1:
+ inb $K_STATUS
++ cmpb $0xff, %al
++ jz gloopint1_done
+ andb $K_IBUF_FUL, %al
+ jnz gloopint1
+
++gloopint1_done:
+ movb $KB_OUTPUT_MASK, %al
+ cmpb $0, 0x8(%esp)
+ jz gdoit
+@@ -1684,6 +1710,8 @@
+
+ gloop1:
+ inb $K_STATUS
++ cmpb $0xff, %al
++ jz gloop2ret
+ andb $K_IBUF_FUL, %al
+ jnz gloop1
+
+@@ -1994,8 +2022,25 @@
+ call EXT_C(prot_to_real)
+ .code16
+
++.again:
++ mov $0x11, %ah /* poll kbd */
+ int $0x16
+
++ jz .again
++#if 0
++/* XXX handle serial here? -- pj */
++ jnz .kbd
++#endif
++.kbd:
++ mov $0x10, %ah
++ int $0x16
++ cmp $0xe0, %al
++ jnz .not_ext
++ xor %al, %al
++.not_ext:
++ and %al, %al
++ jz .func_key
++.func_key:
+ movw %ax, %dx /* real_to_prot uses %eax */
+ call translate_keycode
+ call remap_ascii_char
+@@ -2003,7 +2048,7 @@
+ DATA32 call EXT_C(real_to_prot)
+ .code32
+
+- movw %dx, %ax
++ mov %dx, %ax
+
+ pop %ebp
+ ret
+@@ -2029,7 +2074,7 @@
+ call EXT_C(prot_to_real) /* enter real mode */
+ .code16
+
+- movb $0x1, %ah
++ movb $0x11, %ah
+ int $0x16
+
+ DATA32 jz notpending
--- /dev/null
+--- grub-0.97/util/grub-install.in.mdadm-path 2005-12-12 18:42:23.000000000 -0500
++++ grub-0.97/util/grub-install.in 2005-12-12 18:44:15.000000000 -0500
+@@ -30,5 +30,6 @@
+ pkglibdir=${libdir}/${PACKAGE}/${host_cpu}-${host_vendor}
+
+ grub_shell=${sbindir}/grub
++mdadm=${sbindir}/mdadm
+ log_file=/tmp/grub-install.log.$$
+ img_file=/tmp/grub-install.img.$$
+@@ -217,7 +218,7 @@
+ is_raid1_device () {
+ case "$host_os" in
+ linux*)
+- level=`mdadm --query --detail $1 2>/dev/null | \
++ level=`$mdadm --query --detail $1 2>/dev/null | \
+ awk '/Raid Level :/ {print $4}'`
+ if [ "$level" = "raid1" ]; then
+ return 0
+@@ -236,7 +237,7 @@
+ linux*)
+ if is_raid1_device $source_device ; then
+ list=""
+- for device in `mdadm --query --detail "${source_device}" | \
++ for device in `$mdadm --query --detail "${source_device}" | \
+ awk '/\/dev\/[^(md)]/ {print $7}'` ; do
+ list="$list $device"
+ done
--- /dev/null
+--- grub-0.97/util/grub-install.in.mpath 2006-08-02 17:21:53.000000000 -0400
++++ grub-0.97/util/grub-install.in 2006-08-02 17:23:23.000000000 -0400
+@@ -107,6 +107,7 @@
+ -e 's%\(fd[0-9]*\)$%\1%' \
+ -e 's%/part[0-9]*$%/disc%' \
+ -e 's%\(c[0-7]d[0-9]*\).*$%\1%' \
++ -e 's%\(/mapper/[[:alpha:]]\+[[:digit:]]\+\)p[[:digit:]]\+$%\1%' \
+ -e 's%\(/mapper/[[:alpha:]]\+_[[:alpha:]]\+\)[[:digit:]]\+$%\1%'`
+ tmp_part=`echo "$1" | grep -v '/mapper/control$' |
+ grep -v '/mapper/[[:alnum:]]\+-[[:alnum:]]\+$' | uniq |
+@@ -116,6 +117,7 @@
+ -e 's%.*/floppy/[0-9]*$%%' \
+ -e 's%.*/\(disc\|part\([0-9]*\)\)$%\2%' \
+ -e 's%.*c[0-7]d[0-9]*p%%' \
++ -e 's%.*/mapper/[[:alpha:]]\+[[:digit:]]\+p\([[:digit:]]\+\)$%\1%' \
+ -e 's%.*/mapper/[[:alpha:]]\+_[[:alpha:]]\+\([[:digit:]]\+\)$%\1%' |
+ grep -v '.*/mapper/.*'`
+ ;;
--- /dev/null
+2006-03-09 Alexandre Oliva <oliva@gnu.org>
+
+ * lib/builtins.c (install_blocklist_helper): Move static
+ last_lenght...
+ (install_func_context): ... here.
+ (install_func): Reset it.
+
+Index: grub-0.97/stage2/builtins.c
+===================================================================
+--- grub-0.97.orig/stage2/builtins.c 2006-03-09 10:26:41.000000000 -0300
++++ grub-0.97/stage2/builtins.c 2006-03-09 11:36:18.000000000 -0300
+@@ -1926,11 +1926,13 @@ static struct {
+ int saved_sector;
+ int installaddr;
+ int installlist;
++ int last_length;
+ char *stage2_first_buffer;
+ } install_func_context = {
+ .saved_sector = 0,
+ .installaddr = 0,
+ .installlist = 0,
++ .last_length = SECTOR_SIZE,
+ .stage2_first_buffer = NULL,
+ };
+
+@@ -1960,19 +1962,19 @@ install_blocklist_helper (int sector, in
+ 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;
++ int *last_length = &install_func_context.last_length;
+
+ if (debug)
+ printf("[%d]", sector);
+
+- if (offset != 0 || last_length != SECTOR_SIZE)
++ if (offset != 0 || *last_length != SECTOR_SIZE)
+ {
+ /* We found a non-sector-aligned data block. */
+ errnum = ERR_UNALIGNED;
+ return;
+ }
+
+- last_length = length;
++ *last_length = length;
+
+ if (*((unsigned long *) (*installlist - 4))
+ + *((unsigned short *) *installlist) != sector
+@@ -2027,7 +2029,11 @@ install_func (char *arg, int flags)
+ int is_open = 0;
+ /* If LBA is forced? */
+ int is_force_lba = 0;
++ int *last_length = &install_func_context.last_length;
+
++ /* Reset state. */
++ *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
--- /dev/null
+--- grub-0.97/stage2/shared.h.nxstack 2005-12-12 18:31:41.000000000 -0500
++++ grub-0.97/stage2/shared.h 2005-12-12 18:31:42.000000000 -0500
+@@ -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)
+--- grub-0.97/stage2/builtins.c.nxstack 2005-12-12 18:31:41.000000000 -0500
++++ grub-0.97/stage2/builtins.c 2005-12-12 18:41:47.000000000 -0500
+@@ -131,62 +131,97 @@
+ }
+
+ \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))
+@@ -206,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");
+
+@@ -1889,6 +1924,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)
+ {
+@@ -1896,8 +2002,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;
+@@ -1906,10 +2016,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? */
+@@ -1918,68 +2029,14 @@
+ 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)
+ {
+@@ -2011,10 +2068,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;
+ }
+@@ -2110,17 +2167,17 @@
+ = 0x9090;
+
+ /* 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))
+@@ -2136,27 +2193,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)
+@@ -2170,13 +2227,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;
+
+@@ -2259,7 +2316,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;
+
+@@ -2329,7 +2386,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;
+ }
+ }
+@@ -2351,7 +2408,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;
+@@ -2378,7 +2435,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/grub/asmstub.c.nxstack 2005-12-12 18:31:41.000000000 -0500
++++ grub-0.97/grub/asmstub.c 2005-12-12 18:31:42.000000000 -0500
+@@ -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 */
+@@ -82,7 +83,7 @@
+ struct apm_info apm_bios_info;
+
+ /* Emulation requirements. */
+-char *grub_scratch_mem = 0;
++void *grub_scratch_mem = 0;
+
+ struct geometry *disks = 0;
+
+@@ -106,14 +107,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;
+
+ auto void doit (void);
+@@ -145,9 +194,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. */
+
+@@ -220,7 +295,7 @@
+ device_map = 0;
+ free (disks);
+ disks = 0;
+- free (scratch);
++ munmap(simstack_alloc_base, simstack_size);
+ grub_scratch_mem = 0;
+
+ if (serial_device)
--- /dev/null
+--- grub-0.97/stage2/builtins.c.bootonce 2005-12-12 18:23:12.000000000 -0500
++++ grub-0.97/stage2/builtins.c 2005-12-12 18:29:20.000000000 -0500
+@@ -3217,146 +3217,175 @@
+ };
+
+ \f
+-/* savedefault */
++
++#if !defined(SUPPORT_DISKLESS) && !defined(GRUB_UTIL)
++/* Write specified default entry number into stage2 file. */
+ static int
+-savedefault_func (char *arg, int flags)
++savedefault_helper(int new_default)
+ {
+-#if !defined(SUPPORT_DISKLESS) && !defined(GRUB_UTIL)
+- unsigned long tmp_drive = saved_drive;
+- unsigned long tmp_partition = saved_partition;
+- char *default_file = (char *) DEFAULT_FILE_BUF;
+- char buf[10];
+- char sect[SECTOR_SIZE];
+- int entryno;
+- int sector_count = 0;
+- int saved_sectors[2];
+- int saved_offsets[2];
+- int saved_lengths[2];
+-
+- /* Save sector information about at most two sectors. */
+- auto void disk_read_savesect_func (int sector, int offset, int length);
+- void disk_read_savesect_func (int sector, int offset, int length)
+- {
+- if (sector_count < 2)
+- {
+- saved_sectors[sector_count] = sector;
+- saved_offsets[sector_count] = offset;
+- saved_lengths[sector_count] = length;
+- }
+- sector_count++;
+- }
+-
+- /* This command is only useful when you boot an entry from the menu
+- interface. */
+- if (! (flags & BUILTIN_SCRIPT))
++ char buffer[512];
++ int *entryno_ptr;
++
++ /* Get the geometry of the boot drive (i.e. the disk which contains
++ this stage2). */
++ if (get_diskinfo (boot_drive, &buf_geom))
+ {
+- errnum = ERR_UNRECOGNIZED;
++ errnum = ERR_NO_DISK;
+ return 1;
+ }
+
+- /* Determine a saved entry number. */
+- if (*arg)
++ /* Load the second sector of this stage2. */
++ if (! rawread (boot_drive, install_second_sector, 0, SECTOR_SIZE, buffer))
+ {
+- if (grub_memcmp (arg, "fallback", sizeof ("fallback") - 1) == 0)
+- {
+- int i;
+- int index = 0;
+-
+- for (i = 0; i < MAX_FALLBACK_ENTRIES; i++)
+- {
+- if (fallback_entries[i] < 0)
+- break;
+- if (fallback_entries[i] == current_entryno)
+- {
+- index = i + 1;
+- break;
+- }
+- }
+-
+- if (index >= MAX_FALLBACK_ENTRIES || fallback_entries[index] < 0)
+- {
+- /* This is the last. */
+- errnum = ERR_BAD_ARGUMENT;
+- return 1;
+- }
++ return 1;
++ }
+
+- entryno = fallback_entries[index];
+- }
+- else if (! safe_parse_maxint (&arg, &entryno))
+- return 1;
++ /* Sanity check. */
++ if (buffer[STAGE2_STAGE2_ID] != STAGE2_ID_STAGE2
++ || *((short *) (buffer + STAGE2_VER_MAJ_OFFS)) != COMPAT_VERSION)
++ {
++ errnum = ERR_BAD_VERSION;
++ return 1;
+ }
+- else
+- entryno = current_entryno;
++
++ entryno_ptr = (int *) (buffer + STAGE2_SAVED_ENTRYNO);
+
+- /* Open the default file. */
+- saved_drive = boot_drive;
+- saved_partition = install_partition;
+- if (grub_open (default_file))
++ /* Check if the saved entry number differs from current entry number. */
++ if (*entryno_ptr != new_default)
+ {
+- int len;
++ /* Overwrite the saved entry number. */
++ *entryno_ptr = new_default;
+
+- disk_read_hook = disk_read_savesect_func;
+- len = grub_read (buf, sizeof (buf));
+- disk_read_hook = 0;
+- grub_close ();
++ /* Save the image in the disk. */
++ if (! rawwrite (boot_drive, install_second_sector, buffer))
++ return 1;
+
+- if (len != sizeof (buf))
+- {
+- /* This is too small. Do not modify the file manually, please! */
+- errnum = ERR_READ;
+- goto fail;
+- }
++ /* Clear the cache. */
++ buf_track = -1;
++ }
+
+- if (sector_count > 2)
+- {
+- /* Is this possible?! Too fragmented! */
+- errnum = ERR_FSYS_CORRUPT;
+- goto fail;
+- }
+-
+- /* Set up a string to be written. */
+- grub_memset (buf, '\n', sizeof (buf));
+- grub_sprintf (buf, "%d", entryno);
+-
+- if (saved_lengths[0] < sizeof (buf))
+- {
+- /* The file is anchored to another file and the first few bytes
+- are spanned in two sectors. Uggh... */
+- if (! rawread (current_drive, saved_sectors[0], 0, SECTOR_SIZE,
+- sect))
+- goto fail;
+- grub_memmove (sect + saved_offsets[0], buf, saved_lengths[0]);
+- if (! rawwrite (current_drive, saved_sectors[0], sect))
+- goto fail;
++ return 0;
++}
++#endif
+
+- if (! rawread (current_drive, saved_sectors[1], 0, SECTOR_SIZE,
+- sect))
+- goto fail;
+- grub_memmove (sect + saved_offsets[1],
+- buf + saved_lengths[0],
+- sizeof (buf) - saved_lengths[0]);
+- if (! rawwrite (current_drive, saved_sectors[1], sect))
+- goto fail;
+- }
++#if !defined(SUPPORT_DISKLESS) && defined(GRUB_UTIL)
++/*
++ * Full implementation of new `savedefault' for GRUB shell.
++ * XXX This needs fixing for stage2 files which aren't accessible
++ * through a mounted filesystem.
++ */
++static int
++savedefault_shell(char *arg, int flags)
++{
++ char *stage2_os_file = "/boot/grub/stage2"; /* Default filename */
++ FILE *fp;
++ char buffer[512];
++ int *entryno_ptr;
++ int new_default = 0;
++ int old_default = 0;
++
++ while (1)
++ {
++ if (grub_memcmp ("--stage2=", arg, sizeof ("--stage2=") - 1) == 0)
++ {
++ stage2_os_file = arg + sizeof ("--stage2=") - 1;
++ arg = skip_to (0, arg);
++ nul_terminate (stage2_os_file);
++ }
++ else if (grub_memcmp ("--default=", arg, sizeof ("--default=") - 1) == 0)
++ {
++ char *p = arg + sizeof ("--default=") - 1;
++ if (! safe_parse_maxint (&p, &new_default))
++ return 1;
++ arg = skip_to (0, arg);
++ }
++ else if (grub_memcmp ("--once", arg, sizeof ("--once") - 1) == 0)
++ {
++ new_default <<= 8;
++ new_default |= STAGE2_ONCEONLY_ENTRY;
++ arg = skip_to (0, arg);
++ }
+ else
+- {
+- /* This is a simple case. It fits into a single sector. */
+- if (! rawread (current_drive, saved_sectors[0], 0, SECTOR_SIZE,
+- sect))
+- goto fail;
+- grub_memmove (sect + saved_offsets[0], buf, sizeof (buf));
+- if (! rawwrite (current_drive, saved_sectors[0], sect))
+- goto fail;
+- }
++ break;
++ }
+
+- /* Clear the cache. */
+- buf_track = -1;
++ if (! (fp = fopen(stage2_os_file, "r+")))
++ {
++ errnum = ERR_FILE_NOT_FOUND;
++ return 1;
++ }
++
++ if (fseek (fp, SECTOR_SIZE, SEEK_SET) != 0)
++ {
++ fclose (fp);
++ errnum = ERR_BAD_VERSION;
++ return 1;
++ }
++
++ if (fread (buffer, 1, SECTOR_SIZE, fp) != SECTOR_SIZE)
++ {
++ fclose (fp);
++ errnum = ERR_READ;
++ return 1;
+ }
+
+- fail:
+- saved_drive = tmp_drive;
+- saved_partition = tmp_partition;
+- return errnum;
++ /* Sanity check. */
++ if (buffer[STAGE2_STAGE2_ID] != STAGE2_ID_STAGE2
++ || *((short *) (buffer + STAGE2_VER_MAJ_OFFS)) != COMPAT_VERSION)
++ {
++ errnum = ERR_BAD_VERSION;
++ return 1;
++ }
++
++ entryno_ptr = (int *) (buffer + STAGE2_SAVED_ENTRYNO);
++ if (new_default & STAGE2_ONCEONLY_ENTRY)
++ {
++ old_default=*entryno_ptr;
++ *entryno_ptr = new_default + (old_default & 0xFF);
++ }
++ else
++ {
++ *entryno_ptr = new_default;
++ }
++
++ if (fseek (fp, SECTOR_SIZE, SEEK_SET) != 0)
++ {
++ fclose (fp);
++ errnum = ERR_BAD_VERSION;
++ return 1;
++ }
++
++ if (fwrite (buffer, 1, SECTOR_SIZE, fp) != SECTOR_SIZE)
++ {
++ fclose (fp);
++ errnum = ERR_WRITE;
++ return 1;
++ }
++
++ (void)fflush (fp);
++ fclose (fp);
++ return 0;
++}
++#endif
++
++/* savedefault */
++static int
++savedefault_func (char *arg, int flags)
++{
++#if !defined(SUPPORT_DISKLESS)
++#if !defined(GRUB_UTIL)
++ /* This command is only useful when you boot an entry from the menu
++ interface. */
++ if (! (flags & BUILTIN_SCRIPT))
++ {
++ errnum = ERR_UNRECOGNIZED;
++ return 1;
++ }
++
++ return savedefault_helper(current_entryno);
++#else /* defined(GRUB_UTIL) */
++ return savedefault_shell(arg, flags);
++#endif
+ #else /* ! SUPPORT_DISKLESS && ! GRUB_UTIL */
+ errnum = ERR_UNRECOGNIZED;
+ return 1;
+@@ -3368,10 +3397,14 @@
+ "savedefault",
+ savedefault_func,
+ BUILTIN_CMDLINE,
+- "savedefault [NUM | `fallback']",
+- "Save the current entry as the default boot entry if no argument is"
+- " specified. If a number is specified, this number is saved. If"
+- " `fallback' is used, next fallback entry is saved."
++#ifdef GRUB_UTIL
++ "savedefault [--stage2=STAGE2_FILE] [--default=DEFAULT] [--once]",
++ "Save DEFAULT as the default boot entry in STAGE2_FILE. If '--once'"
++ " is specified, the default is reset after the next reboot."
++#else
++ "savedefault",
++ "Save the current entry as the default boot entry."
++#endif
+ };
+
+ \f
+@@ -4598,6 +4631,15 @@
+ static int
+ timeout_func (char *arg, int flags)
+ {
++ /* One-shot default shenanigans -- don't piss around with the menu! */
++ if (grub_timeout != -1)
++ return 0;
++ if ((saved_entryno & STAGE2_ONCEONLY_ENTRY) != 0)
++ {
++ grub_timeout = 0;
++ return 0;
++ }
++
+ if (! safe_parse_maxint (&arg, &grub_timeout))
+ return 1;
+
+--- grub-0.97/stage2/shared.h.bootonce 2005-12-12 18:23:13.000000000 -0500
++++ grub-0.97/stage2/shared.h 2005-12-12 18:23:13.000000000 -0500
+@@ -200,6 +200,8 @@
+ #define STAGE2_FORCE_LBA 0x11
+ #define STAGE2_VER_STR_OFFS 0x12
+
++#define STAGE2_ONCEONLY_ENTRY 0x10000
++
+ /* Stage 2 identifiers */
+ #define STAGE2_ID_STAGE2 0
+ #define STAGE2_ID_FFS_STAGE1_5 1
+--- grub-0.97/stage2/builtins.c.bootonce 2006-03-13 16:55:11.000000000 -0500
++++ grub-0.97/stage2/builtins.c 2006-03-13 16:56:01.000000000 -0500
+@@ -761,11 +761,25 @@
+ };
+
+ \f
++#if !defined(SUPPORT_DISKLESS) && !defined(GRUB_UTIL)
++static int savedefault_helper(int);
++#endif
+ /* default */
+ static int
+ default_func (char *arg, int flags)
+ {
+ #ifndef SUPPORT_DISKLESS
++#ifndef GRUB_UTIL
++ /* Has a forced once-only default been specified? */
++ if ((saved_entryno & STAGE2_ONCEONLY_ENTRY) != 0)
++ {
++ int old_defaults=saved_entryno & ~STAGE2_ONCEONLY_ENTRY;
++ grub_timeout = 0;
++ default_entry = old_defaults >> 8;
++ savedefault_helper(old_defaults & 0xff);
++ return 0;
++ }
++#endif
+ if (grub_strcmp (arg, "saved") == 0)
+ {
+ default_entry = saved_entryno;
+--- grub-0.97/stage2/stage2.c.bootonce 2006-03-13 17:27:40.000000000 -0500
++++ grub-0.97/stage2/stage2.c 2006-03-13 17:29:11.000000000 -0500
+@@ -960,38 +960,8 @@
+ if (use_config_file)
+ #endif /* GRUB_UTIL */
+ {
+- char *default_file = (char *) DEFAULT_FILE_BUF;
+ int i;
+-
+- /* Get a saved default entry if possible. */
+- saved_entryno = 0;
+- *default_file = 0;
+- grub_strncat (default_file, config_file, DEFAULT_FILE_BUFLEN);
+- for (i = grub_strlen(default_file); i >= 0; i--)
+- if (default_file[i] == '/')
+- {
+- i++;
+- break;
+- }
+- default_file[i] = 0;
+- grub_strncat (default_file + i, "default", DEFAULT_FILE_BUFLEN - i);
+- if (grub_open (default_file))
+- {
+- char buf[10]; /* This is good enough. */
+- char *p = buf;
+- int len;
+-
+- len = grub_read (buf, sizeof (buf));
+- if (len > 0)
+- {
+- buf[sizeof (buf) - 1] = 0;
+- safe_parse_maxint (&p, &saved_entryno);
+- }
+
+- grub_close ();
+- }
+- errnum = ERR_NONE;
+-
+ do
+ {
+ /* STATE 0: Before any title command.
+--- grub-0.97/util/grub-install.in.bootonce 2006-03-13 17:39:35.000000000 -0500
++++ grub-0.97/util/grub-install.in 2006-03-13 17:39:50.000000000 -0500
+@@ -30,7 +30,6 @@
+ pkglibdir=${libdir}/${PACKAGE}/${host_cpu}-${host_vendor}
+
+ grub_shell=${sbindir}/grub
+-grub_set_default=${sbindir}/grub-set-default
+ log_file=/tmp/grub-install.log.$$
+ img_file=/tmp/grub-install.img.$$
+ rootdir=
+@@ -432,9 +431,6 @@
+ exit 1
+ fi
+
+-# Make a default file.
+-${grub_set_default} --root-directory=${rootdir} default
+-
+ # Make sure that GRUB reads the same images as the host OS.
+ test -n "$mkimg" && img_file=`$mkimg`
+ test -n "$mklog" && log_file=`$mklog`
+--- grub-0.97/configure.bootonce 2006-03-13 17:49:05.000000000 -0500
++++ grub-0.97/configure 2006-03-13 17:49:16.000000000 -0500
+@@ -6135,7 +6135,7 @@
+
+
+
+- ac_config_files="$ac_config_files Makefile stage1/Makefile stage2/Makefile docs/Makefile lib/Makefile util/Makefile grub/Makefile netboot/Makefile util/grub-image util/grub-install util/grub-md5-crypt util/grub-terminfo util/grub-set-default"
++ ac_config_files="$ac_config_files Makefile stage1/Makefile stage2/Makefile docs/Makefile lib/Makefile util/Makefile grub/Makefile netboot/Makefile util/grub-image util/grub-install util/grub-md5-crypt util/grub-terminfo"
+
+ cat >confcache <<\_ACEOF
+ # This file is a shell script that caches the results of configure
+@@ -6754,7 +6754,6 @@
+ "util/grub-install" ) CONFIG_FILES="$CONFIG_FILES util/grub-install" ;;
+ "util/grub-md5-crypt" ) CONFIG_FILES="$CONFIG_FILES util/grub-md5-crypt" ;;
+ "util/grub-terminfo" ) CONFIG_FILES="$CONFIG_FILES util/grub-terminfo" ;;
+- "util/grub-set-default" ) CONFIG_FILES="$CONFIG_FILES util/grub-set-default" ;;
+ "depfiles" ) CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+ "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+ *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+--- grub-0.97/configure.ac.bootonce 2006-03-13 17:47:24.000000000 -0500
++++ grub-0.97/configure.ac 2006-03-13 17:47:37.000000000 -0500
+@@ -666,5 +666,5 @@
+ docs/Makefile lib/Makefile util/Makefile \
+ grub/Makefile netboot/Makefile util/grub-image \
+ util/grub-install util/grub-md5-crypt \
+- util/grub-terminfo util/grub-set-default])
++ util/grub-terminfo])
+ AC_OUTPUT
+--- grub-0.97/util/Makefile.am.bootonce 2006-03-13 17:48:39.000000000 -0500
++++ grub-0.97/util/Makefile.am 2006-03-13 17:48:45.000000000 -0500
+@@ -1,6 +1,5 @@
+ bin_PROGRAMS = mbchk
+-sbin_SCRIPTS = grub-install grub-md5-crypt grub-terminfo \
+- grub-set-default
++sbin_SCRIPTS = grub-install grub-md5-crypt grub-terminfo
+ noinst_SCRIPTS = grub-image mkbimage
+
+ EXTRA_DIST = mkbimage
+--- grub-0.97/util/Makefile.in.bootonce 2006-03-13 17:47:56.000000000 -0500
++++ grub-0.97/util/Makefile.in 2006-03-13 17:48:34.000000000 -0500
+@@ -43,8 +43,7 @@
+ subdir = util
+ DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ $(srcdir)/grub-image.in $(srcdir)/grub-install.in \
+- $(srcdir)/grub-md5-crypt.in $(srcdir)/grub-set-default.in \
+- $(srcdir)/grub-terminfo.in
++ $(srcdir)/grub-md5-crypt.in $(srcdir)/grub-terminfo.in
+ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+ am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+@@ -52,8 +51,7 @@
+ $(ACLOCAL_M4)
+ mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+ CONFIG_HEADER = $(top_builddir)/config.h
+-CONFIG_CLEAN_FILES = grub-image grub-install grub-md5-crypt \
+- grub-terminfo grub-set-default
++CONFIG_CLEAN_FILES = grub-image grub-install grub-md5-crypt grub-terminfo
+ am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)"
+ binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+ PROGRAMS = $(bin_PROGRAMS)
+@@ -183,8 +181,7 @@
+ sharedstatedir = @sharedstatedir@
+ sysconfdir = @sysconfdir@
+ target_alias = @target_alias@
+-sbin_SCRIPTS = grub-install grub-md5-crypt grub-terminfo \
+- grub-set-default
++sbin_SCRIPTS = grub-install grub-md5-crypt grub-terminfo
+
+ noinst_SCRIPTS = grub-image mkbimage
+ EXTRA_DIST = mkbimage
+@@ -234,8 +231,6 @@
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ grub-terminfo: $(top_builddir)/config.status $(srcdir)/grub-terminfo.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+-grub-set-default: $(top_builddir)/config.status $(srcdir)/grub-set-default.in
+- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+ install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)"
--- /dev/null
+--- grub-0.97/acinclude.m4.prototypes 2005-12-12 19:07:24.000000000 -0500
++++ grub-0.97/acinclude.m4 2005-12-12 19:07:56.000000000 -0500
+@@ -44,6 +44,8 @@
+ [AC_MSG_CHECKING([whether ${OBJCOPY} works for absolute addresses])
+ AC_CACHE_VAL(grub_cv_prog_objcopy_absolute,
+ [cat > conftest.c <<\EOF
++void cmain(void);
++
+ void
+ cmain (void)
+ {
--- /dev/null
+--- grub-0.97/util/grub-install.in.stderr 2006-07-07 10:56:37.000000000 -0400
++++ grub-0.97/util/grub-install.in 2006-07-07 11:01:35.000000000 -0400
+@@ -207,7 +207,7 @@
+ while test -L $tmp_fname; do
+ tmp_new_fname=`ls -al $tmp_fname | sed -n 's%.*-> \(.*\)%\1%p'`
+ if test -z "$tmp_new_fname"; then
+- echo "Unrecognized ls output" 2>&1
++ echo "Unrecognized ls output" 1>&2
+ exit 1
+ fi
+
+@@ -264,7 +264,7 @@
+ stat_device() {
+ majmin=`stat -c "%t:%T" "$1" 2>/dev/null`
+ if test -z "$majmin"; then
+- echo "Could not find device for $1" 2>&1
++ echo "Could not find device for $1" 1>&2
+ exit 1
+ fi
+
+@@ -281,7 +281,7 @@
+ dev=`awk '($2 ~ /'$mntpnt'/) { print $1 }' /etc/mtab`
+ fi
+ if test -z "$dev"; then
+- echo "Could not find device for $1" 2>&1
++ echo "Could not find device for $1" 1>&2
+ exit 1
+ fi
+
+@@ -304,11 +304,11 @@
+ tmp_fname=`df $1/ | sed -n 's%.*\(/dev/[^ ]*\).*%\1%p'`
+
+ if test -z "$tmp_fname"; then
+- echo "Could not find device for $1" 2>&1
++ echo "Could not find device for $1" 1>&2
+ exit 1
+ fi
+
+- ret_fname=`resolve_symlink $tmp_fname`
++ ret_fname=`resolve_symlink $tmp_fname` || exit 1
+ tmp_fname=`find_mapper_device $ret_fname`
+ if test -n "$tmp_fname"; then
+ ret_fname="$tmp_fname"
+@@ -325,7 +325,7 @@
+ done
+ for file in \
+ ${pkgdatadir}/stage1 ${pkgdatadir}/stage2 ${pkgdatadir}/*stage1_5; do
+- cp -f $file ${grubdir} || exit 1
++ cp -f $file ${grubdir} 1>&2 || exit 1
+ done
+ }
+
+@@ -520,9 +520,9 @@
+ # Check for INSTALL_DEVICE.
+ case "$install_device" in
+ /dev/*)
+- install_device=`resolve_symlink "$install_device"`
++ install_device=`resolve_symlink "$install_device"` || exit 1
+ for install_drive in `find_real_devs $install_device` ; do
+- install_drive=`convert $install_drive`
++ install_drive=`convert $install_drive` || exit 1
+ if is_raid1_device $install_device; then
+ install_drive=`echo $install_drive | sed 's/,[0-9]*)/)/'`
+ fi
+@@ -550,8 +550,8 @@
+ unset install_device
+
+ # Get the root drive.
+-root_device=`find_device ${rootdir}`
+-bootdir_device=`find_device ${bootdir}`
++root_device=`find_device ${rootdir}` || exit 1
++bootdir_device=`find_device ${bootdir}` || exit 1
+
+ # Check if the boot directory is in the same device as the root directory.
+ if test "x$root_device" != "x$bootdir_device"; then
+@@ -561,7 +561,7 @@
+ fi
+
+ # Check if the root directory exists in the same device as the grub directory.
+-grubdir_device=`find_device ${grubdir}`
++grubdir_device=`find_device ${grubdir}` || exit 1
+
+ if test "x$grubdir_device" != "x$root_device"; then
+ # For now, cannot deal with this situation.
+@@ -582,7 +582,7 @@
+ fi
+
+ # Convert the root deviceto a GRUB drive.
+-root_drive=`convert "$root_device"`
++root_drive=`convert "$root_device"` || exit 1
+ if [ "x$root_drive" = x ]; then
+ exit 1
+ fi
+@@ -618,7 +618,7 @@
+
+ for install_drive in $install_drives; do
+ # Convert the root deviceto a GRUB drive.
+- root_drive=`convert "$root_device"`
++ root_drive=`convert "$root_device"` || exit 1
+ if [ "x$root_drive" = x ]; then
+ exit 1
+ fi