Supported non-512 bytes/sector format.

PR:		misc/12992
Submitted by:	chi@bd.mbn.or.jp (Chiharu Shibata) and
		Dmitrij Tejblum <tejblum@arc.hq.cti.ru>
Reviewed by:	Dmitrij Tejblum <tejblum@arc.hq.cti.ru>
This commit is contained in:
Yoshihiro Takahashi 2000-01-27 14:43:07 +00:00
parent fca569ab4f
commit 01f6cfbae0
8 changed files with 122 additions and 140 deletions

View file

@ -299,7 +299,7 @@ deget(pmp, dirclust, diroffset, depp)
/* de_FileSize will be filled in further down */
else {
ldep->de_StartCluster = MSDOSFSROOT;
ldep->de_FileSize = pmp->pm_rootdirsize * pmp->pm_BytesPerSec;
ldep->de_FileSize = pmp->pm_rootdirsize * DEV_BSIZE;
}
/*
* fill in time and date so that dos2unixtime() doesn't

View file

@ -109,7 +109,7 @@ fatblock(pmp, ofs, bnp, sizep, bop)
bn = ofs / pmp->pm_fatblocksize * pmp->pm_fatblocksec;
size = min(pmp->pm_fatblocksec, pmp->pm_FATsecs - bn)
* pmp->pm_BytesPerSec;
* DEV_BSIZE;
bn += pmp->pm_fatblk + pmp->pm_curfat * pmp->pm_FATsecs;
if (bnp)
@ -364,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.
*/

View file

@ -69,6 +69,17 @@
#include <msdosfs/msdosfsmount.h>
#include <msdosfs/fat.h>
#if 1 /*def PC98*/
/*
* XXX - The boot signature formatted by NEC PC-98 DOS looks like a
* garbage or a random value :-{
* If you want to use that broken-signatured media, define the
* following symbol even though PC/AT.
* (ex. mount PC-98 DOS formatted FD on PC/AT)
*/
#define MSDOSFS_NOCHECKSIG
#endif
MALLOC_DEFINE(M_MSDOSFSMNT, "MSDOSFS mount", "MSDOSFS mount structure");
static MALLOC_DEFINE(M_MSDOSFSFAT, "MSDOSFS FAT", "MSDOSFS file allocation table");
@ -423,12 +434,10 @@ mountmsdosfs(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.
*
* NOTE: 2048 is a maximum sector size in current...
*/
#ifdef PC98
error = bread(devvp, 0, 1024, NOCRED, &bp);
#else
error = bread(devvp, 0, 512, NOCRED, &bp);
#endif
error = bread(devvp, 0, 2048, NOCRED, &bp);
if (error)
goto error_exit;
bp->b_flags |= B_AGE;
@ -440,22 +449,13 @@ mountmsdosfs(devvp, mp, p, argp)
#ifndef __FreeBSD__
if (!(argp->flags & MSDOSFSMNT_GEMDOSFS)) {
#endif
#ifdef PC98
if ((bsp->bs50.bsBootSectSig0 != BOOTSIG0
|| bsp->bs50.bsBootSectSig1 != BOOTSIG1)
&& (bsp->bs50.bsBootSectSig0 != 0 /* PC98 DOS 3.3x */
|| bsp->bs50.bsBootSectSig1 != 0)
&& (bsp->bs50.bsBootSectSig0 != 0x90 /* PC98 DOS 5.0 */
|| bsp->bs50.bsBootSectSig1 != 0x3d)
&& (bsp->bs50.bsBootSectSig0 != 0x46 /* PC98 DOS 3.3B */
|| bsp->bs50.bsBootSectSig1 != 0xfa)) {
#else
#ifndef MSDOSFS_NOCHECKSIG
if (bsp->bs50.bsBootSectSig0 != BOOTSIG0
|| bsp->bs50.bsBootSectSig1 != BOOTSIG1) {
#endif
error = EINVAL;
goto error_exit;
}
#endif
#ifndef __FreeBSD__
}
#endif
@ -480,6 +480,9 @@ mountmsdosfs(devvp, mp, p, argp)
pmp->pm_Heads = getushort(b50->bpbHeads);
pmp->pm_Media = b50->bpbMedia;
/* calculate the ratio of sector size to DEV_BSIZE */
pmp->pm_BlkPerSec = pmp->pm_BytesPerSec / DEV_BSIZE;
#ifndef __FreeBSD__
if (!(argp->flags & MSDOSFSMNT_GEMDOSFS)) {
#endif
@ -538,67 +541,46 @@ mountmsdosfs(devvp, mp, p, argp)
} else
pmp->pm_flags |= MSDOSFS_FATMIRROR;
#ifndef __FreeBSD__
if (argp->flags & MSDOSFSMNT_GEMDOSFS) {
if (FAT32(pmp)) {
/*
* GEMDOS doesn't know fat32.
*/
error = EINVAL;
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 = 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;
/*
* 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 < DEV_BSIZE)
|| (pmp->pm_BytesPerSec & (pmp->pm_BytesPerSec - 1))
|| (pmp->pm_HugeSectors == 0)
) {
error = EINVAL;
goto error_exit;
}
#endif
pmp->pm_fatblk = pmp->pm_ResSectors;
pmp->pm_HugeSectors *= pmp->pm_BlkPerSec;
pmp->pm_HiddenSects *= pmp->pm_BlkPerSec; /* XXX not used? */
pmp->pm_FATsecs *= pmp->pm_BlkPerSec;
SecPerClust *= pmp->pm_BlkPerSec;
pmp->pm_fatblk = pmp->pm_ResSectors * 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; /* in blocks */
pmp->pm_firstcluster = pmp->pm_rootdirblk + pmp->pm_rootdirsize;
}
pmp->pm_maxcluster = (pmp->pm_HugeSectors - pmp->pm_firstcluster) /
SecPerClust + 1;
pmp->pm_fatsize = pmp->pm_FATsecs * pmp->pm_BytesPerSec;
pmp->pm_fatsize = pmp->pm_FATsecs * DEV_BSIZE; /* XXX not used? */
#ifndef __FreeBSD__
if (argp->flags & MSDOSFSMNT_GEMDOSFS) {
@ -647,14 +629,14 @@ mountmsdosfs(devvp, mp, p, argp)
else
pmp->pm_fatblocksize = DFLTBSIZE;
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;
@ -679,7 +661,8 @@ mountmsdosfs(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)

View file

@ -68,6 +68,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 */
u_long pm_BlkPerSec; /* How many DEV_BSIZE blocks fit inside a physical sector */
u_long pm_FATsecs; /* actual number of fat sectors */
u_long pm_fatblk; /* block # of first FAT */
u_long pm_rootdirblk; /* block # (cluster # for FAT32) of root directory number */
@ -190,6 +191,12 @@ struct msdosfsmount {
? roottobn((pmp), (dirofs)) \
: cntobn((pmp), (dirclu)))
/*
* Calculate fsinfo block size
*/
#define fsi_size(pmp) \
(1024 << ((pmp)->pm_BlkPerSec >> 2))
int msdosfs_init __P((struct vfsconf *vfsp));
int msdosfs_mountroot __P((void));

View file

@ -299,7 +299,7 @@ deget(pmp, dirclust, diroffset, depp)
/* de_FileSize will be filled in further down */
else {
ldep->de_StartCluster = MSDOSFSROOT;
ldep->de_FileSize = pmp->pm_rootdirsize * pmp->pm_BytesPerSec;
ldep->de_FileSize = pmp->pm_rootdirsize * DEV_BSIZE;
}
/*
* fill in time and date so that dos2unixtime() doesn't

View file

@ -109,7 +109,7 @@ fatblock(pmp, ofs, bnp, sizep, bop)
bn = ofs / pmp->pm_fatblocksize * pmp->pm_fatblocksec;
size = min(pmp->pm_fatblocksec, pmp->pm_FATsecs - bn)
* pmp->pm_BytesPerSec;
* DEV_BSIZE;
bn += pmp->pm_fatblk + pmp->pm_curfat * pmp->pm_FATsecs;
if (bnp)
@ -364,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.
*/

View file

@ -69,6 +69,17 @@
#include <msdosfs/msdosfsmount.h>
#include <msdosfs/fat.h>
#if 1 /*def PC98*/
/*
* XXX - The boot signature formatted by NEC PC-98 DOS looks like a
* garbage or a random value :-{
* If you want to use that broken-signatured media, define the
* following symbol even though PC/AT.
* (ex. mount PC-98 DOS formatted FD on PC/AT)
*/
#define MSDOSFS_NOCHECKSIG
#endif
MALLOC_DEFINE(M_MSDOSFSMNT, "MSDOSFS mount", "MSDOSFS mount structure");
static MALLOC_DEFINE(M_MSDOSFSFAT, "MSDOSFS FAT", "MSDOSFS file allocation table");
@ -423,12 +434,10 @@ mountmsdosfs(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.
*
* NOTE: 2048 is a maximum sector size in current...
*/
#ifdef PC98
error = bread(devvp, 0, 1024, NOCRED, &bp);
#else
error = bread(devvp, 0, 512, NOCRED, &bp);
#endif
error = bread(devvp, 0, 2048, NOCRED, &bp);
if (error)
goto error_exit;
bp->b_flags |= B_AGE;
@ -440,22 +449,13 @@ mountmsdosfs(devvp, mp, p, argp)
#ifndef __FreeBSD__
if (!(argp->flags & MSDOSFSMNT_GEMDOSFS)) {
#endif
#ifdef PC98
if ((bsp->bs50.bsBootSectSig0 != BOOTSIG0
|| bsp->bs50.bsBootSectSig1 != BOOTSIG1)
&& (bsp->bs50.bsBootSectSig0 != 0 /* PC98 DOS 3.3x */
|| bsp->bs50.bsBootSectSig1 != 0)
&& (bsp->bs50.bsBootSectSig0 != 0x90 /* PC98 DOS 5.0 */
|| bsp->bs50.bsBootSectSig1 != 0x3d)
&& (bsp->bs50.bsBootSectSig0 != 0x46 /* PC98 DOS 3.3B */
|| bsp->bs50.bsBootSectSig1 != 0xfa)) {
#else
#ifndef MSDOSFS_NOCHECKSIG
if (bsp->bs50.bsBootSectSig0 != BOOTSIG0
|| bsp->bs50.bsBootSectSig1 != BOOTSIG1) {
#endif
error = EINVAL;
goto error_exit;
}
#endif
#ifndef __FreeBSD__
}
#endif
@ -480,6 +480,9 @@ mountmsdosfs(devvp, mp, p, argp)
pmp->pm_Heads = getushort(b50->bpbHeads);
pmp->pm_Media = b50->bpbMedia;
/* calculate the ratio of sector size to DEV_BSIZE */
pmp->pm_BlkPerSec = pmp->pm_BytesPerSec / DEV_BSIZE;
#ifndef __FreeBSD__
if (!(argp->flags & MSDOSFSMNT_GEMDOSFS)) {
#endif
@ -538,67 +541,46 @@ mountmsdosfs(devvp, mp, p, argp)
} else
pmp->pm_flags |= MSDOSFS_FATMIRROR;
#ifndef __FreeBSD__
if (argp->flags & MSDOSFSMNT_GEMDOSFS) {
if (FAT32(pmp)) {
/*
* GEMDOS doesn't know fat32.
*/
error = EINVAL;
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 = 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;
/*
* 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 < DEV_BSIZE)
|| (pmp->pm_BytesPerSec & (pmp->pm_BytesPerSec - 1))
|| (pmp->pm_HugeSectors == 0)
) {
error = EINVAL;
goto error_exit;
}
#endif
pmp->pm_fatblk = pmp->pm_ResSectors;
pmp->pm_HugeSectors *= pmp->pm_BlkPerSec;
pmp->pm_HiddenSects *= pmp->pm_BlkPerSec; /* XXX not used? */
pmp->pm_FATsecs *= pmp->pm_BlkPerSec;
SecPerClust *= pmp->pm_BlkPerSec;
pmp->pm_fatblk = pmp->pm_ResSectors * 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; /* in blocks */
pmp->pm_firstcluster = pmp->pm_rootdirblk + pmp->pm_rootdirsize;
}
pmp->pm_maxcluster = (pmp->pm_HugeSectors - pmp->pm_firstcluster) /
SecPerClust + 1;
pmp->pm_fatsize = pmp->pm_FATsecs * pmp->pm_BytesPerSec;
pmp->pm_fatsize = pmp->pm_FATsecs * DEV_BSIZE; /* XXX not used? */
#ifndef __FreeBSD__
if (argp->flags & MSDOSFSMNT_GEMDOSFS) {
@ -647,14 +629,14 @@ mountmsdosfs(devvp, mp, p, argp)
else
pmp->pm_fatblocksize = DFLTBSIZE;
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;
@ -679,7 +661,8 @@ mountmsdosfs(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)

View file

@ -68,6 +68,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 */
u_long pm_BlkPerSec; /* How many DEV_BSIZE blocks fit inside a physical sector */
u_long pm_FATsecs; /* actual number of fat sectors */
u_long pm_fatblk; /* block # of first FAT */
u_long pm_rootdirblk; /* block # (cluster # for FAT32) of root directory number */
@ -190,6 +191,12 @@ struct msdosfsmount {
? roottobn((pmp), (dirofs)) \
: cntobn((pmp), (dirclu)))
/*
* Calculate fsinfo block size
*/
#define fsi_size(pmp) \
(1024 << ((pmp)->pm_BlkPerSec >> 2))
int msdosfs_init __P((struct vfsconf *vfsp));
int msdosfs_mountroot __P((void));