Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 28 Jun 2011 00:58:16 GMT
From:      Gyrd Thane Lange <gyrd-se@thanelange.no>
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   kern/158358: [patch] allow /boot/loader to work from an MBR extended partition
Message-ID:  <201106280058.p5S0wGdA073444@red.freebsd.org>
Resent-Message-ID: <201106280100.p5S10LKP039907@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>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 root@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:



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