[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[patch] add setdefault X
From: |
Jim Cromie |
Subject: |
[patch] add setdefault X |
Date: |
Tue, 04 Nov 2003 10:07:28 -0700 |
User-agent: |
Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030624 |
hi folks,
This patch adds a new command to grub - setdefault.
Its a close derivative of savedefault, the only difference is that it
expects a
numeric argument, where original uses an implicit argument.
Its purpose is to support multi-kernel testing; a grub.conf can specify
a sequence
of different kernels to run, which *presumably* would execute some
substantial
set of tests, then reboot to the next kernel, which would repeat until
the last
setdefault (ie: 0 in example below) returned the box to normal operation.
Heres a sequence of 4 kernels on my machine:
# Here are the sequential boot tests
title Test RH 7.2 (2.4.20-20.7)
setdefault 5
root (hd0,1)
kernel /vmlinuz-2.4.20-20.7 ro root=LABEL=/
initrd /initrd-2.4.20-20.7.img
title Test RH 7.2 (2.4.20-18.7)
setdefault 6
root (hd0,1)
kernel /vmlinuz-2.4.20-18.7 ro root=LABEL=/
initrd /initrd-2.4.20-18.7.img
title Test RedHat 9 (2.4.20-20.9)
setdefault 7
root (hd0,0)
kernel /boot/vmlinuz-2.4.20-20.9 ro root=LABEL=/1
initrd /boot/initrd-2.4.20-20.9.img
title Test RedHat 9 (2.4.20-8)
setdefault 0
root (hd0,0)
kernel /boot/vmlinuz-2.4.20-8 ro root=LABEL=/1
initrd /boot/initrd-2.4.20-8.img
I expect to combine this with a runlevel=4 or similar to make it easy to
trigger
the *smoke-test* and reboot from rc.local.
The patch is against RH grub-0.93-7 srpm, which has 18 patches for
0.90-0.93
Its also somewhat unfinished;
1. I copy-pasted verbatim from savedefault_helper to setdefault_helper
The 'right' thing to do would be to rename savedefault_helper as
setdefault_helper,
and modify savedefault to call it. IOW, savedefault is higher-level
than setdefault,
and should be implemented on top. Doing this however felt a bit too
brazen.
2. No (proper patch to the source of ) docs.
I couldnt quite make out from docs/Makefile.am which texi/info/etc
file to edit into.
I added stuff into grub.texi.config.new, with hope that it could be
easily cut-pasted
into wherever it belongs.
I also left some of the help-text in static struct builtin
builtin_setdefault:
I am unsure whether any of the options should be allowed; I think
--once would not make
any sense though. I did not strip the code for those options, so I
thought it best to leave
an inappropriate marker.
Lastly - I found the FAQ and info on installation somewhat confusing -
Specifically, putting an ext2 on a floppy is apparently mutually
exclusive with writing stage1, stage2
via dd. I'll try to explain better in a separate (appropriately titled)
msg.
--- grub.texi.config.old Tue Nov 4 09:15:22 2003
+++ grub.texi.config.new Tue Nov 4 09:39:10 2003
@@ -1845,8 +1845,9 @@
used.
You can specify @samp{saved} instead of a number. In this case, the
-default entry is the entry saved with the command
address@hidden @xref{savedefault}, for more information.
+default entry is the entry saved with the commands
address@hidden or @command{setdefault}.
address@hidden, @xref{setdefault}, for more information.
@end deffn
@@ -2404,6 +2405,7 @@
* root:: Set GRUB's root device
* rootnoverify:: Set GRUB's root device without mounting
* savedefault:: Save current entry as the default entry
+* setdefault:: Save given value as the default entry
* setup:: Set up GRUB's installation automatically
* testload:: Load a file for testing a filesystem
* testvbe:: Test VESA BIOS EXTENSION
@@ -2890,6 +2892,46 @@
@end deffn
address@hidden setdefault
address@hidden setdefault
+
address@hidden Command setdefault
+Set the given menu entry as a default entry. This command allows you
+to set up a sequence of configurations which will boot different
+kernels in sequence. This is intended to support unattended testing
+of kernels, or of applications that should be portable across different
+kernels. Here is an example:
+
address@hidden
address@hidden
+default saved
+timeout 10
+# Assume 0..2 are normal boots.
+# test boot sequence 3,4
+
+# assume this is
+title GNU/Linux TEST
+root (hd0,0)
+kernel /boot/vmlinuz root=/dev/sda1 vga=ext
+initrd /boot/initrd
+savedefault 4
+
+title FreeBSD TEST
+root (hd0,a)
+kernel /boot/loader
+setdefault 0
address@hidden group
address@hidden example
+
+With this configuration, once you (the user) select the 4th entry,
+GRUB will set the default to the 5th entry, then boot the 4th. When
+the tests (which you configure separately) within the 4th entry
+complete and reboot, the 5th entry is then booted; it too runs tests
+and reboots, but before it does, it sets the default back to 0,
+resuming normal operations.
+See also @ref{default}. @end deffn
+
+
@node setup
@subsection setup
--- builtins.old.c Fri Oct 31 08:14:40 2003
+++ builtins.c Tue Nov 4 09:54:21 2003
@@ -3515,6 +3515,189 @@
};
+
+#if !defined(SUPPORT_DISKLESS) && !defined(GRUB_UTIL)
+/* Write specified default entry number into stage2 file. */
+static int
+setdefault_helper(int new_default)
+{
+ 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_NO_DISK;
+ return 1;
+ }
+
+ /* Load the second sector of this stage2. */
+ if (! rawread (boot_drive, install_second_sector, 0, SECTOR_SIZE, buffer))
+ {
+ 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;
+ }
+
+ entryno_ptr = (int *) (buffer + STAGE2_SAVED_ENTRYNO);
+
+ /* Check if the saved entry number differs from current entry number. */
+ if (*entryno_ptr != new_default)
+ {
+ /* Overwrite the saved entry number. */
+ *entryno_ptr = new_default;
+
+ /* Save the image in the disk. */
+ if (! rawwrite (boot_drive, install_second_sector, buffer))
+ return 1;
+
+ /* Clear the cache. */
+ buf_track = -1;
+ }
+
+ return 0;
+}
+#endif
+
+#if !defined(SUPPORT_DISKLESS) && defined(GRUB_UTIL)
+/*
+ * Full implementation of new `setdefault' for GRUB shell.
+ * XXX This needs fixing for stage2 files which aren't accessible
+ * through a mounted filesystem.
+ */
+static int
+setdefault_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;
+
+ 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 |= STAGE2_ONCEONLY_ENTRY;
+ arg = skip_to (0, arg);
+ }
+ else
+ break;
+ }
+
+ 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;
+ }
+
+ /* 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);
+ *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
+
+/* setdefault */
+static int
+setdefault_func (char *arg, int flags)
+{
+#if !defined(SUPPORT_DISKLESS)
+#if !defined(GRUB_UTIL)
+ int new_default;
+ /* This command is only useful when you boot an entry from the menu
+ interface. */
+ if (! (flags & BUILTIN_SCRIPT))
+ {
+ errnum = ERR_UNRECOGNIZED;
+ return 1;
+ }
+ /* convert new-default arg (a string) into an int */
+ if (!safe_parse_maxint(&arg, &new_default)) return 1;
+ return setdefault_helper(new_default);
+#else /* defined(GRUB_UTIL) */
+ return setdefault_shell(arg, flags);
+#endif
+#else /* ! SUPPORT_DISKLESS && ! GRUB_UTIL */
+ errnum = ERR_UNRECOGNIZED;
+ return 1;
+#endif /* ! SUPPORT_DISKLESS && ! GRUB_UTIL */
+}
+
+static struct builtin builtin_setdefault =
+{
+ "setdefault",
+ setdefault_func,
+ BUILTIN_CMDLINE,
+#ifdef GRUB_UTIL
+ "setdefault [--stage2=STAGE2_FILE] [--default=DEFAULT] [--once]
Entry-Number",
+ "Save DEFAULT as the default boot entry in STAGE2_FILE. If '--once'"
+ " is specified, the default is reset after the next reboot."
+#else
+ "setdefault",
+ "Set the given entry as the default boot entry."
+#endif
+};
+
+
#ifdef SUPPORT_SERIAL
/* serial */
static int
@@ -5009,6 +5192,7 @@
&builtin_root,
&builtin_rootnoverify,
&builtin_savedefault,
+ &builtin_setdefault,
#ifdef SUPPORT_SERIAL
&builtin_serial,
#endif /* SUPPORT_SERIAL */
- [patch] add setdefault X,
Jim Cromie <=
- Re: [patch] add setdefault X, Yoshinori K. Okuji, 2003/11/06
- Re: [patch] add setdefault X, Robert Millan, 2003/11/08
- Re: [patch] add setdefault X, Yoshinori K. Okuji, 2003/11/12
- Re: [patch] add setdefault X, Robert Millan, 2003/11/12
- Re: [patch] add setdefault X, Yoshinori K. Okuji, 2003/11/13
- Re: [patch] add setdefault X, Robert Millan, 2003/11/13
- Re: [patch] add setdefault X, Yoshinori K. Okuji, 2003/11/15
- Re: [patch] add setdefault X, Robert Millan, 2003/11/15
- Re: [patch] add setdefault X, Yoshinori K. Okuji, 2003/11/15
- Re: [patch] add setdefault X, Jim Cromie, 2003/11/12