#ifndef _SYS_FS_PC_FS_H
#define _SYS_FS_PC_FS_H
#include <sys/thread.h>
#include <sys/ksynch.h>
#include <sys/sysmacros.h>
#include <sys/byteorder.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef uint16_t pc_cluster16_t;
typedef uint32_t pc_cluster32_t;
struct bootsec {
uchar_t instr[3];
uchar_t version[8];
uchar_t bps[2];
uchar_t spcl;
uchar_t res_sec[2];
uchar_t nfat;
uchar_t rdirents[2];
uchar_t numsect[2];
uchar_t mediadesriptor;
ushort_t fatsec;
ushort_t spt;
ushort_t nhead;
uint_t hiddensec;
uint_t totalsec;
};
struct fat32_bootsec {
struct bootsec f_bs;
uint32_t f_fatlength;
uint16_t f_flags;
uint8_t f_major;
uint8_t f_minor;
uint32_t f_rootcluster;
uint16_t f_infosector;
uint16_t f_backupboot;
uint16_t f_reserved2[6];
};
#define OFF_JMPBOOT 0
#define OFF_OEMNAME 3
#define OFF_BYTESPERSEC 11
#define OFF_SECPERCLUS 13
#define OFF_RSVDSECCNT 14
#define OFF_NUMFATS 16
#define OFF_ROOTENTCNT 17
#define OFF_TOTSEC16 19
#define OFF_MEDIA 21
#define OFF_FATSZ16 22
#define OFF_SECPERTRK 24
#define OFF_NUMHEADS 26
#define OFF_HIDDSEC 28
#define OFF_TOTSEC32 32
#define OFF_BPBSIG 510
#define OFF_DRVNUM16 36
#define OFF_BOOTSIG16 38
#define OFF_VOLID16 39
#define OFF_VOLLAB16 43
#define OFF_FILSYSTYP16 54
#define OFF_FATSZ32 36
#define OFF_EXTFLAGS32 40
#define OFF_FSVER32 42
#define OFF_ROOTCLUS32 44
#define OFF_FSINFO32 48
#define OFF_BKBOOTSEC32 50
#define OFF_DRVNUM32 64
#define OFF_BOOTSIG32 66
#define OFF_VOLID32 67
#define OFF_VOLLAB32 71
#define OFF_FILSYSTYP32 82
#define LE_16_NA(addr) \
(((uint16_t)*((uint8_t *)(addr))) + \
((uint16_t)*((uint8_t *)(addr) + 1) << 8))
#define LE_32_NA(addr) \
(((uint32_t)*((uint8_t *)(addr))) + \
((uint32_t)*((uint8_t *)(addr) + 1) << 8) + \
((uint32_t)*((uint8_t *)(addr) + 2) << 16) + \
((uint32_t)*((uint8_t *)(addr) + 3) << 24))
#define bpb_jmpBoot(bpb) ((unsigned char *)(bpb))
#define bpb_OEMName(bpb) ((char *)(bpb) + OFF_OEMNAME)
#define bpb_get_BytesPerSec(bpb) LE_16_NA((bpb) + OFF_BYTESPERSEC)
#define bpb_get_SecPerClus(bpb) (((uint8_t *)(bpb))[OFF_SECPERCLUS])
#define bpb_get_RsvdSecCnt(bpb) LE_16_NA((bpb) + OFF_RSVDSECCNT)
#define bpb_get_NumFATs(bpb) (((uint8_t *)(bpb))[OFF_NUMFATS])
#define bpb_get_RootEntCnt(bpb) LE_16_NA((bpb) + OFF_ROOTENTCNT)
#define bpb_get_TotSec16(bpb) LE_16_NA((bpb) + OFF_TOTSEC16)
#define bpb_get_Media(bpb) (((uint8_t *)(bpb))[OFF_MEDIA])
#define bpb_get_FatSz16(bpb) LE_16_NA((bpb) + OFF_FATSZ16)
#define bpb_get_SecPerTrk(bpb) LE_16_NA((bpb) + OFF_SECPERTRK)
#define bpb_get_NumHeads(bpb) LE_16_NA((bpb) + OFF_NUMHEADS)
#define bpb_get_HiddSec(bpb) LE_32_NA((bpb) + OFF_HIDDSEC)
#define bpb_get_TotSec32(bpb) LE_32_NA((bpb) + OFF_TOTSEC32)
#define bpb_get_BPBSig(bpb) LE_16_NA((bpb) + OFF_BPBSIG)
#define bpb_get_DrvNum16(bpb) (((uint8_t *)(bpb))[OFF_DRVNUM16])
#define bpb_get_BootSig16(bpb) (((uint8_t *)(bpb))[OFF_BOOTSIG16])
#define bpb_VolLab16(bpb) ((char *)(bpb) + OFF_VOLLAB16)
#define bpb_FilSysType16(bpb) ((char *)(bpb) + OFF_FILSYSTYP16)
#define bpb_get_VolID16(bpb) LE_32_NA((bpb) + OFF_VOLID16)
#define bpb_get_FatSz32(bpb) LE_32_NA((bpb) + OFF_FATSZ32)
#define bpb_get_ExtFlags32(bpb) LE_16_NA((bpb) + OFF_EXTFLAGS32)
#define bpb_get_FSVer32(bpb) LE_16_NA((bpb) + OFF_FSVER32)
#define bpb_get_RootClus32(bpb) LE_32_NA((bpb) + OFF_ROOTCLUS32)
#define bpb_get_FSInfo32(bpb) LE_16_NA((bpb) + OFF_FSINFO32)
#define bpb_get_BkBootSec32(bpb) LE_16_NA((bpb) + OFF_BKBOOTSEC32)
#define bpb_get_DrvNum32(bpb) (((uint8_t *)(bpb))[OFF_DRVNUM32])
#define bpb_get_BootSig32(bpb) (((uint8_t *)(bpb))[OFF_BOOTSIG32])
#define bpb_get_VolID32(bpb) LE_32_NA((bpb) + OFF_VOLID32)
#define bpb_VolLab32(bpb) ((char *)(bpb) + OFF_VOLLAB32)
#define bpb_FilSysType32(bpb) ((char *)(bpb) + OFF_FILSYSTYP32)
#define VALID_SECSIZE(s) \
(s == 512 || s == 1024 || s == 2048 || s == 4096)
#define VALID_SPCL(s) (ISP2((s)) && (unsigned int)(s) <= 128)
#define VALID_CLSIZE(s) (ISP2((s)) && (unsigned int)(s) <= (64 * 1024))
#define VALID_NUMFATS(n) ((n) > 0 && (n) < 8)
#define VALID_RSVDSEC(s) ((s) > 0)
#define VALID_BPBSIG(sig) ((sig) == MBB_MAGIC)
#define VALID_BOOTSIG(sig) ((sig) == 0x29)
#define VALID_MEDIA(m) ((m) == 0xF0 || ((m) >= 0xF8 && (m) <= 0xFF))
#define VALID_VOLLAB(l) ( \
pc_validchar((l)[0]) && pc_validchar((l)[1]) && \
pc_validchar((l)[2]) && pc_validchar((l)[3]) && \
pc_validchar((l)[4]) && pc_validchar((l)[5]) && \
pc_validchar((l)[6]) && pc_validchar((l)[7]) && \
pc_validchar((l)[8]) && pc_validchar((l)[9]) && \
pc_validchar((l)[10]))
#define VALID_OEMNAME(nm) ( \
bcmp((nm), "MSDOS", 5) == 0 || bcmp((nm), "MSWIN", 5) == 0)
#define VALID_FSTYPSTR16(typ) (bcmp((typ), "FAT", 3) == 0)
#define VALID_FSTYPSTR32(typ) (bcmp((typ), "FAT32", 5) == 0)
#define VALID_JMPBOOT(b) ( \
((b)[0] == 0xeb && (b)[2] == 0x90) || (b)[0] == 0xe9)
#define VALID_FSVER32(v) ((v) == PCFS_SUPPORTED_FSVER)
#define VALID_EXTFLAGS(flags) (((flags) & 0x8f) == (flags))
#define BPB_SECSIZE_OK (1 << 0)
#define BPB_OEMNAME_OK (1 << 1)
#define BPB_JMPBOOT_OK (1 << 2)
#define BPB_SECPERCLUS_OK (1 << 3)
#define BPB_RSVDSECCNT_OK (1 << 4)
#define BPB_NUMFAT_OK (1 << 5)
#define BPB_ROOTENTCNT_OK (1 << 6)
#define BPB_TOTSEC_OK (1 << 7)
#define BPB_TOTSEC16_OK (1 << 8)
#define BPB_TOTSEC32_OK (1 << 9)
#define BPB_MEDIADESC_OK (1 << 10)
#define BPB_FATSZ_OK (1 << 11)
#define BPB_FATSZ16_OK (1 << 12)
#define BPB_FATSZ32_OK (1 << 13)
#define BPB_BPBSIG_OK (1 << 14)
#define BPB_BOOTSIG16_OK (1 << 15)
#define BPB_BOOTSIG32_OK (1 << 16)
#define BPB_FSTYPSTR16_OK (1 << 17)
#define BPB_FSTYPSTR32_OK (1 << 18)
#define BPB_EXTFLAGS_OK (1 << 19)
#define BPB_FSVER_OK (1 << 20)
#define BPB_ROOTCLUSTER_OK (1 << 21)
#define BPB_FSISEC_OK (1 << 22)
#define BPB_BKBOOTSEC_OK (1 << 23)
#define BPB_VOLLAB16_OK (1 << 24)
#define BPB_VOLLAB32_OK (1 << 25)
#define BPB_NCLUSTERS_OK (1 << 26)
#define BPB_CLSIZE_OK (1 << 27)
#define BPB_MEDIASZ_OK (1 << 28)
#define FAT12_VALIDMSK \
(BPB_SECSIZE_OK | BPB_SECPERCLUS_OK | BPB_CLSIZE_OK | \
BPB_RSVDSECCNT_OK | BPB_NUMFAT_OK | BPB_ROOTENTCNT_OK | \
BPB_TOTSEC_OK | BPB_TOTSEC16_OK | \
BPB_FATSZ_OK | BPB_FATSZ16_OK | BPB_BPBSIG_OK)
#define FAT16_VALIDMSK \
(BPB_SECSIZE_OK | BPB_SECPERCLUS_OK | BPB_CLSIZE_OK | \
BPB_RSVDSECCNT_OK | BPB_NUMFAT_OK | BPB_ROOTENTCNT_OK | \
BPB_TOTSEC_OK | BPB_TOTSEC16_OK | BPB_TOTSEC32_OK | \
BPB_FATSZ_OK | BPB_FATSZ16_OK | BPB_BPBSIG_OK)
#define FAT32_VALIDMSK \
(BPB_SECSIZE_OK | BPB_SECPERCLUS_OK | BPB_CLSIZE_OK | \
BPB_RSVDSECCNT_OK | BPB_NUMFAT_OK | BPB_ROOTENTCNT_OK | \
BPB_TOTSEC_OK | BPB_TOTSEC16_OK | BPB_TOTSEC32_OK | \
BPB_FATSZ_OK | BPB_FATSZ16_OK | BPB_FATSZ32_OK | \
BPB_EXTFLAGS_OK | BPB_FSVER_OK | BPB_ROOTCLUSTER_OK | \
BPB_BPBSIG_OK)
#define PCFS_SUPPORTED_FSVER 0
typedef struct fat_fsinfo {
uint32_t fs_free_clusters;
uint32_t fs_next_free;
} fat_fsi_t;
typedef struct fat_od_fsi {
uint32_t fsi_leadsig;
char fsi_reserved1[480];
uint32_t fsi_strucsig;
fat_fsi_t fsi_incore;
char fsi_reserved2[12];
uint32_t fsi_trailsig;
} fat_od_fsi_t;
#define FSI_LEADSIG LE_32(0x41615252)
#define FSI_STRUCSIG LE_32(0x61417272)
#define FSI_TRAILSIG LE_32(0xaa550000)
#define FSISIG_OK(fsi) ( \
((fat_od_fsi_t *)(fsi))->fsi_leadsig == FSI_LEADSIG && \
((fat_od_fsi_t *)(fsi))->fsi_strucsig == FSI_STRUCSIG && \
((fat_od_fsi_t *)(fsi))->fsi_trailsig == FSI_TRAILSIG)
#define FSINFO_UNKNOWN ((uint32_t)(-1))
typedef enum { FAT12, FAT16, FAT32, FAT_UNKNOWN, FAT_QUESTIONABLE } fattype_t;
struct pcfs {
struct vfs *pcfs_vfs;
int pcfs_flags;
int pcfs_ldrive;
fattype_t pcfs_fattype;
dev_t pcfs_xdev;
struct vnode *pcfs_devvp;
int pcfs_secsize;
int pcfs_spcl;
int pcfs_spt;
int pcfs_sdshift;
int pcfs_fatsec;
int pcfs_numfat;
int pcfs_rdirsec;
daddr_t pcfs_dosstart;
daddr_t pcfs_fsistart;
daddr_t pcfs_fatstart;
daddr_t pcfs_rdirstart;
daddr_t pcfs_datastart;
int pcfs_clsize;
int pcfs_ncluster;
int pcfs_nrefs;
int pcfs_frefs;
int pcfs_nxfrecls;
uchar_t *pcfs_fatp;
uchar_t *pcfs_fat_changemap;
int pcfs_fat_changemapsize;
time_t pcfs_fattime;
time_t pcfs_verifytime;
kmutex_t pcfs_lock;
kthread_id_t pcfs_owner;
int pcfs_count;
struct fat_fsinfo pcfs_fsinfo;
struct pcfs *pcfs_nxt;
int pcfs_fatjustread;
struct vnode *pcfs_root;
int pcfs_secondswest;
len_t pcfs_mediasize;
int pcfs_rootblksize;
int pcfs_mediadesc;
pc_cluster32_t pcfs_lastclmark;
pc_cluster32_t pcfs_rootclnum;
timestruc_t pcfs_mounttime;
};
#define PCFS_FATMOD 0x01
#define PCFS_LOCKED 0x02
#define PCFS_WANTED 0x04
#define PCFS_NOCHK 0x800
#define PCFS_BOOTPART 0x1000
#define PCFS_HIDDEN 0x2000
#define PCFS_PCMCIA_NO_CIS 0x4000
#define PCFS_FOLDCASE 0x8000
#define PCFS_FSINFO_OK 0x10000
#define PCFS_IRRECOV 0x20000
#define PCFS_NOCLAMPTIME 0x40000
#define PCFS_NOATIME 0x80000
#define IS_FAT12(PCFS) ((PCFS)->pcfs_fattype == FAT12)
#define IS_FAT16(PCFS) ((PCFS)->pcfs_fattype == FAT16)
#define IS_FAT32(PCFS) ((PCFS)->pcfs_fattype == FAT32)
struct old_pcfs_args {
int secondswest;
int dsttime;
};
struct pcfs_args {
int secondswest;
int dsttime;
int flags;
};
#define MNTOPT_PCFS_HIDDEN "hidden"
#define MNTOPT_PCFS_NOHIDDEN "nohidden"
#define MNTOPT_PCFS_FOLDCASE "foldcase"
#define MNTOPT_PCFS_NOFOLDCASE "nofoldcase"
#define MNTOPT_PCFS_CLAMPTIME "clamptime"
#define MNTOPT_PCFS_NOCLAMPTIME "noclamptime"
#define MNTOPT_PCFS_TIMEZONE "timezone"
#define MNTOPT_PCFS_SECSIZE "secsize"
#define PCFS_DISKTIMEOUT 2
#define PCFS_MAXOFFSET_T UINT32_MAX
#define VFSTOPCFS(VFSP) ((struct pcfs *)((VFSP)->vfs_data))
#define PCFSTOVFS(FSP) ((FSP)->pcfs_vfs)
#define PCF_FREECLUSTER 0x00
#define PCF_ERRORCLUSTER 0x01
#define PCF_12BCLUSTER 0xFF0
#define PCF_RESCLUSTER 0xFFF0
#define PCF_RESCLUSTER32 0xFFFFFF0
#define PCF_BADCLUSTER 0xFFF7
#define PCF_BADCLUSTER32 0xFFFFFF7
#define PCF_LASTCLUSTER 0xFFF8
#define PCF_LASTCLUSTER32 0xFFFFFF8
#define PCF_LASTCLUSTERMARK 0xFFFF
#define PCF_LASTCLUSTERMARK32 0xFFFFFFF
#define PCF_FIRSTCLUSTER 2
#define PC_MAXFATSEC 256
#define pc_clear_fatchanges(PCFS) \
bzero((PCFS)->pcfs_fat_changemap, (PCFS)->pcfs_fat_changemapsize)
#define pc_blksize(PCFS, PCP, OFF) \
(((PCTOV(PCP)->v_flag & VROOT) && !IS_FAT32(PCFS)) ? \
((OFF) >= \
((PCFS)->pcfs_rdirsec & \
~((PCFS)->pcfs_spcl - 1)) * ((PCFS)->pcfs_secsize)? \
((PCFS)->pcfs_rdirsec & \
((PCFS)->pcfs_spcl - 1)) * ((PCFS)->pcfs_secsize): \
(PCFS)->pcfs_clsize): \
(PCFS)->pcfs_clsize)
#define pc_blkoff(PCFS, OFF) \
((int)((OFF) & ((PCFS)->pcfs_clsize - 1)))
#define pc_lblkno(PCFS, OFF) \
((daddr_t)((OFF) / (PCFS)->pcfs_clsize))
#define pc_dbtocl(PCFS, DB) \
((int)((DB) / (PCFS)->pcfs_spcl))
#define pc_cltodb(PCFS, CL) \
((daddr_t)((CL) * (PCFS)->pcfs_spcl))
#define pc_dbdaddr(PCFS, DB) \
((DB) << (PCFS)->pcfs_sdshift)
#define pc_daddrdb(PCFS, DADDR) \
((DADDR) >> (PCFS)->pcfs_sdshift)
#define pc_cldaddr(PCFS, CL) \
pc_dbdaddr(PCFS, ((daddr_t)((PCFS)->pcfs_datastart + \
pc_cltodb(PCFS, (CL) - PCF_FIRSTCLUSTER))))
#define pc_daddrcl(PCFS, DADDR) \
((int)(PCF_FIRSTCLUSTER + \
pc_dbtocl(pc_daddrdb(PCFS, DADDR) - (PCFS)->pcfs_datastart)))
#define pc_direntpersec(PCFS) \
((int)((PCFS)->pcfs_secsize / sizeof (struct pcdir)))
#define pc_direntpercl(PCFS) \
((int)((PCFS)->pcfs_clsize / sizeof (struct pcdir)))
#define pc_validcl(PCFS, CL) \
((int)(CL) >= PCF_FIRSTCLUSTER && \
(int)(CL) < (PCFS)->pcfs_ncluster + PCF_FIRSTCLUSTER)
extern int pc_lockfs(struct pcfs *, int, int);
extern void pc_unlockfs(struct pcfs *);
extern int pc_getfat(struct pcfs *);
extern void pc_invalfat(struct pcfs *);
extern int pc_syncfat(struct pcfs *);
extern int pc_freeclusters(struct pcfs *);
extern pc_cluster32_t pc_alloccluster(struct pcfs *, int);
extern void pc_setcluster(struct pcfs *, pc_cluster32_t, pc_cluster32_t);
extern void pc_mark_fat_updated(struct pcfs *fsp, pc_cluster32_t cn);
extern int pc_fat_is_changed(struct pcfs *fsp, pc_cluster32_t bn);
extern int pcfsdebuglevel;
#define PC_DPRINTF0(level, A) \
if (pcfsdebuglevel >= level) \
cmn_err(CE_CONT, (A))
#define PC_DPRINTF1(level, A, B) \
if (pcfsdebuglevel >= level) \
cmn_err(CE_CONT, (A), (B))
#define PC_DPRINTF2(level, A, B, C) \
if (pcfsdebuglevel >= level) \
cmn_err(CE_CONT, (A), (B), (C))
#define PC_DPRINTF3(level, A, B, C, D) \
if (pcfsdebuglevel >= level) \
cmn_err(CE_CONT, (A), (B), (C), (D))
#define PC_DPRINTF4(level, A, B, C, D, E) \
if (pcfsdebuglevel >= level) \
cmn_err(CE_CONT, (A), (B), (C), (D), (E))
#ifdef __cplusplus
}
#endif
#endif