summaryrefslogtreecommitdiff
path: root/sys/msdosfs
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2006-12-16 12:44:06 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2006-12-16 12:44:06 +0000
commit5319a398801f23368225691f44bf07b096eb5e86 (patch)
treeb860cff86b48bf04c8d915f8eb3cb074042ba73e /sys/msdosfs
parent474330739d2effcf5f82056b412155be23b391fb (diff)
Adopt FreeBSD's code for non-DEV_BSIZE formatted MSDOSFS filesystems.
Enables devices (e.g. newer iPods, various other mp3 players) that use 2048 byte sectors. Inspired by original diffs from weingart@ and Alexey Vatchenk. ok tom@ pedro@ deraadt@ weingart@ marco@
Diffstat (limited to 'sys/msdosfs')
-rw-r--r--sys/msdosfs/msdosfs_fat.c8
-rw-r--r--sys/msdosfs/msdosfs_vfsops.c45
-rw-r--r--sys/msdosfs/msdosfsmount.h7
3 files changed, 44 insertions, 16 deletions
diff --git a/sys/msdosfs/msdosfs_fat.c b/sys/msdosfs/msdosfs_fat.c
index c9127de9d85..325620473ee 100644
--- a/sys/msdosfs/msdosfs_fat.c
+++ b/sys/msdosfs/msdosfs_fat.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: msdosfs_fat.c,v 1.18 2006/10/03 19:49:06 pedro Exp $ */
+/* $OpenBSD: msdosfs_fat.c,v 1.19 2006/12/16 12:44:05 krw Exp $ */
/* $NetBSD: msdosfs_fat.c,v 1.26 1997/10/17 11:24:02 ws Exp $ */
/*-
@@ -104,8 +104,7 @@ fatblock(pmp, ofs, bnp, sizep, bop)
uint32_t bn, size;
bn = ofs / pmp->pm_fatblocksize * pmp->pm_fatblocksec;
- size = min(pmp->pm_fatblocksec, pmp->pm_FATsecs - bn)
- * pmp->pm_BytesPerSec;
+ size = min(pmp->pm_fatblocksec, pmp->pm_FATsecs - bn) * DEV_BSIZE;
bn += pmp->pm_fatblk + pmp->pm_curfat * pmp->pm_FATsecs;
if (bnp)
@@ -365,7 +364,8 @@ updatefats(pmp, bp, fatbn)
+ ffs(pmp->pm_inusemap[cn / N_INUSEBITS]
^ (u_int)-1) - 1;
}
- if (bread(pmp->pm_devvp, pmp->pm_fsinfo, 1024, NOCRED, &bpn) != 0) {
+ if (bread(pmp->pm_devvp, pmp->pm_fsinfo, fsi_size(pmp), NOCRED,
+ &bpn) != 0) {
/*
* Ignore the error, but turn off FSInfo update for the future.
*/
diff --git a/sys/msdosfs/msdosfs_vfsops.c b/sys/msdosfs/msdosfs_vfsops.c
index e64bbe7ba28..c3442966cc1 100644
--- a/sys/msdosfs/msdosfs_vfsops.c
+++ b/sys/msdosfs/msdosfs_vfsops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: msdosfs_vfsops.c,v 1.45 2006/12/15 03:04:24 krw Exp $ */
+/* $OpenBSD: msdosfs_vfsops.c,v 1.46 2006/12/16 12:44:05 krw Exp $ */
/* $NetBSD: msdosfs_vfsops.c,v 1.48 1997/10/18 02:54:57 briggs Exp $ */
/*-
@@ -294,7 +294,7 @@ msdosfs_mountfs(devvp, mp, p, argp)
* Read the boot sector of the filesystem, and then check the
* 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, 2048, NOCRED, &bp)) != 0)
goto error_exit;
bp->b_flags |= B_AGE;
bsp = (union bootsector *)bp->b_data;
@@ -322,6 +322,9 @@ msdosfs_mountfs(devvp, mp, p, argp)
pmp->pm_Heads = getushort(b50->bpbHeads);
pmp->pm_Media = b50->bpbMedia;
+ /* Determine the number of DEV_BSIZE blocks in a MSDOSFS sector */
+ pmp->pm_BlkPerSec = pmp->pm_BytesPerSec / DEV_BSIZE;
+
if (!pmp->pm_BytesPerSec || !SecPerClust || pmp->pm_SecPerTrack > 63) {
error = EFTYPE;
goto error_exit;
@@ -352,25 +355,44 @@ msdosfs_mountfs(devvp, mp, p, argp)
} else
pmp->pm_flags |= MSDOSFS_FATMIRROR;
- pmp->pm_fatblk = pmp->pm_ResSectors;
+ /*
+ * More sanity checks:
+ * MSDOSFS sectors per cluster: >0 && power of 2
+ * MSDOSFS sector size: >= DEV_BSIZE && power of 2
+ * HUGE sector count: >0
+ * FAT sectors: >0
+ */
+ if ((SecPerClust == 0) || (SecPerClust & (SecPerClust - 1)) ||
+ (pmp->pm_BytesPerSec < DEV_BSIZE) ||
+ (pmp->pm_BytesPerSec & (pmp->pm_BytesPerSec - 1)) ||
+ (pmp->pm_HugeSectors == 0) || (pmp->pm_FATsecs == 0)) {
+ error = EINVAL;
+ goto error_exit;
+ }
+
+ pmp->pm_HugeSectors *= pmp->pm_BlkPerSec;
+ pmp->pm_HiddenSects *= pmp->pm_BlkPerSec;
+ pmp->pm_FATsecs *= pmp->pm_BlkPerSec;
+ pmp->pm_fatblk = pmp->pm_ResSectors * pmp->pm_BlkPerSec;
+ SecPerClust *= pmp->pm_BlkPerSec;
+
if (FAT32(pmp)) {
pmp->pm_rootdirblk = getulong(b710->bpbRootClust);
pmp->pm_firstcluster = pmp->pm_fatblk
+ (pmp->pm_FATs * pmp->pm_FATsecs);
- pmp->pm_fsinfo = getushort(b710->bpbFSInfo);
+ pmp->pm_fsinfo = getushort(b710->bpbFSInfo) * pmp->pm_BlkPerSec;
} else {
pmp->pm_rootdirblk = pmp->pm_fatblk +
(pmp->pm_FATs * pmp->pm_FATsecs);
pmp->pm_rootdirsize = (pmp->pm_RootDirEnts * sizeof(struct direntry)
- + pmp->pm_BytesPerSec - 1)
- / pmp->pm_BytesPerSec;/* in sectors */
+ + DEV_BSIZE - 1) / DEV_BSIZE;
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;
+ pmp->pm_fatsize = pmp->pm_FATsecs * DEV_BSIZE;
if (pmp->pm_fatmask == 0) {
if (pmp->pm_maxcluster
@@ -417,14 +439,14 @@ msdosfs_mountfs(devvp, mp, p, argp)
pmp->pm_maxcluster = fat_max_clusters - 1;
}
- pmp->pm_fatblocksec = pmp->pm_fatblocksize / pmp->pm_BytesPerSec;
- pmp->pm_bnshift = ffs(pmp->pm_BytesPerSec) - 1;
+ pmp->pm_fatblocksec = pmp->pm_fatblocksize / DEV_BSIZE;
+ pmp->pm_bnshift = ffs(DEV_BSIZE) - 1;
/*
* Compute mask and shift value for isolating cluster relative byte
* offsets and cluster numbers from a file offset.
*/
- pmp->pm_bpcluster = SecPerClust * pmp->pm_BytesPerSec;
+ pmp->pm_bpcluster = SecPerClust * DEV_BSIZE;
pmp->pm_crbomask = pmp->pm_bpcluster - 1;
pmp->pm_cnshift = ffs(pmp->pm_bpcluster) - 1;
@@ -449,7 +471,8 @@ msdosfs_mountfs(devvp, mp, p, argp)
if (pmp->pm_fsinfo) {
struct fsinfo *fp;
- if ((error = bread(devvp, pmp->pm_fsinfo, 1024, NOCRED, &bp)) != 0)
+ if ((error = bread(devvp, pmp->pm_fsinfo, fsi_size(pmp),
+ NOCRED, &bp)) != 0)
goto error_exit;
fp = (struct fsinfo *)bp->b_data;
if (!bcmp(fp->fsisig1, "RRaA", 4)
diff --git a/sys/msdosfs/msdosfsmount.h b/sys/msdosfs/msdosfsmount.h
index 56f2cd971ff..45f72016fde 100644
--- a/sys/msdosfs/msdosfsmount.h
+++ b/sys/msdosfs/msdosfsmount.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: msdosfsmount.h,v 1.17 2006/12/15 03:04:24 krw Exp $ */
+/* $OpenBSD: msdosfsmount.h,v 1.18 2006/12/16 12:44:05 krw Exp $ */
/* $NetBSD: msdosfsmount.h,v 1.16 1997/10/17 11:24:24 ws Exp $ */
/*-
@@ -59,6 +59,7 @@ struct msdosfsmount {
mode_t pm_mask; /* mask to and with file protection bits */
struct vnode *pm_devvp; /* vnode for block device mntd */
struct bpb50 pm_bpb; /* BIOS parameter blk for this fs */
+ uint32_t pm_BlkPerSec; /* # of DEV_BSIZE blocks in MSDOSFS sector */
uint32_t pm_FATsecs; /* actual number of fat sectors */
uint32_t pm_fatblk; /* block # of first FAT */
uint32_t pm_rootdirblk; /* block # (cluster # for FAT32) of root directory number */
@@ -195,6 +196,10 @@ struct msdosfsmount {
? roottobn((pmp), (dirofs)) \
: cntobn((pmp), (dirclu)))
+/* Calculate size of fsinfo block */
+#define fsi_size(pmp) \
+ (1024 << ((pmp)->pm_BlkPerSec >> 2))
+
/*
* Prototypes for MSDOSFS virtual filesystem operations
*/