Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F147484619
D49078.id151825.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
12 KB
Referenced Files
None
Subscribers
None
D49078.id151825.diff
View Options
diff --git a/stand/libsa/dosfs.h b/stand/libsa/dosfs.h
--- a/stand/libsa/dosfs.h
+++ b/stand/libsa/dosfs.h
@@ -94,12 +94,15 @@
typedef struct {
struct open_file *fd; /* file descriptor */
+ u_char *secbuf; /* sector cache */
u_char *fatbuf; /* FAT cache buffer */
u_int fatbuf_blknum; /* number of 128K block in FAT cache buffer */
u_int links; /* active links to structure */
+ u_int sshift; /* sector shift */
u_int spc; /* sectors per cluster */
u_int bsize; /* cluster size in bytes */
u_int bshift; /* cluster conversion shift */
+ u_int dshift; /* directory entries shift */
u_int dirents; /* root directory entries */
u_int spf; /* sectors per fat */
u_int rdcl; /* root directory start cluster */
diff --git a/stand/libsa/dosfs.c b/stand/libsa/dosfs.c
--- a/stand/libsa/dosfs.c
+++ b/stand/libsa/dosfs.c
@@ -32,6 +32,7 @@
*/
#include <sys/types.h>
+#include <sys/disk.h>
#include <string.h>
#include <stddef.h>
@@ -71,10 +72,6 @@
.fo_unmount = dos_unmount
};
-#define SECSIZ 512 /* sector size */
-#define SSHIFT 9 /* SECSIZ shift */
-#define DEPSEC 16 /* directory entries per sector */
-#define DSHIFT 4 /* DEPSEC shift */
#define LOCLUS 2 /* lowest cluster number */
#define FATBLKSZ 0x20000 /* size of block in the FAT cache buffer */
@@ -92,14 +89,43 @@
u_char heads[2]; /* drive heads */
u_char hidsec[4]; /* hidden sectors */
u_char lsecs[4]; /* huge sectors */
- u_char lspf[4]; /* huge sectors per FAT */
- u_char xflg[2]; /* flags */
- u_char vers[2]; /* filesystem version */
- u_char rdcl[4]; /* root directory start cluster */
- u_char infs[2]; /* filesystem info sector */
- u_char bkbs[2]; /* backup boot sector */
+ union {
+ struct {
+ u_char drvnum; /* Int 13 drive number */
+ u_char rsvd1; /* Reserved */
+ u_char bootsig; /* Boot signature (0x29) */
+ u_char volid[4]; /* Volume serial number */
+ u_char vollab[11]; /* Volume label */
+ u_char fstype[8]; /* Informational */
+ } f12_f16;
+ struct {
+ u_char lspf[4]; /* huge sectors per FAT */
+ u_char xflg[2]; /* flags */
+ u_char vers[2]; /* filesystem version */
+ u_char rdcl[4]; /* root directory cluster */
+ u_char infs[2]; /* filesystem info sector */
+ u_char bkbs[2]; /* backup boot sector */
+ u_char reserved[12]; /* Reserved */
+ u_char drvnum; /* Int 13 drive number */
+ u_char rsvd1; /* Reserved */
+ u_char bootsig; /* Boot signature (0x29) */
+ u_char volid[4]; /* Volume serial number */
+ u_char vollab[11]; /* Volume label */
+ u_char fstype[8]; /* Informational */
+ } f32;
+ } fstype;
} DOS_BPB;
+typedef struct {
+ u_char fsi_leadsig[4]; /* Value 0x41615252 */
+ u_char fsi_reserved1[480];
+ u_char fsi_structsig[4]; /* Value 0x61417272 */
+ u_char fsi_free_count[4]; /* Last known free cluster count */
+ u_char fsi_next_free[4]; /* First free cluster */
+ u_char fsi_reserved2[12];
+ u_char fsi_trailsig[4]; /* Value 0xAA550000 */
+} DOS_FSINFO;
+
/* Initial portion of DOS boot sector */
typedef struct {
u_char jmp[3]; /* usually 80x86 'jmp' opcode */
@@ -117,16 +143,18 @@
};
/* The usual conversion macros to avoid multiplication and division */
-#define bytsec(n) ((n) >> SSHIFT)
-#define secbyt(s) ((s) << SSHIFT)
-#define entsec(e) ((e) >> DSHIFT)
-#define bytblk(fs, n) ((n) >> (fs)->bshift)
-#define blkbyt(fs, b) ((b) << (fs)->bshift)
-#define secblk(fs, s) ((s) >> ((fs)->bshift - SSHIFT))
-#define blksec(fs, b) ((b) << ((fs)->bshift - SSHIFT))
+#define bytsec(fs, n) ((n) >> (fs)->sshift)
+#define secbyt(fs, s) ((s) << (fs)->sshift)
+#define depsec(fs) (1 << (fs)->dshift)
+#define entsec(fs, e) ((e) >> (fs)->dshift)
+#define bytblk(fs, n) ((n) >> (fs)->bshift)
+#define blkbyt(fs, b) ((b) << (fs)->bshift)
+#define secblk(fs, s) ((s) >> ((fs)->bshift - (fs)->sshift))
+#define blksec(fs, b) ((b) << ((fs)->bshift - (fs)->sshift))
/* Convert cluster number to offset within filesystem */
-#define blkoff(fs, b) (secbyt((fs)->lsndta) + blkbyt(fs, (b) - LOCLUS))
+#define blkoff(fs, b) (secbyt(fs, (fs)->lsndta) + \
+ blkbyt(fs, (b) - LOCLUS))
/* Convert cluster number to logical sector number */
#define blklsn(fs, b) ((fs)->lsndta + blksec(fs, (b) - LOCLUS))
@@ -154,17 +182,17 @@
static int fatget(DOS_FS *, u_int *);
static int fatend(u_int, u_int);
static int ioread(DOS_FS *, uint64_t, void *, size_t);
-static int ioget(struct open_file *, daddr_t, void *, size_t);
+static int ioget(DOS_FS *, daddr_t, void *, size_t);
static int
-dos_read_fatblk(DOS_FS *fs, struct open_file *fd, u_int blknum)
+dos_read_fatblk(DOS_FS *fs, u_int blknum)
{
int err;
size_t io_size;
daddr_t offset_in_fat, max_offset_in_fat;
offset_in_fat = ((daddr_t)blknum) * FATBLKSZ;
- max_offset_in_fat = secbyt(fs->spf);
+ max_offset_in_fat = secbyt(fs, (daddr_t)fs->spf);
io_size = FATBLKSZ;
if (offset_in_fat > max_offset_in_fat)
offset_in_fat = max_offset_in_fat;
@@ -172,7 +200,7 @@
io_size = ((size_t)(max_offset_in_fat - offset_in_fat));
if (io_size != 0) {
- err = ioget(fd, fs->lsnfat + bytsec(offset_in_fat),
+ err = ioget(fs, fs->lsnfat + bytsec(fs, offset_in_fat),
fs->fatbuf, io_size);
if (err != 0) {
fs->fatbuf_blknum = ((u_int)(-1));
@@ -193,23 +221,34 @@
dos_mount_impl(DOS_FS *fs, struct open_file *fd)
{
int err;
+ unsigned secsz;
u_char *buf;
fs->fd = fd;
- if ((buf = malloc(secbyt(1))) == NULL)
+ err = ioctl(fd->f_id, DIOCGSECTORSIZE, &secsz);
+ if (err != 0) {
+ return (err);
+ }
+
+ buf = malloc(secsz);
+ if (buf == NULL)
return (errno);
- if ((err = ioget(fs->fd, 0, buf, secbyt(1))) ||
+
+ if ((err = ioget(fs, 0, buf, secsz)) ||
(err = parsebs(fs, (DOS_BS *)buf))) {
free(buf);
return (err);
}
- free(buf);
+ fs->secbuf = buf;
- if ((fs->fatbuf = malloc(FATBLKSZ)) == NULL)
+ if ((fs->fatbuf = malloc(FATBLKSZ)) == NULL) {
+ free(buf);
return (errno);
- err = dos_read_fatblk(fs, fd, 0);
+ }
+ err = dos_read_fatblk(fs, 0);
if (err != 0) {
+ free(buf);
free(fs->fatbuf);
return (err);
}
@@ -292,6 +331,7 @@
{
if (fs->links)
return (EBUSY);
+ free(fs->secbuf);
free(fs->fatbuf);
free(fs);
return (0);
@@ -305,7 +345,7 @@
{
DOS_DE *de;
DOS_FILE *f;
- DOS_FS *fs;
+ DOS_FS *fs = NULL;
dos_mnt_t *mnt;
const char *dev;
u_int size, clus;
@@ -408,7 +448,7 @@
if (c != 0)
off += blkoff(f->fs, (uint64_t)c);
else
- off += secbyt(f->fs->lsndir);
+ off += secbyt(f->fs, f->fs->lsndir);
err = ioread(f->fs, off, buf, n);
if (err != 0)
goto out;
@@ -588,36 +628,54 @@
static int
parsebs(DOS_FS *fs, DOS_BS *bs)
{
- u_int sc;
+ u_int sc, RootDirSectors;
- if ((bs->jmp[0] != 0x69 &&
- bs->jmp[0] != 0xe9 &&
- (bs->jmp[0] != 0xeb || bs->jmp[2] != 0x90)) ||
- bs->bpb.media < 0xf0)
+ if (bs->bpb.media < 0xf0)
return (EINVAL);
- if (cv2(bs->bpb.secsiz) != SECSIZ)
+
+ /* Check supported sector sizes */
+ switch (cv2(bs->bpb.secsiz)) {
+ case 512:
+ case 1024:
+ case 2048:
+ case 4096:
+ fs->sshift = ffs(cv2(bs->bpb.secsiz)) - 1;
+ break;
+
+ default:
return (EINVAL);
+ }
+
if (!(fs->spc = bs->bpb.spc) || fs->spc & (fs->spc - 1))
return (EINVAL);
- fs->bsize = secbyt(fs->spc);
+ fs->bsize = secbyt(fs, fs->spc);
fs->bshift = ffs(fs->bsize) - 1;
- if ((fs->spf = cv2(bs->bpb.spf))) {
+ fs->dshift = ffs(secbyt(fs, 1) / sizeof (DOS_DE)) - 1;
+ fs->dirents = cv2(bs->bpb.dirents);
+ fs->spf = cv2(bs->bpb.spf);
+ fs->lsnfat = cv2(bs->bpb.ressec);
+
+ if (fs->spf != 0) {
if (bs->bpb.fats != 2)
return (EINVAL);
- if (!(fs->dirents = cv2(bs->bpb.dirents)))
+ if (fs->dirents == 0)
return (EINVAL);
} else {
- if (!(fs->spf = cv4(bs->bpb.lspf)))
+ fs->spf = cv4(bs->bpb.fstype.f32.lspf);
+ if (fs->spf == 0)
return (EINVAL);
- if (!bs->bpb.fats || bs->bpb.fats > 16)
+ if (bs->bpb.fats == 0 || bs->bpb.fats > 16)
return (EINVAL);
- if ((fs->rdcl = cv4(bs->bpb.rdcl)) < LOCLUS)
+ fs->rdcl = cv4(bs->bpb.fstype.f32.rdcl);
+ if (fs->rdcl < LOCLUS)
return (EINVAL);
}
- if (!(fs->lsnfat = cv2(bs->bpb.ressec)))
- return (EINVAL);
+
+ RootDirSectors = ((fs->dirents * sizeof (DOS_DE)) +
+ (secbyt(fs, 1) - 1)) / secbyt(fs, 1);
+
fs->lsndir = fs->lsnfat + fs->spf * bs->bpb.fats;
- fs->lsndta = fs->lsndir + entsec(fs->dirents);
+ fs->lsndta = fs->lsndir + RootDirSectors;
if (!(sc = cv2(bs->bpb.secs)) && !(sc = cv4(bs->bpb.lsecs)))
return (EINVAL);
if (fs->lsndta > sc)
@@ -625,7 +683,7 @@
if ((fs->xclus = secblk(fs, sc - fs->lsndta) + 1) < LOCLUS)
return (EINVAL);
fs->fatsz = fs->dirents ? fs->xclus < 0xff6 ? 12 : 16 : 32;
- sc = (secbyt(fs->spf) << 1) / (fs->fatsz >> 2) - 1;
+ sc = (secbyt(fs, fs->spf) << 1) / (fs->fatsz >> 2) - 1;
if (fs->xclus > sc)
fs->xclus = sc;
return (0);
@@ -672,7 +730,7 @@
static int
lookup(DOS_FS *fs, u_int clus, const char *name, DOS_DE **dep)
{
- static DOS_DIR dir[DEPSEC];
+ DOS_DIR *dir;
u_char lfn[261];
u_char sfn[13];
u_int nsec, lsec, xdn, chk, sec, ent, x;
@@ -686,9 +744,10 @@
}
if (!clus && fs->fatsz == 32)
clus = fs->rdcl;
- nsec = !clus ? entsec(fs->dirents) : fs->spc;
+ nsec = !clus ? entsec(fs, fs->dirents) : fs->spc;
lsec = 0;
xdn = chk = 0;
+ dir = (DOS_DIR *)fs->secbuf;
for (;;) {
if (!clus && !lsec)
lsec = fs->lsndir;
@@ -697,9 +756,10 @@
else
return (EINVAL);
for (sec = 0; sec < nsec; sec++) {
- if ((err = ioget(fs->fd, lsec + sec, dir, secbyt(1))))
+ if ((err = ioget(fs, lsec + sec, dir,
+ secbyt(fs, 1))))
return (err);
- for (ent = 0; ent < DEPSEC; ent++) {
+ for (ent = 0; ent < depsec(fs); ent++) {
if (!*dir[ent].de.name)
return (ENOENT);
if (*dir[ent].de.name != 0xe5) {
@@ -866,14 +926,14 @@
/* ensure that current 128K FAT block is cached */
offset = fatoff(fs->fatsz, val_in);
nbyte = fs->fatsz != 32 ? 2 : 4;
- if (offset + nbyte > secbyt(fs->spf))
+ if (offset + nbyte > secbyt(fs, fs->spf))
return (EINVAL);
blknum = offset / FATBLKSZ;
offset %= FATBLKSZ;
if (offset + nbyte > FATBLKSZ)
return (EINVAL);
if (blknum != fs->fatbuf_blknum) {
- err = dos_read_fatblk(fs, fs->fd, blknum);
+ err = dos_read_fatblk(fs, blknum);
if (err != 0)
return (err);
}
@@ -918,53 +978,55 @@
ioread(DOS_FS *fs, uint64_t offset, void *buf, size_t nbyte)
{
char *s;
- size_t n;
+ size_t n, secsiz;
int err;
uint64_t off;
- u_char local_buf[SECSIZ];
+ secsiz = secbyt(fs, 1);
s = buf;
- if ((off = offset & (SECSIZ - 1))) {
+ if ((off = offset & (secsiz - 1))) {
offset -= off;
- if ((n = SECSIZ - off) > nbyte)
+ if ((n = secsiz - off) > nbyte)
n = nbyte;
- err = ioget(fs->fd, bytsec(offset), local_buf,
- sizeof(local_buf));
+ err = ioget(fs, bytsec(fs, offset), fs->secbuf, secsiz);
if (err != 0)
return (err);
- memcpy(s, local_buf + off, n);
- offset += SECSIZ;
+ memcpy(s, fs->secbuf + off, n);
+ offset += secsiz;
s += n;
nbyte -= n;
}
- n = nbyte & (SECSIZ - 1);
+ n = nbyte & (secsiz - 1);
if (nbyte -= n) {
- if ((err = ioget(fs->fd, bytsec(offset), s, nbyte)))
+ if ((err = ioget(fs, bytsec(fs, offset), s, nbyte)))
return (err);
offset += nbyte;
s += nbyte;
}
if (n != 0) {
- err = ioget(fs->fd, bytsec(offset), local_buf,
- sizeof(local_buf));
+ err = ioget(fs, bytsec(fs, offset), fs->secbuf, secsiz);
if (err != 0)
return (err);
- memcpy(s, local_buf, n);
+ memcpy(s, fs->secbuf, n);
}
return (0);
}
/*
- * Sector-based I/O primitive
+ * Sector-based I/O primitive. Note, since strategy functions are operating
+ * in terms of 512B sectors, we need to do necessary conversion here.
*/
static int
-ioget(struct open_file *fd, daddr_t lsec, void *buf, size_t size)
+ioget(DOS_FS *fs, daddr_t lsec, void *buf, size_t size)
{
size_t rsize;
int rv;
+ struct open_file *fd = fs->fd;
/* Make sure we get full read or error. */
rsize = 0;
+ /* convert native sector number to 512B sector number. */
+ lsec = secbyt(fs, lsec) >> 9;
rv = (fd->f_dev->dv_strategy)(fd->f_devdata, F_READ, lsec,
size, buf, &rsize);
if ((rv == 0) && (size != rsize))
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Mar 12, 8:50 AM (17 h, 30 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29555573
Default Alt Text
D49078.id151825.diff (12 KB)
Attached To
Mode
D49078: loader: dosfs should be able to work with different sector sizes
Attached
Detach File
Event Timeline
Log In to Comment