On Wed, Dec 06, 2006 at 04:44:32AM +0000, Mikolaj Kucharski wrote:
> On Tue, Dec 05, 2006 at 09:27:39PM -0700, Chris Kuethe wrote:
> > On 12/5/06, Mikolaj Kucharski <[EMAIL PROTECTED]> wrote:
> > >sd0 at scsibus1 targ 1 lun 0: <Apple, iPod, 1.62> SCSI0 0/direct removable
> > >sd0: 76319MB, 19079 cyl, 64 head, 32 sec, 2048 bytes/sec, 39075372 sec 
> > >total
> > 
> > 80GB. Maybe it's one of the ipods with 2K sectors. Look in the
> > archives for an experimental patch to possibly make this work.
> 
> It looks like perfect answer. Thanks.
> 
> http://marc.theaimsgroup.com/?t=116345681100004&r=1&w=2

I used all patches from thread above (sd, msdosfs, and fdisk patch) and
iPod and fdisk are working like a charm. Thanks!

$ sysctl -n kern.version
OpenBSD 4.0-current (ACPI) #8: Wed Dec  6 03:34:00 MST 2006
    [EMAIL PROTECTED]:/usr/src/sys/arch/i386/compile/ACPI


Patches attached in this mail too.

-- 
best regards
q#
Index: sbin/fdisk/cmd.c
===================================================================
RCS file: /cvs/src/sbin/fdisk/cmd.c,v
retrieving revision 1.42
diff -u -r1.42 cmd.c
--- sbin/fdisk/cmd.c    2006/07/27 04:06:13     1.42
+++ sbin/fdisk/cmd.c    2006/12/06 18:34:36
@@ -46,7 +46,7 @@
        char buf[DEV_BSIZE];
 
        /* Copy template MBR */
-       MBR_make(tt, buf);
+       MBR_make(tt, buf, disk->real->sec_size);
        MBR_parse(disk, buf, mbr->offset, mbr->reloffset, mbr);
 
        MBR_init(disk, mbr);
@@ -321,8 +321,8 @@
        printf("Writing MBR at offset %d.\n", offset);
 
        fd = DISK_open(disk->name, O_RDWR);
-       MBR_make(mbr, mbr_buf);
-       if (MBR_write(fd, offset, mbr_buf) != -1)
+       MBR_make(mbr, mbr_buf, disk->real->sec_size);
+       if (MBR_write(fd, offset, mbr_buf, disk->real->sec_size) != -1)
                ret = CMD_CLEAN;
        close(fd);
        return (ret);
Index: sbin/fdisk/disk.c
===================================================================
RCS file: /cvs/src/sbin/fdisk/disk.c,v
retrieving revision 1.25
diff -u -r1.25 disk.c
--- sbin/fdisk/disk.c   2006/11/19 20:17:12     1.25
+++ sbin/fdisk/disk.c   2006/12/06 18:34:36
@@ -99,11 +99,21 @@
                        lm->heads = dl.d_ntracks;
                        lm->sectors = dl.d_nsectors;
                        lm->size = dl.d_secperunit;
+                       lm->sec_size = dl.d_secsize;
                        unit_types[SECTORS].conversion = dl.d_secsize;
                }
                DISK_close(fd);
        }
 
+       if (lm && lm->sec_size != 512 && lm->sec_size != 1024 &&
+           lm->sec_size != 2048 && lm->sec_size != 4096 &&
+           lm->sec_size != 8192) {
+
+               warnx("Invalid sector size %d, setting to %d", lm->sec_size,
+                   DEV_BSIZE);
+               lm->sec_size = DEV_BSIZE;
+       }
+
        return (lm);
 }
 
@@ -157,6 +167,7 @@
        bm->heads = di.bios_heads;
        bm->sectors = di.bios_sectors;
        bm->size = di.bios_cylinders * di.bios_heads * di.bios_sectors;
+       bm->sec_size = DEV_BSIZE;
        return (bm);
 }
 #else
@@ -187,6 +198,13 @@
        disk->label = DISK_getlabelmetrics(disk->name);
        disk->bios = DISK_getbiosmetrics(disk->name);
 
+       /*
+        * If we have a disklabel, the kernel tells us what size sector
+        * this raw device has.  As such, use it.  Yes, not pretty.
+        */
+       if (disk->label && disk->bios)
+               disk->bios->sec_size = disk->label->sec_size;
+
        /* If user supplied, use that */
        if (user) {
                disk->real = user;
@@ -236,11 +254,12 @@
        size = ((double)disk->real->size * unit_types[SECTORS].conversion) /
            unit_types[i].conversion;
        printf("Disk: %s\t", disk->name);
-       if (disk->real)
-               printf("geometry: %d/%d/%d [%.0f %s]\n", disk->real->cylinders,
+       if (disk->real) {
+               printf("geometry: %d/%d/%d [%.0f %s] ", disk->real->cylinders,
                    disk->real->heads, disk->real->sectors, size,
                    unit_types[i].lname);
-       else
+               printf("(%d byte sectors)\n", disk->real->sec_size);
+       } else
                printf("geometry: <none>\n");
 
        return (0);
Index: sbin/fdisk/disk.h
===================================================================
RCS file: /cvs/src/sbin/fdisk/disk.h,v
retrieving revision 1.8
diff -u -r1.8 disk.h
--- sbin/fdisk/disk.h   2004/08/03 09:22:03     1.8
+++ sbin/fdisk/disk.h   2006/12/06 18:34:36
@@ -34,6 +34,7 @@
        u_int32_t heads;
        u_int32_t sectors;
        u_int32_t size;
+       u_int32_t sec_size;
 } DISK_metrics;
 
 typedef struct _disk_t {
Index: sbin/fdisk/fdisk.c
===================================================================
RCS file: /cvs/src/sbin/fdisk/fdisk.c,v
retrieving revision 1.46
diff -u -r1.46 fdisk.c
--- sbin/fdisk/fdisk.c  2006/11/09 00:01:10     1.46
+++ sbin/fdisk/fdisk.c  2006/12/06 18:34:43
@@ -78,8 +78,10 @@
        char *mbrfile = NULL;
 #endif
        mbr_t mbr;
-       char mbr_buf[DEV_BSIZE];
+       char mbr_buf[MBR_MAX_SIZE];
 
+       memset(mbr_buf, 0, sizeof(mbr_buf));
+
        while ((ch = getopt(argc, argv, "ieuf:c:h:s:y")) != -1) {
                const char *errstr;
 
@@ -160,9 +162,9 @@
                mbrfile == NULL;
        }
        if (mbrfile == NULL) {
-               memcpy(mbr_buf, builtin_mbr, sizeof(mbr_buf));
+               memcpy(mbr_buf, builtin_mbr, DEV_BSIZE);
        } else {
-               MBR_read(fd, 0, mbr_buf);
+               MBR_read(fd, 0, mbr_buf, DEV_BSIZE);
                close(fd);
        }
        MBR_parse(&disk, mbr_buf, 0, 0, &mbr);
Index: sbin/fdisk/mbr.c
===================================================================
RCS file: /cvs/src/sbin/fdisk/mbr.c,v
retrieving revision 1.22
diff -u -r1.22 mbr.c
--- sbin/fdisk/mbr.c    2006/05/29 05:09:36     1.22
+++ sbin/fdisk/mbr.c    2006/12/06 18:34:43
@@ -97,6 +97,7 @@
        mbr->offset = offset;
        mbr->reloffset = reloff;
        mbr->signature = getshort(&mbr_buf[MBR_SIG_OFF]);
+       memcpy(mbr->rest, mbr_buf+DEV_BSIZE, disk->real->sec_size - DEV_BSIZE);
 
        for (i = 0; i < NDOSPART; i++)
                PRT_parse(disk, &mbr_buf[MBR_PART_OFF + MBR_PART_SIZE * i],
@@ -104,12 +105,13 @@
 }
 
 void
-MBR_make(mbr_t *mbr, char *mbr_buf)
+MBR_make(mbr_t *mbr, char *mbr_buf, int size)
 {
        int i;
 
        memcpy(mbr_buf, mbr->code, MBR_CODE_SIZE);
        putshort(&mbr_buf[MBR_SIG_OFF], mbr->signature);
+       memcpy(mbr_buf+DEV_BSIZE, mbr->rest, size - DEV_BSIZE);
 
        for (i = 0; i < NDOSPART; i++)
                PRT_make(&mbr->part[i], mbr->offset, mbr->reloffset,
@@ -132,19 +134,19 @@
 }
 
 int
-MBR_read(int fd, off_t where, char *buf)
+MBR_read(int fd, off_t where, char *buf, int size)
 {
        off_t off;
        ssize_t len;
 
-       where *= DEV_BSIZE;
+       where *= size;
        off = lseek(fd, where, SEEK_SET);
        if (off != where)
                return (-1);
-       len = read(fd, buf, DEV_BSIZE);
+       len = read(fd, buf, size);
        if (len == -1)
                return (-1);
-       if (len != DEV_BSIZE) {
+       if (len != size) {
                /* short read */
                errno = EIO;
                return (-1);
@@ -153,19 +155,19 @@
 }
 
 int
-MBR_write(int fd, off_t where, char *buf)
+MBR_write(int fd, off_t where, char *buf, int size)
 {
        off_t off;
        ssize_t len;
 
-       where *= DEV_BSIZE;
+       where *= size;
        off = lseek(fd, where, SEEK_SET);
        if (off != where)
                return (-1);
-       len = write(fd, buf, DEV_BSIZE);
+       len = write(fd, buf, size);
        if (len == -1)
                return (-1);
-       if (len != DEV_BSIZE) {
+       if (len != size) {
                /* short write */
                errno = EIO;
                return (-1);
@@ -182,11 +184,12 @@
 MBR_pcopy(disk_t *disk, mbr_t *mbr)
 {
        int i, fd, offset = 0, reloff = 0;
+       int size = disk->real->sec_size;
        mbr_t mbrd;
-       char mbr_disk[DEV_BSIZE];
+       char mbr_disk[size];
 
        fd = DISK_open(disk->name, O_RDONLY);
-       MBR_read(fd, offset, mbr_disk);
+       MBR_read(fd, offset, mbr_disk, size);
        DISK_close(fd);
        MBR_parse(disk, mbr_disk, offset, reloff, &mbrd);
        for (i = 0; i < NDOSPART; i++) {
Index: sbin/fdisk/mbr.h
===================================================================
RCS file: /cvs/src/sbin/fdisk/mbr.h,v
retrieving revision 1.11
diff -u -r1.11 mbr.h
--- sbin/fdisk/mbr.h    2003/06/03 01:13:19     1.11
+++ sbin/fdisk/mbr.h    2006/12/06 18:34:43
@@ -28,6 +28,7 @@
 #ifndef _MBR_H
 #define _MBR_H
 
+#include <machine/param.h>
 #include "part.h"
 
 /* Various constants */
@@ -35,8 +36,8 @@
 #define MBR_PART_SIZE  0x10
 #define MBR_PART_OFF 0x1BE
 #define MBR_SIG_OFF 0x1FE
+#define MBR_MAX_SIZE 8192
 
-
 /* MBR type */
 typedef struct _mbr_t {
        off_t reloffset;
@@ -44,16 +45,17 @@
        unsigned char code[MBR_CODE_SIZE];
        prt_t part[NDOSPART];
        unsigned short signature;
+       unsigned char rest[MBR_MAX_SIZE-DEV_BSIZE];
 } mbr_t;
 
 /* Prototypes */
 void MBR_print_disk(char *);
 void MBR_print(mbr_t *, char *);
 void MBR_parse(disk_t *, char *, off_t, off_t, mbr_t *);
-void MBR_make(mbr_t *, char *);
+void MBR_make(mbr_t *, char *, int);
 void MBR_init(disk_t *, mbr_t *);
-int MBR_read(int, off_t, char *);
-int MBR_write(int, off_t, char *);
+int MBR_read(int, off_t, char *, int);
+int MBR_write(int, off_t, char *, int);
 void MBR_pcopy(disk_t *, mbr_t *);
 
 /* Sanity check */
Index: sbin/fdisk/user.c
===================================================================
RCS file: /cvs/src/sbin/fdisk/user.c,v
retrieving revision 1.23
diff -u -r1.23 user.c
--- sbin/fdisk/user.c   2006/07/27 04:06:13     1.23
+++ sbin/fdisk/user.c   2006/12/06 18:34:43
@@ -68,7 +68,7 @@
 USER_init(disk_t *disk, mbr_t *tt, int preserve)
 {
        int fd, yn;
-       char mbr_buf[DEV_BSIZE];
+       char mbr_buf[MBR_MAX_SIZE];
        char *msgp = "\nDo you wish to write new MBR?";
        char *msgk = "\nDo you wish to write new MBR and partition table?";
 
@@ -89,8 +89,8 @@
 
        if (yn) {
                fd = DISK_open(disk->name, O_RDWR);
-               MBR_make(tt, mbr_buf);
-               if (MBR_write(fd, 0, mbr_buf) == -1) {
+               MBR_make(tt, mbr_buf, disk->real->sec_size);
+               if (MBR_write(fd, 0, mbr_buf, disk->real->sec_size) == -1) {
                        int saved_errno = errno;
                        DISK_close(fd);
                        errno = saved_errno;
@@ -109,7 +109,7 @@
 USER_modify(disk_t *disk, mbr_t *tt, off_t offset, off_t reloff)
 {
        static int editlevel;
-       char mbr_buf[DEV_BSIZE];
+       char mbr_buf[MBR_MAX_SIZE];
        mbr_t mbr;
        cmd_t cmd;
        int i, st, fd;
@@ -122,7 +122,7 @@
 
        /* Read MBR & partition */
        fd = DISK_open(disk->name, O_RDONLY);
-       MBR_read(fd, offset, mbr_buf);
+       MBR_read(fd, offset, mbr_buf, disk->real->sec_size);
        DISK_close(fd);
 
        /* Parse the sucker */
@@ -173,8 +173,8 @@
                if (st == CMD_SAVE) {
                        printf("Writing current MBR to disk.\n");
                        fd = DISK_open(disk->name, O_RDWR);
-                       MBR_make(&mbr, mbr_buf);
-                       if (MBR_write(fd, offset, mbr_buf) == -1) {
+                       MBR_make(&mbr, mbr_buf, disk->real->sec_size);
+                       if (MBR_write(fd, offset, mbr_buf, 
disk->real->sec_size) == -1) {
                                warn("error writing MBR");
                                close(fd);
                                goto again;
@@ -193,8 +193,8 @@
 int
 USER_print_disk(disk_t *disk)
 {
-       int fd, offset, firstoff, i;
-       char mbr_buf[DEV_BSIZE];
+       int fd, offset, firstoff, i, st = 0;
+       char mbr_buf[MBR_MAX_SIZE];
        mbr_t mbr;
 
        fd = DISK_open(disk->name, O_RDONLY);
@@ -203,7 +203,9 @@
        DISK_printmetrics(disk, NULL);
 
        do {
-               MBR_read(fd, (off_t)offset, mbr_buf);
+               st = MBR_read(fd, (off_t)offset, mbr_buf, disk->real->sec_size);
+               if (st == -1)
+                       err(1, "MBR_read");
                MBR_parse(disk, mbr_buf, offset, firstoff, &mbr);
 
                printf("Offset: %d\t", (int)offset);
Index: sys/msdosfs/bpb.h
===================================================================
RCS file: /cvs/src/sys/msdosfs/bpb.h,v
retrieving revision 1.4
diff -u -r1.4 bpb.h
--- sys/msdosfs/bpb.h   2005/09/28 20:53:56     1.4
+++ sys/msdosfs/bpb.h   2006/12/06 18:36:22
@@ -204,6 +204,4 @@
        u_int8_t fsinxtfree[4];
        u_int8_t fsifill2[12];
        u_int8_t fsisig3[4];
-       u_int8_t fsifill3[508];
-       u_int8_t fsisig4[4];
 };
Index: sys/msdosfs/msdosfs_vfsops.c
===================================================================
RCS file: /cvs/src/sys/msdosfs/msdosfs_vfsops.c,v
retrieving revision 1.42
diff -u -r1.42 msdosfs_vfsops.c
--- sys/msdosfs/msdosfs_vfsops.c        2006/11/29 13:35:07     1.42
+++ sys/msdosfs/msdosfs_vfsops.c        2006/12/06 18:36:28
@@ -272,7 +272,7 @@
        u_int8_t SecPerClust;
        int     ronly, error, bmapsiz;
        int     bsize = 0, dtype = 0, tmp;
-       uint32_t dirsperblk;
+       u_int32_t n_rootsec, n_datasec;
 
        /*
         * Disallow multiple mounts of the same device.
@@ -298,6 +298,29 @@
        bp  = NULL; /* both used in error_exit */
        pmp = NULL;
 
+       /*
+        * We need to know sector size of the disk because bread()
+        * will fail if we try to read not N * secsize
+        * According to Microsoft documentations (fatget103.pdf)
+        * allowed sector sizes are 512, 1024, 2048, 4096.
+        */
+       error = VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p);
+       if (error)
+               goto error_exit;
+
+       bsize = dpart.disklab->d_secsize;
+       switch (bsize) {
+       case 512:
+       case 1024:
+       case 2048:
+       case 4096:
+               break;
+
+       default:
+               error = EINVAL;
+               goto error_exit;
+       }
+
        if (argp->flags & MSDOSFSMNT_GEMDOSFS) {
                /*
                 * We need the disklabel to calculate the size of a FAT entry
@@ -309,13 +332,8 @@
                 * that the size of a disk block will always be 512 bytes.
                 * Let's check it...
                 */
-               error = VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart,
-                                 FREAD, NOCRED, p);
-               if (error)
-                       goto error_exit;
                tmp   = dpart.part->p_fstype;
                dtype = dpart.disklab->d_type;
-               bsize = dpart.disklab->d_secsize;
                if (bsize != 512 || (dtype!=DTYPE_FLOPPY && tmp!=FS_MSDOS)) {
                        error = EFTYPE;
                        goto error_exit;
@@ -324,9 +342,9 @@
 
        /*
         * Read the boot sector of the filesystem, and then check the
-        * boot signature.  If not a dos boot sector then error out.
+        * boot signature. If not a dos boot sector then error out.
         */
-       if ((error = bread(devvp, 0, 512, NOCRED, &bp)) != 0)
+       if ((error = bread(devvp, 0, bsize, NOCRED, &bp)) != 0)
                goto error_exit;
        bp->b_flags |= B_AGE;
        bsp = (union bootsector *)bp->b_data;
@@ -343,54 +361,79 @@
         * bootsector.  Copy in the dos 5 variant of the bpb then fix up
         * the fields that are different between dos 5 and dos 3.3.
         */
-       SecPerClust = b50->bpbSecPerClust;
+
        pmp->pm_BytesPerSec = getushort(b50->bpbBytesPerSec);
+       if (pmp->pm_BytesPerSec != bsize) {
+               printf("msdosfs_mountfs: "
+                   "disk block size != FAT's BytesPerSector\n");
+               error = EINVAL;
+               goto error_exit;
+       }
+
+       SecPerClust = b50->bpbSecPerClust;
        pmp->pm_ResSectors = getushort(b50->bpbResSectors);
        pmp->pm_FATs = b50->bpbFATs;
        pmp->pm_RootDirEnts = getushort(b50->bpbRootDirEnts);
-       pmp->pm_Sectors = getushort(b50->bpbSectors);
-       pmp->pm_FATsecs = getushort(b50->bpbFATsecs);
        pmp->pm_SecPerTrack = getushort(b50->bpbSecPerTrack);
        pmp->pm_Heads = getushort(b50->bpbHeads);
        pmp->pm_Media = b50->bpbMedia;
+       pmp->pm_HiddenSects = getulong(b50->bpbHiddenSecs);
 
-       if (!(argp->flags & MSDOSFSMNT_GEMDOSFS)) {
-               if (!pmp->pm_BytesPerSec || !SecPerClust
-                   || pmp->pm_SecPerTrack > 63) {
-                       error = EFTYPE;
-                       goto error_exit;
-               }
+       if (SecPerClust == 0 ||
+           (SecPerClust & (SecPerClust - 1)) != 0 || pmp->pm_ResSectors == 0) {
+               error = EFTYPE;
+               goto error_exit;
        }
 
-       if (pmp->pm_Sectors == 0) {
-               pmp->pm_HiddenSects = getulong(b50->bpbHiddenSecs);
-               pmp->pm_HugeSectors = getulong(b50->bpbHugeSectors);
-       } else {
-               pmp->pm_HiddenSects = getushort(b33->bpbHiddenSecs);
-               pmp->pm_HugeSectors = pmp->pm_Sectors;
-       }
+       pmp->pm_totalsecs = getushort(b33->bpbSectors);
+       if (pmp->pm_totalsecs == 0)
+               pmp->pm_totalsecs = getulong(b50->bpbHugeSectors);
 
-       dirsperblk = pmp->pm_BytesPerSec / sizeof(struct direntry);
+       pmp->pm_FATsecs = getushort(b33->bpbFATsecs);
+       if (pmp->pm_FATsecs == 0)
+               pmp->pm_FATsecs = getulong(b710->bpbBigFATsecs);
 
-       if (pmp->pm_RootDirEnts == 0) {
-               if (pmp->pm_Sectors || pmp->pm_FATsecs ||
-                   getushort(b710->bpbFSVers)) {
-                       error = EINVAL;
+       if (pmp->pm_totalsecs == 0 || pmp->pm_FATsecs == 0 ||
+               pmp->pm_totalsecs > dpart.part->p_size) {
+               printf("msdosfs_mountfs: partition is probably damaged\n");
+               error = EFTYPE;
+               goto error_exit;
+       }
+
+       if (!(argp->flags & MSDOSFSMNT_GEMDOSFS)) {
+               if (pmp->pm_SecPerTrack > 63) {
+                       error = EFTYPE;
                        goto error_exit;
                }
-               pmp->pm_fatmask = FAT32_MASK;
-               pmp->pm_fatmult = 4;
+       }
+
+       /*
+        * Determine FAT type, according to Microsoft documentations
+        * (fatgen103.pdf, p.14).
+        */
+       n_rootsec = ((pmp->pm_RootDirEnts * 32) + pmp->pm_BytesPerSec - 1) /
+           pmp->pm_BytesPerSec;
+       n_datasec = pmp->pm_totalsecs -
+           (pmp->pm_ResSectors + pmp->pm_FATsecs * pmp->pm_FATs + n_rootsec);
+       pmp->pm_nmbrofclusters = n_datasec / SecPerClust;
+
+       if (pmp->pm_nmbrofclusters < 4085) {
+               /* FAT12 */
+               pmp->pm_fatmask = FAT12_MASK;
+               pmp->pm_fatmult = 3;
+               pmp->pm_fatdiv = 2;
+
+               pmp->pm_flags |= MSDOSFS_FATMIRROR;
+       } else if (pmp->pm_nmbrofclusters < 65525) {
+               /* FAT16 */
+               pmp->pm_fatmask = FAT16_MASK;
+               pmp->pm_fatmult = 2;
                pmp->pm_fatdiv = 1;
-               pmp->pm_FATsecs = getulong(b710->bpbBigFATsecs);
-               if (getushort(b710->bpbExtFlags) & FATMIRROR)
-                       pmp->pm_curfat = getushort(b710->bpbExtFlags) & FATNUM;
-               else
-                       pmp->pm_flags |= MSDOSFS_FATMIRROR;
-       } else
-               pmp->pm_flags |= MSDOSFS_FATMIRROR;
 
-       if (argp->flags & MSDOSFSMNT_GEMDOSFS) {
-               if (FAT32(pmp)) {
+               pmp->pm_flags |= MSDOSFS_FATMIRROR;
+       } else {
+               /* FAT32 */
+               if (argp->flags & MSDOSFSMNT_GEMDOSFS) {
                        /*
                         * GEMDOS doesn't know fat32.
                         */
@@ -398,44 +441,29 @@
                        goto error_exit;
                }
 
-               /*
-                * Check a few values (could do some more):
-                * - logical sector size: power of 2, >= block size
-                * - sectors per cluster: power of 2, >= 1
-                * - number of sectors:   >= 1, <= size of partition
-                */
-               if ( (SecPerClust == 0)
-                 || (SecPerClust & (SecPerClust - 1))
-                 || (pmp->pm_BytesPerSec < bsize)
-                 || (pmp->pm_BytesPerSec & (pmp->pm_BytesPerSec - 1))
-                 || (pmp->pm_HugeSectors == 0)
-                 || (pmp->pm_HugeSectors * (pmp->pm_BytesPerSec / bsize)
-                                                       > dpart.part->p_size)
-                  ) {
-                       error = EFTYPE;
+               pmp->pm_fatmask = FAT32_MASK;
+               pmp->pm_fatmult = 4;
+               pmp->pm_fatdiv = 1;
+
+               /* Respect FAT32's version */
+               if (getushort(b710->bpbFSVers) != 0) {
+                       error = EINVAL;
                        goto error_exit;
                }
-               /*
-                * XXX - Many parts of the msdos fs driver seem to assume that
-                * the number of bytes per logical sector (BytesPerSec) will
-                * always be the same as the number of bytes per disk block
-                * Let's pretend it is.
-                */
-               tmp = pmp->pm_BytesPerSec / bsize;
-               pmp->pm_BytesPerSec  = bsize;
-               pmp->pm_HugeSectors *= tmp;
-               pmp->pm_HiddenSects *= tmp;
-               pmp->pm_ResSectors  *= tmp;
-               pmp->pm_Sectors     *= tmp;
-               pmp->pm_FATsecs     *= tmp;
-               SecPerClust         *= tmp;
+
+               if (getushort(b710->bpbExtFlags) & FATMIRROR)
+                       pmp->pm_curfat = getushort(b710->bpbExtFlags) & FATNUM;
+               else
+                       pmp->pm_flags |= MSDOSFS_FATMIRROR;
+
+               pmp->pm_fsinfo = getushort(b710->bpbFSInfo);
        }
+
        pmp->pm_fatblk = pmp->pm_ResSectors;
        if (FAT32(pmp)) {
-               pmp->pm_rootdirblk = getulong(b710->bpbRootClust);
+               pmp->pm_rootdirblk = getulong(b710->bpbRootClust);
                pmp->pm_firstcluster = pmp->pm_fatblk
                        + (pmp->pm_FATs * pmp->pm_FATsecs);
-               pmp->pm_fsinfo = getushort(b710->bpbFSInfo);
        } else {
                pmp->pm_rootdirblk = pmp->pm_fatblk +
                        (pmp->pm_FATs * pmp->pm_FATsecs);
@@ -445,8 +473,6 @@
                pmp->pm_firstcluster = pmp->pm_rootdirblk + pmp->pm_rootdirsize;
        }
 
-       pmp->pm_nmbrofclusters = (pmp->pm_HugeSectors - pmp->pm_firstcluster) /
-           SecPerClust;
        pmp->pm_maxcluster = pmp->pm_nmbrofclusters + 1;
        pmp->pm_fatsize = pmp->pm_FATsecs * pmp->pm_BytesPerSec;
 
@@ -459,27 +485,12 @@
                        pmp->pm_fatmult = 3;
                        pmp->pm_fatdiv = 2;
                } else {
-                       pmp->pm_fatmask = FAT16_MASK;
-                       pmp->pm_fatmult = 2;
-                       pmp->pm_fatdiv = 1;
-               }
-       } else if (pmp->pm_fatmask == 0) {
-               if (pmp->pm_maxcluster
-                   <= ((CLUST_RSRVD - CLUST_FIRST) & FAT12_MASK)) {
-                       /*
-                        * This will usually be a floppy disk. This size makes
-                        * sure that one fat entry will not be split across
-                        * multiple blocks.
-                        */
-                       pmp->pm_fatmask = FAT12_MASK;
-                       pmp->pm_fatmult = 3;
-                       pmp->pm_fatdiv = 2;
-               } else {
                        pmp->pm_fatmask = FAT16_MASK;
                        pmp->pm_fatmult = 2;
                        pmp->pm_fatdiv = 1;
                }
        }
+
        if (FAT12(pmp))
                pmp->pm_fatblocksize = 3 * pmp->pm_BytesPerSec;
        else
@@ -514,16 +525,15 @@
        /*
         * Check FSInfo
         */
-       if (pmp->pm_fsinfo) {
+       if (pmp->pm_fsinfo > 0) {
                struct fsinfo *fp;
 
-               if ((error = bread(devvp, pmp->pm_fsinfo, 1024, NOCRED, &bp)) 
!= 0)
+               if ((error = bread(devvp, pmp->pm_fsinfo, bsize, NOCRED, &bp)) 
!= 0)
                        goto error_exit;
                fp = (struct fsinfo *)bp->b_data;
                if (!bcmp(fp->fsisig1, "RRaA", 4)
                    && !bcmp(fp->fsisig2, "rrAa", 4)
-                   && !bcmp(fp->fsisig3, "\0\0\125\252", 4)
-                   && !bcmp(fp->fsisig4, "\0\0\125\252", 4))
+                   && !bcmp(fp->fsisig3, "\0\0\125\252", 4))
                        pmp->pm_nxtfree = getulong(fp->fsinxtfree);
                else
                        pmp->pm_fsinfo = 0;
Index: sys/msdosfs/msdosfsmount.h
===================================================================
RCS file: /cvs/src/sys/msdosfs/msdosfsmount.h,v
retrieving revision 1.16
diff -u -r1.16 msdosfsmount.h
--- sys/msdosfs/msdosfsmount.h  2004/05/14 04:05:05     1.16
+++ sys/msdosfs/msdosfsmount.h  2006/12/06 18:36:28
@@ -60,6 +60,9 @@
        struct vnode *pm_devvp; /* vnode for block device mntd */
        struct bpb50 pm_bpb;    /* BIOS parameter blk for this fs */
        uint32_t pm_FATsecs;    /* actual number of fat sectors */
+
+       u_int32_t pm_totalsecs; /* amount of sectors in the volume */
+
        uint32_t pm_fatblk;     /* block # of first FAT */
        uint32_t pm_rootdirblk; /* block # (cluster # for FAT32) of root 
directory number */
        uint32_t pm_rootdirsize;        /* size in blocks (not clusters) */
@@ -120,12 +123,10 @@
 #define        pm_ResSectors   pm_bpb.bpbResSectors
 #define        pm_FATs         pm_bpb.bpbFATs
 #define        pm_RootDirEnts  pm_bpb.bpbRootDirEnts
-#define        pm_Sectors      pm_bpb.bpbSectors
 #define        pm_Media        pm_bpb.bpbMedia
 #define        pm_SecPerTrack  pm_bpb.bpbSecPerTrack
 #define        pm_Heads        pm_bpb.bpbHeads
 #define        pm_HiddenSects  pm_bpb.bpbHiddenSecs
-#define        pm_HugeSectors  pm_bpb.bpbHugeSectors
 
 /*
  * Convert pointer to buffer -> pointer to direntry
Index: sys/scsi/sd.c
===================================================================
RCS file: /cvs/src/sys/scsi/sd.c,v
retrieving revision 1.114
diff -u -r1.114 sd.c
--- sys/scsi/sd.c       2006/11/28 16:56:50     1.114
+++ sys/scsi/sd.c       2006/12/06 18:36:44
@@ -659,12 +659,8 @@
 
                /*
                 * We have a buf, now we should make a command
-                *
-                * First, translate the block to absolute and put it in terms
-                * of the logical blocksize of the device.
                 */
-               blkno =
-                   bp->b_blkno / (sd->sc_dk.dk_label->d_secsize / DEV_BSIZE);
+               blkno = bp->b_blkno;
                if (SDPART(bp->b_dev) != RAW_PART) {
                        p = 
&sd->sc_dk.dk_label->d_partitions[SDPART(bp->b_dev)];
                        blkno += p->p_offset;

Reply via email to