--- 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 @@
 };
 
 
-/* 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
 };
 
 
@@ -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 @@
 };
 
 
+#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)"
