Subject: port-mac68k/4999: port-mac68k disklabel bug fix + DOS partition
To: None <gnats-bugs@gnats.netbsd.org>
From: Ken Nakata <kenn@physics.rutgers.edu>
List: netbsd-bugs
Date: 02/15/1998 21:05:31
>Number: 4999
>Category: port-mac68k
>Synopsis: a bug fix and DOS partition handling to disksubr.c
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: gnats-admin (GNATS administrator)
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sun Feb 15 18:20:01 1998
>Last-Modified:
>Originator: Ken Nakata
>Organization:
Rutgers - The State University of New Jersey
>Release: NetBSD-current tar balls of Feb 14 1998
>Environment:
Macintosh Quadra 840AV
MacOS 7.5.5
Booter 1.11.1
SCSI devices:
0: Quantum LPS270S - 1 MacOS partition
1: Quantum Fireball1080S - 4 A/UX & 1 MacOS partitions
2: Fujitsu M2694ES-512 - 3 A/UX & 1 MacOS partitions
4: Pioneer CD-ROM DR-U12X
5: Iomega Zip-100
System: NetBSD phil 1.3C NetBSD 1.3C (GENERIC) #1: Sun Feb 15 17:15:44 EST 1998 hacker@phil:/s/src/sys/arch/mac68k/compile/GENERIC mac68k
>Description:
There's a bug in disksubr.c that omits the 'c' partition if there are
too few (<3) partitions on the disk. Precise reason is unknown but it seems
to cause kernel to panic w/illegal insn.
Also, DOS partition table handling is added to disksubr.c, primarily
to mount DOS-formatted Zip and possibly other removable media.
>How-To-Repeat:
"disklabel sdX" where sdX is a disk which has LESS THAN 3 partitions.
With high probability kernel will panic. Kernel debugger backtrace gives
little information.
>Fix:
The bug fix is in the second hunk. The others are for DOS partition
handling.
*** orig/src/sys/arch/mac68k/mac68k/disksubr.c Tue Jan 13 08:45:14 1998
--- src/sys/arch/mac68k/mac68k/disksubr.c Sun Feb 15 17:14:32 1998
***************
*** 109,114 ****
--- 109,116 ----
__P((struct partmapentry *, int, struct disklabel *, int, int, int *));
static char *read_mac_label __P((dev_t, void (*)(struct buf *),
register struct disklabel *, struct cpu_disklabel *));
+ static char *read_dos_label __P((dev_t, void (*)(struct buf *),
+ register struct disklabel *, struct cpu_disklabel *));
/*
* Find an entry in the disk label that is unused and return it
***************
*** 452,458 ****
break;
}
}
! lp->d_npartitions = maxslot+1;
done:
bp->b_flags = B_INVAL | B_AGE | B_READ;
--- 454,460 ----
break;
}
}
! lp->d_npartitions = ((maxslot >= RAW_PART) ? maxslot : RAW_PART) + 1;
done:
bp->b_flags = B_INVAL | B_AGE | B_READ;
***************
*** 460,465 ****
--- 462,539 ----
return msg;
}
+ #ifdef MSDOSFS
+ static int fat_types[] = { DOSPTYP_FAT12, DOSPTYP_FAT16S,
+ DOSPTYP_FAT16B, DOSPTYP_FAT16C, -1 };
+
+ /* Read MS-DOS partition table.
+ *
+ * XXX -
+ * Since FFS is endian sensitive, we pay no effort in attempting to
+ * dig up *BSD/i386 disk labels that may be present on the disk.
+ * Hence anything but DOS partitions is treated as unknown FS type, but
+ * this should suffice to mount_msdos Zip and other removable media.
+ */
+ static char *
+ read_dos_label(dev, strat, lp, osdep)
+ dev_t dev;
+ void (*strat)(struct buf *);
+ register struct disklabel *lp;
+ struct cpu_disklabel *osdep;
+ {
+ struct dos_partition *dp;
+ struct partition *pp;
+ struct buf *bp;
+ char *msg = NULL;
+ int i, *ip, slot, maxslot = 0;
+
+ /* get a buffer and initialize it */
+ bp = geteblk((int)lp->d_secsize);
+ bp->b_dev = dev;
+
+ /* read master boot record */
+ bp->b_blkno = DOSBBSECTOR;
+ bp->b_bcount = lp->d_secsize;
+ bp->b_flags = B_BUSY | B_READ;
+ bp->b_cylin = DOSBBSECTOR / lp->d_secpercyl;
+ (*strat)(bp);
+
+ /* if successful, wander through dos partition table */
+ if (biowait(bp)) {
+ msg = "dos partition I/O error";
+ goto done;
+ } else {
+ /* XXX */
+ dp = (struct dos_partition *)(bp->b_data + DOSPARTOFF);
+ for (i = 0; i < NDOSPART; i++, dp++) {
+ if (dp->dp_typ != 0) {
+ u_int8_t fstype = FS_OTHER;
+
+ slot = getFreeLabelEntry(lp);
+ if (slot > maxslot) maxslot = slot;
+
+ for (ip = fat_types; *ip != -1; ip++) {
+ if (dp->dp_typ == *ip) {
+ fstype = FS_MSDOS;
+ break;
+ }
+ }
+ pp = &lp->d_partitions[slot];
+ pp->p_fstype = fstype;
+ pp->p_offset = bswap32(dp->dp_start);
+ pp->p_size = bswap32(dp->dp_size);
+ }
+ }
+ }
+ lp->d_npartitions = ((maxslot >= RAW_PART) ? maxslot : RAW_PART) + 1;
+
+ done:
+ bp->b_flags |= B_INVAL;
+ brelse(bp);
+ return (msg);
+ }
+ #endif /* MSDOSFS */
+
/*
* Attempt to read a disk label from a device using the indicated stategy
* routine. The label must be partly set up before this: secpercyl and
***************
*** 506,511 ****
--- 580,590 ----
sbSigp = (u_int16_t *) bp->b_un.b_addr;
if (*sbSigp == 0x4552) {
msg = read_mac_label(dev, strat, lp, osdep);
+ #ifdef MSDOSFS
+ } else if (*(u_int16_t *)(bp->b_data + 510) == 0x55aa
+ /* XXX */) {
+ msg = read_dos_label(dev, strat, lp, osdep);
+ #endif /* MSDOSFS */
} else {
dlp = (struct disklabel *)(bp->b_un.b_addr + 0);
if (dlp->d_magic == DISKMAGIC) {
*** orig/src/sys/arch/mac68k/include/disklabel.h Sun May 5 07:31:44 1996
--- src/sys/arch/mac68k/include/disklabel.h Sun Feb 15 00:11:01 1998
***************
*** 38,43 ****
--- 38,71 ----
#define MAXPARTITIONS 8 /* number of partitions */
#define RAW_PART 2 /* raw partition: xx?c */
+ #ifdef MSDOSFS
+ /* DOS partition table -- located in boot block */
+ #define DOSBBSECTOR 0 /* DOS boot block relative sector # */
+ #define DOSPARTOFF 446
+ #define NDOSPART 4
+
+ struct dos_partition {
+ unsigned char dp_flag; /* bootstrap flags */
+ unsigned char dp_shd; /* starting head */
+ unsigned char dp_ssect; /* starting sector */
+ unsigned char dp_scyl; /* starting cylinder */
+ unsigned char dp_typ; /* partition type (see below) */
+ unsigned char dp_ehd; /* end head */
+ unsigned char dp_esect; /* end sector */
+ unsigned char dp_ecyl; /* end cylinder */
+ unsigned long dp_start; /* absolute starting sector number */
+ unsigned long dp_size; /* partition size in sectors */
+ };
+
+ /* Known DOS partition types. */
+ #define DOSPTYP_386BSD 0xa5 /* 386BSD partition type */
+ #define DOSPTYP_NETBSD DOSPTYP_386BSD /* NetBSD partition type (XXX) */
+ #define DOSPTYP_FAT12 0x1 /* 12-bit FAT */
+ #define DOSPTYP_FAT16S 0x4 /* 16-bit FAT, less than 32M */
+ #define DOSPTYP_FAT16B 0x6 /* 16-bit FAT, more than 32M */
+ #define DOSPTYP_FAT16C 0xe /* 16-bit FAT, CHS-mapped */
+ #endif /* MSDOSFS */
+
/* Just a dummy */
struct cpu_disklabel {
int cd_dummy; /* must have one element. */
>Audit-Trail:
>Unformatted: