Subject: port-i386/15295: pbr boot code should load boot from same partition it was loaded from
To: None <gnats-bugs@gnats.netbsd.org>
From: None <david@l8s.co.uk>
List: netbsd-bugs
Date: 01/19/2002 04:50:22
>Number:         15295
>Category:       port-i386
>Synopsis:       pbr boot code should load boot from same partition it was loaded from
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    port-i386-maintainer
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sat Jan 19 04:50:00 PST 2002
>Closed-Date:
>Last-Modified:
>Originator:     David Laight
>Release:        current
>Organization:
>Environment:
NetBSD snowdrop 1.5ZA NetBSD 1.5ZA (GENERIC) #1: Wed Jan 16 17:59:39 GMT 2002
     dsl@snowdrop:/usr/bsd-current/src/sys/arch/i386/compile/GENERIC i386

>Description:
The pbr (partition boot code) re-reads the partition table in order
to find the boot partition (to load the rest of itself and hence
the boot program).

If there is more that one netbsd partition on the disk, the mbs code
reads the wrong one.  I've given a fixed mbr_bootsel.S in port-i386/14748
which passes the sector number through to the pbr code.

The fixes here:
1) start_bootsect.S: Scan the partition table giving preference to the
   sector number passed in from the mbr code, pass to bootsectmain()
2) bootsectmain.c: Dump the sector number int a global (as it does
   with the device number)
3) biosdisk.c (biosdevopen): Give preference for passed in sector
   number when locating netbsd partition.

The sector number is already passed into the kernel
(which ignores it... - minor change coming soon)

I've also spotted an incorrect instruction in start_bootsel.S that will corrupt
memory - this may, or may not, ever matter.
I've generated a little space in pbr code by using some 16bit load
instructions.  It's still got less space than the mbr_bootsel code
and does rather less!
>How-To-Repeat:

>Fix:
The diff for start_bootsect.S would be large, the updated file can be found at:
http://www.btinternet.com/~david.laight/netbsd/start_bootsect.S

cvs diff biosdisk.c
Index: biosdisk.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/i386/stand/lib/biosdisk.c,v
retrieving revision 1.15
diff -u -r1.15 biosdisk.c
--- biosdisk.c  2001/07/07 22:57:57     1.15
+++ biosdisk.c  2002/01/19 12:37:29
@@ -95,6 +95,8 @@
 
 #define        RF_PROTECTED_SECTORS    64      /* XXX refer to <.../rf_optnames.h> */
 
+int boot_biossector;   /* disk sector partition might have started in */
+
 int 
 biosdiskstrategy(devdata, flag, dblk, size, buf, rsize)
        void           *devdata;
@@ -192,11 +194,15 @@
        }
        sector = -1;
        dptr = (struct mbr_partition *) & d->buf[MBR_PARTOFF];
-       /* Look for NetBSD partition ID */
+       /* Look for NetBSD partition ID  and partition we booted from */
        for (i = 0; i < NMBRPART; i++, dptr++)
                if (dptr->mbrp_typ == MBR_PTYPE_NETBSD) {
-                       sector = dptr->mbrp_start;
-                       break;
+                       if (boot_biossector == dptr->mbrp_start) {
+                               sector = dptr->mbrp_start;
+                               break;
+                       }
+                       if (sector == -1)
+                               sector = dptr->mbrp_start;
                }
 #ifdef COMPAT_386BSD_MBRPART
        if (sector == -1) {

 cvs diff bootsectmain.c
Index: bootsectmain.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/i386/stand/lib/crt/bootsect/bootsectmain.c,v
retrieving revision 1.3
diff -u -r1.3 bootsectmain.c
--- bootsectmain.c      1999/04/14 10:57:59     1.3
+++ bootsectmain.c      2002/01/19 12:44:26
@@ -45,16 +45,18 @@
 #include "bbinfo.h"
 
 int boot_biosdev; /* exported */
-void bootsectmain __P((int));
+int boot_biossector; /* exported */
+void bootsectmain __P((int,int));
 
 extern struct fraglist fraglist;
 extern char edata[], end[];
 
 extern void main __P((void));
 
+/* bios_sector is a hint..... */
+
 void
-bootsectmain(biosdev)
-       int biosdev;
+bootsectmain(int biosdev, int bios_sector )
 {
        struct biosdisk_ll d;
        int i;
@@ -88,5 +90,6 @@
 
        /* call main() */
        boot_biosdev = biosdev;
+       boot_biossector = bios_sector;
        main();
 }


>Release-Note:
>Audit-Trail:
>Unformatted: