Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 31 Aug 2000 08:29:16 -0500 (CDT)
From:      Mike Meyer <mwm@mired.org>
To:        R Joseph Wright <rjoseph@mammalia.org>
Cc:        questions@freebsd.org, zzhang@cs.binghamton.edu
Subject:   Re: boot manager other than booteasy
Message-ID:  <14766.23980.183756.126206@guru.mired.org>
In-Reply-To: <115781327@toto.iv>

next in thread | previous in thread | raw e-mail | index | archive | help
R Joseph Wright writes:
> And Siegbert Baude spoke:
> > Zhihui Zhang wrote:
> > > I have installed Linux on my laptop and am using LILO as the boot manager.
> > > Compared to booteasy, LILO can not remember the last OS I booted from and
> > > boot from that OS automatically next time powerup.  But booteasy can not
> > > recognize Linux in a DOS extended partition.  Is there any FREE boot
> > > manager that can boot Linux in a DOS extended partition and yet can
> > > remember the last OS it booted from?
> That looks very slick and all, but I recommend grub, now in the ports
> collection (sysutils/grub).  It will boot virtually anything and can be used 
> interactively on its own command line.  It also does not need Lilo to boot
> into Linux.  
>
> However, I don't know if it will remember the last OS booted
> from and boot from it.

No, it can't. The following patch fixes that. It adds the command
"savedefault", which saves the current entry number when used in an
entry, and makes the "default" command accept the keyword "saved",
which uses the value from the last saved default.

Grub is much more flexible than booteasy in general, as it boots
"entries" as opposed to partitions, so you can have a menu that boots
the same OS in various modes. This patch carries that on, allowing
some entries to become the default, and not others.

Feedback on it would be greatly appreciated.

	<mike

diff -ru grub-0.5.95-orig/docs/user-ref.texi grub-0.5.95/docs/user-ref.texi
--- grub-0.5.95-orig/docs/user-ref.texi	Sun Aug 27 05:45:27 2000
+++ grub-0.5.95/docs/user-ref.texi	Sun Aug 27 05:46:10 2000
@@ -474,7 +474,7 @@
 
 Commands usable in the menu only.
 
-@deffn Command default num
+@deffn Command default [num | `saved']
 Set the default entry to the entry number @var{num} (if not specified,
 it is 0, the first entry).
 @end deffn
diff -ru grub-0.5.95-orig/grub/asmstub.c grub-0.5.95/grub/asmstub.c
--- grub-0.5.95-orig/grub/asmstub.c	Sun Aug 27 05:45:27 2000
+++ grub-0.5.95/grub/asmstub.c	Sun Aug 27 05:46:10 2000
@@ -85,6 +85,7 @@
 
 unsigned long install_partition = 0x20000;
 unsigned long boot_drive = 0;
+unsigned long stage2_sector2 = 0;
 char version_string[] = VERSION;
 char config_file[128] = "/boot/grub/menu.lst"; /* FIXME: arbitrary */
 
diff -ru grub-0.5.95-orig/stage2/asm.S grub-0.5.95/stage2/asm.S
--- grub-0.5.95-orig/stage2/asm.S	Sun Aug 27 05:45:27 2000
+++ grub-0.5.95/stage2/asm.S	Sun Aug 27 06:31:30 2000
@@ -73,6 +73,8 @@
 	.long	0xFFFFFF
 VARIABLE(stage2_id)
 	.byte	STAGE2_ID
+VARIABLE(saved_entry)
+	.byte	1
 VARIABLE(force_lba)
 	.byte	0
 VARIABLE(version_string)
@@ -112,6 +114,9 @@
 	ADDR32	movb	%dl, EXT_C(boot_drive)
 #endif
 
+	/* save the second sector address for savedefault */
+	ADDR32 movl	%ecx,EXT_C(stage2_sector2)
+	
 	/* reset disk system (%ah = 0) */
 	int	$0x13
 
@@ -2095,6 +2100,10 @@
 #else
 	.long	0
 #endif
+
+/* sector # for stage 2, sector 2 for savedefault */
+VARIABLE(stage2_sector2)
+	.long	0
 
 	/* an address can only be long-jumped to if it is in memory, this
 	   is used by multiple routines */
diff -ru grub-0.5.95-orig/stage2/builtins.c grub-0.5.95/stage2/builtins.c
--- grub-0.5.95-orig/stage2/builtins.c	Sun Aug 27 05:45:27 2000
+++ grub-0.5.95/stage2/builtins.c	Sun Aug 27 07:04:01 2000
@@ -697,6 +697,27 @@
 static int
 default_func (char *arg, int flags)
 {
+  if (grub_strcmp (arg, "saved") == 0)
+    {
+      struct geometry geom ;
+      /* Setup */
+      if (get_diskinfo(boot_drive, &geom))
+	{
+	  errnum = ERR_NO_DISK;
+	  return 1;
+	}
+      /* Get original sector 2 from the disk */
+      if (biosdisk (BIOSDISK_READ, boot_drive, &geom,
+		    stage2_sector2, 1, SCRATCHSEG))
+	{
+	  errnum = ERR_READ;
+	  return 1;
+	}
+
+      default_entry = ((unsigned char *) SCRATCHADDR)[STAGE2_SAVED_DEFAULT];
+      return 0;
+    }
+
   if (! safe_parse_maxint (&arg, &default_entry))
     return 1;
 
@@ -709,9 +730,9 @@
   default_func,
   BUILTIN_MENU,
 #if 0
-  "default NUM",
-  "Set the default entry to entry number NUM (if not specified, it is"
-  " 0, the first entry)."
+  "default [NUM | `saved']",
+  "Set the default entry to entry number NUM or to the value saved by"
+  " `savedefault' (if not specified, it is 0, the first entry)."
 #endif
 };
 
@@ -1994,6 +2015,57 @@
 };
 
 
+/* savedefault */
+static int
+savedefault_func (char *arg, int flags)
+{
+  struct geometry geom ;
+
+  /* Setup */
+  if (get_diskinfo(boot_drive, &geom))
+    {
+      errnum = ERR_NO_DISK;
+      return 1;
+    }
+
+  /* Get original sector 2 from the disk */
+  if (biosdisk (BIOSDISK_READ, boot_drive, &geom,
+		stage2_sector2, 1, SCRATCHSEG))
+    {
+      errnum = ERR_READ;
+      return 1;
+    }
+
+  if ( *((unsigned char *) (SCRATCHADDR + STAGE2_SAVED_DEFAULT))
+       != current_entry_number )
+    {
+
+      /* Set the entry number */
+      *((unsigned char *) (SCRATCHADDR + STAGE2_SAVED_DEFAULT))
+	= current_entry_number;
+
+      /* Now flush the block back to disk */
+      if (biosdisk (BIOSDISK_WRITE, boot_drive, &geom,
+		    stage2_sector2, 1, SCRATCHSEG))
+	{
+	  errnum = ERR_WRITE;
+	  return 1;
+	}
+    }
+
+  return 0;
+}
+
+static struct builtin builtin_savedefault =
+{
+  "savedefault",
+  savedefault_func,
+  BUILTIN_CMDLINE,
+  "savedefault",
+  "Set the saved default entry to the current entry."
+  " This is will make \"default saved\" use the current entry."
+};
+
 /* map */
 /* Map FROM_DRIVE to TO_DRIVE.  */
 static int
@@ -3103,6 +3175,7 @@
   &builtin_read,
   &builtin_root,
   &builtin_rootnoverify,
+  &builtin_savedefault,
   &builtin_setkey,
   &builtin_setup,
   &builtin_testload,
diff -ru grub-0.5.95-orig/stage2/shared.h grub-0.5.95/stage2/shared.h
--- grub-0.5.95-orig/stage2/shared.h	Sun Aug 27 05:45:27 2000
+++ grub-0.5.95/stage2/shared.h	Sun Aug 27 06:14:33 2000
@@ -196,7 +196,8 @@
 #define STAGE2_INSTALLPART	0x8
 #define STAGE2_STAGE2_ID	0xc
 #define STAGE2_FORCE_LBA	0xd
-#define STAGE2_VER_STR_OFFS	0xe
+#define STAGE2_SAVED_DEFAULT	0xe
+#define STAGE2_VER_STR_OFFS	0xf
 
 /* Stage 2 identifiers */
 #define STAGE2_ID_STAGE2		0
@@ -424,6 +425,7 @@
 
 extern unsigned long install_partition;
 extern unsigned long boot_drive;
+extern unsigned long stage2_sector2;
 extern unsigned long boot_part_addr;
 extern unsigned long boot_part_offset;
 extern unsigned char force_lba;
@@ -461,6 +463,7 @@
 /* GUI interface variables. */
 extern int fallback_entry;
 extern int default_entry;
+extern int current_entry_number ;
 extern char *password;
 extern int auth;
 extern char commands[];
diff -ru grub-0.5.95-orig/stage2/stage2.c grub-0.5.95/stage2/stage2.c
--- grub-0.5.95-orig/stage2/stage2.c	Sun Aug 27 05:45:27 2000
+++ grub-0.5.95/stage2/stage2.c	Sun Aug 27 05:46:10 2000
@@ -168,6 +168,7 @@
 #endif
 }
 
+int current_entry_number; /* For savedefault */
 static void
 run_menu (char *menu_entries, char *config_entries, int num_entries,
 	  char *heap, int entryno)
@@ -524,6 +525,7 @@
     {
       cls ();
 
+      current_entry_number = entryno ;	/* For savedefault */
       if (config_entries)
 	printf ("  Booting \'%s\'\n\n",
 		get_entry (menu_entries, first_entry + entryno, 0));
diff -ru grub-0.5.95-orig/stage2/start.S grub-0.5.95/stage2/start.S
--- grub-0.5.95-orig/stage2/start.S	Sun Aug 27 05:45:27 2000
+++ grub-0.5.95/stage2/start.S	Sun Aug 27 06:31:27 2000
@@ -73,7 +73,12 @@
 	
 	/* this sets up for the first run through "bootloop" */
 	movw	$ABS(firstlist - BOOTSEC_LISTSIZE), %di
-
+	
+	/* Save the second sector # for setdefault */
+	movl	(%di),%eax
+	popw	%dx
+	pushl	%eax
+	pushw	%dx
 
         /* this is the loop for reading the secondary boot-loader in */
 bootloop:
@@ -313,6 +318,7 @@
 
 bootit:
 	popw	%dx	/* this makes sure %dl is our "boot" drive */
+	popl	%ecx	/* Pass the stage2 second sector address on as well */
 #ifdef STAGE1_5
 	ljmp	$0, $0x2200
 #else /* ! STAGE1_5 */
@@ -371,6 +377,7 @@
 	cmpb	$0, %al
 	jne	1b	/* if not end of string, jmp to display */
 	ret
+
 lastlist:
 
 /*


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-questions" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?14766.23980.183756.126206>