Subject: bin/12677: fdisk(8) cannot show extended partion info correctly.
To: None <gnats-bugs@gnats.netbsd.org>
From: None <minoura@netbsd.org>
List: netbsd-bugs
Date: 04/16/2001 15:34:27
>Number:         12677
>Category:       bin
>Synopsis:       fdisk(8) cannot show extended partion info correctly.
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    bin-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Apr 15 23:35:00 PDT 2001
>Closed-Date:
>Last-Modified:
>Originator:     Minoura Makoto
>Release:        Mon Apr  2 16:20:31 UTC 2001
>Organization:
>Environment:
System: NetBSD daisy 1.5T NetBSD 1.5T (DAISY) #179: Tue Apr 10 16:25:20 JST 2001 root@daisy:/usr/obj/sys/arch/i386/compile/DAISY i386
Architecture: i386
Machine: i386
>Description:
-current fdisk(8) can display the extended partition information.
But when the extended partition has more than or equal to 3 logical
volumes, it gives up to show that information with the error message:

fdisk: invalid extended partition table found

even when all the EBR's are correct.
>How-To-Repeat:
wd1 is a 30MB CF card.
wd1 at wdc2 channel 0 drive 0: <SunDisk SDCFB-30>
wd1: drive supports 1-sector PIO transfers, LBA addressing
wd1: 29376 KB, 306 cyl, 6 head, 32 sec, 512 bytes/sect x 58752 sectors

It has one primary FAT12 partition of 1MB and the rest is an extended
partition in which there are 4 logical FAT12 volumes of 2MB, 4MB,
8MB, 4MB, respectively.

# fdisk wd1
NetBSD disklabel disk geometry:
cylinders: 28 heads: 64 sectors/track: 32 (2048 sectors/cylinder)

BIOS disk geometry:
cylinders: 306 heads: 6 sectors/track: 32 (192 sectors/cylinder)

Partition table:
0: sysid 1 (Primary DOS with 12 bit FAT)
    start 32, size 2080 (1 MB), flag 0x0
        beg: cylinder    0, head   1, sector  1
        end: cylinder   10, head   5, sector 32
1: sysid 5 (Extended partition)
    start 2112, size 56640 (27 MB), flag 0x0
        beg: cylinder   11, head   0, sector  1
        end: cylinder  305, head   5, sector 32
    Extended partition table:
        0: sysid 1 (Primary DOS with 12 bit FAT)
            start 2144, size 4192 (2 MB), flag 0x0
                beg: cylinder   11, head   1, sector  1
                end: cylinder   32, head   5, sector 32
        1: sysid 5 (Extended partition)
            start 6336, size 8256 (4 MB), flag 0x0
                beg: cylinder   33, head   0, sector  1
                end: cylinder   75, head   5, sector 32
            Extended partition table:
                0: sysid 1 (Primary DOS with 12 bit FAT)
                    start 6368, size 8224 (4 MB), flag 0x0
                        beg: cylinder   33, head   1, sector  1
                        end: cylinder   75, head   5, sector 32
                1: sysid 5 (Extended partition)
                    start 18816, size 16512 (8 MB), flag 0x0
                          ~~~~~wrong!!
                        beg: cylinder   76, head   0, sector  1
                        end: cylinder  161, head   5, sector 32
                    Extended partition table:
fdisk: invalid extended partition table found
                2: <UNUSED>
                3: <UNUSED>
        2: <UNUSED>
        3: <UNUSED>
2: <UNUSED>
3: <UNUSED>
#

The underlined information is wrong; in the EBR, the partition 0 start
address is recorded as an offset from that EBR, but the partition 1
start address is recorded as an offset from the start of the extended
partition (from observation; I am not sure about the specification).

Correct information is like this:
	[snip]
                1: sysid 5 (Extended partition)
                    start 14592, size 16512 (8 MB), flag 0x0
                        beg: cylinder   76, head   0, sector  1
                        end: cylinder  161, head   5, sector 32
                    Extended partition table:
                        0: sysid 1 (Primary DOS with 12 bit FAT)
                            start 14624, size 16480 (8 MB), flag 0x0
                                beg: cylinder   76, head   1, sector  1
                                end: cylinder  161, head   5, sector 32
                        1: sysid 5 (Extended partition)
                            start 31104, size 8256 (4 MB), flag 0x0
                                beg: cylinder  162, head   0, sector  1
                                end: cylinder  204, head   5, sector 32
                            Extended partition table:
                                0: sysid 1 (Primary DOS with 12 bit FAT)
                                    start 31136, size 8224 (4 MB), flag 0x0
                                        beg: cylinder  162, head   1, sector  1
                                        end: cylinder  204, head   5, sector 32
                                1: <UNUSED>
                                2: <UNUSED>
                                3: <UNUSED>
                        2: <UNUSED>
                        3: <UNUSED>
                2: <UNUSED>
                3: <UNUSED>
        2: <UNUSED>
        3: <UNUSED>
2: <UNUSED>
3: <UNUSED>

>Fix:
Index: fdisk.c
===================================================================
RCS file: /cvsroot/basesrc/sbin/fdisk/fdisk.c,v
retrieving revision 1.45
diff -u -r1.45 fdisk.c
--- fdisk.c	2000/12/24 13:32:41	1.45
+++ fdisk.c	2001/04/16 06:09:38
@@ -262,7 +262,7 @@
 void	usage(void);
 void	print_s0(int);
 void	print_part(int);
-void	print_mbr_partition(struct mbr_partition *, off_t, int);
+void	print_mbr_partition(struct mbr_partition *, off_t, off_t, int);
 int	read_boot(const char *, void *, size_t);
 void	init_sector0(int, int);
 void	intuit_translated_geometry(void);
@@ -540,17 +540,21 @@
 		printf("PART%dESEC=%d\n", part, MBR_PSECT(partp->mbrp_esect));
 		return;
 	}
-	print_mbr_partition(partp, 0, 0);
+	print_mbr_partition(partp, 0, 0, 0);
 }
 
 void
-print_mbr_partition(struct mbr_partition *partp, off_t offset, int indent)
+print_mbr_partition(struct mbr_partition *partp,
+		    off_t offset, off_t exoffset, int indent)
 {
 	int	empty;
 	off_t	start;
 
 	empty = (partp->mbrp_typ == 0);
-	start = (off_t)getlong(&partp->mbrp_start) + offset;
+	if (MBR_IS_EXTENDED(partp->mbrp_typ))
+		start = (off_t)getlong(&partp->mbrp_start) + exoffset;
+	else
+		start = (off_t)getlong(&partp->mbrp_start) + offset;
 	if (empty) {
 		printf("<UNUSED>\n");
 		return;
@@ -578,9 +582,12 @@
 		if (read_s0(start, &eboot) == -1)
 			return;
 		indent += 8;
+		if (exoffset == 0)
+			exoffset = start;
 		for (part = 0; part < NMBRPART; part++) {
 			printf("%*s%d: ", indent, "", part);
-			print_mbr_partition(&eboot.parts[part], start, indent);
+			print_mbr_partition(&eboot.parts[part],
+					    start, exoffset, indent);
 		}
 	}
 }
>Release-Note:
>Audit-Trail:
>Unformatted: