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: