>Number:         158358
>Category:       kern
>Synopsis:       [patch] allow /boot/loader to work from an MBR extended 
>partition
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Jun 28 01:00:20 UTC 2011
>Closed-Date:
>Last-Modified:
>Originator:     Gyrd Thane Lange
>Release:        FreeBSD 9.0-CURRENT amd64
>Organization:
>Environment:
FreeBSD parvati.thanelange.no 9.0-CURRENT FreeBSD 9.0-CURRENT #7 r221413M: Thu 
May 5 00:22:25 CEST 2011 
r...@parvati.thanelange.no:/usr/obj/usr/src/sys/PARVATI amd64
>Description:
http://parvati.thanelange.no/freebsd/boot_loader/

The FreeBSD loader has since a very long time ago attempted to work
with MBR extended partitions but a simple logical error has prevented
it from succeeding:

How it is supposed to work.

-----
| 1 |
-----
| 2 | --
-----   |
        |
        |
        |
----- <-
| 5 |
-----
|   | --
-----   |
        |
        |
        |
----- <-
| 6 |
-----
|   |
-----


How /boot/loader (incorrectly) works.

-----
| 1 |
-----
| 2 | --
-----   |
        |
        |
        |
----- <-
| 5 |
-----
| 6 | --
-----   |
        |
        |
        |
----- <-
| 7 |
-----
| 8 |
-----
>How-To-Repeat:
Install FreeBSD in an MBR extended partition. (It is easily doable using 
command line tools.)

Attempt to boot.

Observe that the /boot/loader does not find the desired partition.
>Fix:
Using the attached patch:
patch -d /usr/src/sys/boot/i386/libi386/ < boot_loader.diff

Patch is also found here:
http://parvati.thanelange.no/freebsd/boot_loader/boot_loader.diff


Patch attached with submission follows:

--- biosdisk.c.orig     2007-11-13 00:53:43.000000000 +0100
+++ biosdisk.c  2007-12-29 10:35:30.000000000 +0100
@@ -162,7 +162,8 @@
 static void    bd_closedisk(struct open_disk *od);
 static int     bd_open_mbr(struct open_disk *od, struct i386_devdesc *dev);
 static int     bd_bestslice(struct open_disk *od);
-static void    bd_checkextended(struct open_disk *od, int slicenum);
+static void    bd_checkextended(struct open_disk *od, struct dos_partition 
*dp, 
+            struct dos_partition *primary_dp);
 static int     bd_open_gpt(struct open_disk *od, struct i386_devdesc *dev);
 static struct gpt_part *bd_best_gptpart(struct open_disk *od);
 
@@ -381,6 +382,13 @@
 
        switch (dp->dp_typ) {
        case DOSPTYP_386BSD:
+               if (verbose)
+                       sprintf(line, "%s: BSD     %.6dMB (%d - %d)\n",
+                           prefix, dp->dp_size / 2048,
+                           dp->dp_start, dp->dp_start + dp->dp_size);
+               else
+                       sprintf(line, "%s: BSD\n", prefix);
+               pager_output(line);
                bd_printbsdslice(od, (daddr_t)dp->dp_start, prefix, verbose);
                return;
        case DOSPTYP_LINSWP:
@@ -626,7 +634,7 @@
       sizeof(struct dos_partition) * NDOSPART);
     od->od_nslices = 4;                        /* extended slices start here */
     for (i = 0; i < NDOSPART; i++)
-        bd_checkextended(od, i);
+        bd_checkextended(od, &od->od_slicetab[i], &od->od_slicetab[i]);
     od->od_flags |= BD_PARTTABOK;
     dptr = &od->od_slicetab[0];
 
@@ -728,16 +736,12 @@
 }
 
 static void
-bd_checkextended(struct open_disk *od, int slicenum)
+bd_checkextended(struct open_disk *od, struct dos_partition *dp, struct 
dos_partition *primary_dp)
 {
        char    buf[BIOSDISK_SECSIZE];
-       struct dos_partition *dp;
-       u_int base;
-       int i, start, end;
-
-       dp = &od->od_slicetab[slicenum];
-       start = od->od_nslices;
-
+       int i;
+       struct dos_partition *base_dp;
+       
        if (dp->dp_size == 0)
                goto done;
        if (dp->dp_typ != DOSPTYP_EXT)
@@ -748,24 +752,22 @@
                DEBUG("no magic in extended table");
                goto done;
        }
-       base = dp->dp_start;
+       base_dp = dp;
        dp = (struct dos_partition *)(&buf[DOSPARTOFF]);
        for (i = 0; i < NDOSPART; i++, dp++) {
                if (dp->dp_size == 0)
                        continue;
                if (od->od_nslices == NEXTDOSPART)
                        goto done;
-               dp->dp_start += base;
-               bcopy(dp, &od->od_slicetab[od->od_nslices], sizeof(*dp));
-               od->od_nslices++;
+               if (dp->dp_typ == DOSPTYP_EXT) {
+                       dp->dp_start += primary_dp->dp_start;
+                       bd_checkextended(od, dp, primary_dp);
+               } else {
+                       dp->dp_start += base_dp->dp_start;
+                       bcopy(dp, &od->od_slicetab[od->od_nslices], 
sizeof(*dp));
+                       od->od_nslices++;
+               }
        }
-       end = od->od_nslices;
-
-       /*
-        * now, recursively check the slices we just added
-        */
-       for (i = start; i < end; i++)
-               bd_checkextended(od, i);
 done:
        return;
 }


>Release-Note:
>Audit-Trail:
>Unformatted:
_______________________________________________
freebsd-bugs@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bugs
To unsubscribe, send any mail to "freebsd-bugs-unsubscr...@freebsd.org"

Reply via email to