Support FAT12/16

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@223 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2007-05-13 23:13:42 +00:00
parent a27c0911f4
commit b2aa745708
2 changed files with 95 additions and 25 deletions

View File

@ -78,14 +78,18 @@
#define MBR_GETSECPERCLUS(p) UBYTE_VAL(p,BS_SECPERCLUS)
#define MBR_GETNUMFATS(p) UBYTE_VAL(p,BS_NUMFATS)
#define MBR_GETMEDIA(p) UBYTE_VAL(p,BS_MEDIA)
#define MBR_GETDRVNUM(p) UBYTE_VAL(p,BS32_DRVNUM)
#define MBR_GETBOOTSIG(p) UBYTE_VAL(p,BS32_BOOTSIG)
#define MBR_GETDRVNUM16(p) UBYTE_VAL(p,BS16_DRVNUM)
#define MBR_GETDRVNUM32(p) UBYTE_VAL(p,BS32_DRVNUM)
#define MBR_GETBOOTSIG16(p) UBYTE_VAL(p,BS16_BOOTSIG)
#define MBR_GETBOOTSIG32(p) UBYTE_VAL(p,BS32_BOOTSIG)
#define MBR_PUTSECPERCLUS(p,v) UBYTE_PUT(p,BS_SECPERCLUS),v)
#define MBR_PUTNUMFATS(p,v) UBYTE_PUT(p,BS_NUMFATS,v)
#define MBR_PUTMEDIA(p,v) UBYTE_PUT(p,BS_MEDIA,v)
#define MBR_PUTDRVNUM(p,v) UBYTE_PUT(p,BS32_DRVNUM,v)
#define MBR_PUTBOOTSIG(p,v) UBYTE_PUT(p,BS32_BOOTSIG,v)
#define MBR_PUTDRVNUM16(p,v) UBYTE_PUT(p,BS16_DRVNUM,v)
#define MBR_PUTDRVNUM32(p,v) UBYTE_PUT(p,BS32_DRVNUM,v)
#define MBR_PUTBOOTSIG16(p,v) UBYTE_PUT(p,BS16_BOOTSIG,v)
#define MBR_PUTBOOTSIG32(p,v) UBYTE_PUT(p,BS32_BOOTSIG,v)
/* For the all targets, unaligned values need to be accessed byte-by-byte.
* Some architectures may handle unaligned accesses with special interrupt
@ -97,12 +101,14 @@
#define MBR_GETBYTESPERSEC(p) fat_getuint16(UBYTE_PTR(p,BS_BYTESPERSEC))
#define MBR_GETROOTENTCNT(p) fat_getuint16(UBYTE_PTR(p,BS_ROOTENTCNT))
#define MBR_GETTOTSEC16(p) fat_getuint16(UBYTE_PTR(p,BS_TOTSEC16))
#define MBR_GETVOLID(p) fat_getuint32(UBYTE_PTR(p,BS32_VOLID))
#define MBR_GETVOLID16(p) fat_getuint32(UBYTE_PTR(p,BS16_VOLID))
#define MBR_GETVOLID32(p) fat_getuint32(UBYTE_PTR(p,BS32_VOLID))
#define MBR_PUTBYTESPERSEC(p,v) fat_putuint16(UBYTE_PTR(p,BS_BYTESPERSEC),v)
#define MBR_PUTROOTENTCNT(p,v) fat_putuint16(UBYTE_PTR(p,BS_ROOTENTCNT),v)
#define MBR_PUTTOTSEC16(p,v) fat_putuint16(UBYTE_PTR(p,BS_TOTSEC16),v)
#define MBR_PUTVOLID(p,v) fat_putuint32(UBYTE_PTR(p,BS32_VOLID),v)
#define MBR_PUTVOLID16(p,v) fat_putuint32(UBYTE_PTR(p,BS16_VOLID),v)
#define MBR_PUTVOLID32(p,v) fat_putuint32(UBYTE_PTR(p,BS32_VOLID),v)
/* But for multi-byte values, the endian-ness of the target vs. the little
* endian order of the byte stream or alignment of the data within the byte
@ -468,8 +474,11 @@ static int fat_readfsinfo(struct fat_mountpt_s *fs)
static int fat_checkbootrecord(struct fat_mountpt_s *fs)
{
uint32 ndatasectors;
uint32 fatsize;
uint32 ndatasectors;
uint32 fatsize;
uint16 rootentcnt;
uint16 rootdirsectors = 0;
boolean notfat32 = FALSE;
/* Verify the MBR signature at offset 510 in the sector (true even
* if the sector size is greater than 512. All FAT file systems have
@ -479,7 +488,6 @@ static int fat_checkbootrecord(struct fat_mountpt_s *fs)
*/
if (MBR_GETSIGNATURE(fs->fs_buffer) != 0xaa55 ||
MBR_GETROOTENTCNT(fs->fs_buffer) != 0 ||
MBR_GETBYTESPERSEC(fs->fs_buffer) != fs->fs_hwsectorsize)
{
return -ENODEV;
@ -490,16 +498,30 @@ static int fat_checkbootrecord(struct fat_mountpt_s *fs)
* volume has < 4085 cluseter, a FAT16 volume has fewer than 65,525
* clusters, and any larger is FAT32.
*
* Determine the number of sectors in a FAT.
* Get the number of 32-bit directory entries in root directory (zero
* for FAT32.
*/
fs->fs_rootentcnt = MBR_GETROOTENTCNT(fs->fs_buffer);
if (fs->fs_rootentcnt != 0)
{
notfat32 = TRUE; /* Must be zero for FAT32 */
rootdirsectors = (32 * fs->fs_rootentcnt + fs->fs_hwsectorsize - 1) / fs->fs_hwsectorsize;
}
/* Determine the number of sectors in a FAT. */
fs->fs_fatsize = MBR_GETFATSZ16(fs->fs_buffer); /* Should be zero */
if (!fs->fs_fatsize)
if (fs->fs_fatsize)
{
notfat32 = TRUE; /* Must be zero for FAT32 */
}
else
{
fs->fs_fatsize = MBR_GETFATSZ32(fs->fs_buffer);
}
if (fs->fs_fatsize >= fs->fs_hwnsectors)
if (!fs->fs_fatsize || fs->fs_fatsize >= fs->fs_hwnsectors)
{
return -ENODEV;
}
@ -507,12 +529,16 @@ static int fat_checkbootrecord(struct fat_mountpt_s *fs)
/* Get the total number of sectors on the volume. */
fs->fs_fattotsec = MBR_GETTOTSEC16(fs->fs_buffer); /* Should be zero */
if (!fs->fs_fattotsec)
if (fs->fs_fattotsec)
{
notfat32 = TRUE; /* Must be zero for FAT32 */
}
else
{
fs->fs_fattotsec = MBR_GETTOTSEC32(fs->fs_buffer);
}
if (fs->fs_fattotsec > fs->fs_hwnsectors)
if (!fs->fs_fattotsec || fs->fs_fattotsec > fs->fs_hwnsectors)
{
return -ENODEV;
}
@ -532,7 +558,7 @@ static int fat_checkbootrecord(struct fat_mountpt_s *fs)
/* Get the total number of data sectors */
ndatasectors = fs->fs_fattotsec - fs->fs_fatresvdseccount - fatsize;
ndatasectors = fs->fs_fattotsec - fs->fs_fatresvdseccount - fatsize - rootdirsectors;
if (ndatasectors > fs->fs_hwnsectors)
{
return -ENODEV;
@ -548,7 +574,23 @@ static int fat_checkbootrecord(struct fat_mountpt_s *fs)
/* Finally, the test: */
if (fs->fs_nclusters < 65525)
if (fs->fs_nclusters < 4085)
{
fs->fs_fsinfo = 0;
fs->fs_type = FSTYPE_FAT12;
}
else if (fs->fs_nclusters < 65525)
{
fs->fs_fsinfo = 0;
fs->fs_type = FSTYPE_FAT16;
}
else if (!notfat32)
{
fs->fs_fsinfo = fs->fs_fatbase + MBR_GETFSINFO(fs->fs_buffer);
fs->fs_type = FSTYPE_FAT32;
}
else
{
return -ENODEV;
}
@ -557,10 +599,18 @@ static int fat_checkbootrecord(struct fat_mountpt_s *fs)
* from the boot record that we will need later.
*/
fs->fs_fsinfo = fs->fs_fatbase + MBR_GETFSINFO(fs->fs_buffer);
fs->fs_fatbase += fs->fs_fatresvdseccount;
fs->fs_database = fs->fs_fatbase + fatsize;
fs->fs_rootclus = MBR_GETROOTCLUS(fs->fs_buffer);
if (fs->fs_type == FSTYPE_FAT32)
{
fs->fs_rootbase = MBR_GETROOTCLUS(fs->fs_buffer);
}
else
{
fs->fs_rootbase = fs->fs_fatbase + fatsize;
}
fs->fs_database = fs->fs_fatbase + fatsize + fs->fs_rootentcnt / (fs->fs_hwsectorsize / 32);
fs->fs_fsifreecount = 0xffffffff;
return OK;
@ -675,13 +725,16 @@ static int fat_mount(struct fat_mountpt_s *fs, boolean writeable)
}
/* We have what appears to be a valid FAT filesystem! Now read the
* FSINFO sector.
* FSINFO sector (FAT32 only)
*/
ret = fat_readfsinfo(fs);
if (ret != OK)
if (fs->fs_type == FSTYPE_FAT32)
{
goto errout_with_buffer;
ret = fat_readfsinfo(fs);
if (ret != OK)
{
goto errout_with_buffer;
}
}
/* We did it! */

View File

@ -61,7 +61,7 @@
#define BS_SECPERCLUS 13 /* 1@13: Sectors per allocation unit: 2**n, n=0..7 */
#define BS_RESVDSECCOUNT 14 /* 2@14: Reserved sector count: Usually 32 */
#define BS_NUMFATS 16 /* 1@16: Number of FAT data structures: always 2 */
#define BS_ROOTENTCNT 17 /* 2@17: FAT12/16: Must be 0 for FAT32*/
#define BS_ROOTENTCNT 17 /* 2@17: FAT12/16: Must be 0 for FAT32 */
#define BS_TOTSEC16 19 /* 2@19: FAT12/16: Must be 0, see BS32_totsec32 */
#define BS_MEDIA 21 /* 1@21: Media code: f0, f8, f9-fa, fc-ff */
#define BS_FATSZ16 22 /* 2@22: FAT12/16: Must be 0, see BS32_fatsz32 */
@ -70,6 +70,15 @@
#define BS_HIDSEC 28 /* 4@28: Count of hidden sectors preceding FAT */
#define BS_TOTSEC32 32 /* 4@32: Total count of sectors on the volume */
/* The following fields are only valid for FAT12/16 */
#define BS16_DRVNUM 36 /* 1@36: Drive number for MSDOS bootstrap */
/* 1@37: Reserverd (zero) */
#define BS16_BOOTSIG 38 /* 1@38: Extended boot signature: 0x29 if following valid */
#define BS16_VOLID 39 /* 4@39: Volume serial number */
#define BS16_VOLLAB 43 /* 11@43: Volume label */
#define BS16_FILESYSTYPE 54 /* 8@54: "FAT12 ", "FAT16 ", or "FAT " */
/* The following fields are only valid for FAT32 */
#define BS32_FATSZ32 36 /* 4@36: Count of sectors occupied by one FAT */
@ -96,6 +105,12 @@
#define BS_SIGNATURE 510 /* 2@510: Valid MBRs have 0x55aa here */
/* File system types */
#define FSTYPE_FAT12 0
#define FSTYPE_FAT16 1
#define FSTYPE_FAT32 2
/****************************************************************************
* These offset describe the FSINFO sector
*/
@ -157,15 +172,17 @@ struct fat_mountpt_s
size_t fs_hwsectorsize; /* HW: Sector size reported by block driver*/
size_t fs_hwnsectors; /* HW: The number of sectors reported by the hardware */
size_t fs_fatbase; /* Logical block of start of filesystem (past resd sectors) */
size_t fs_rootbase; /* MBR: Cluster no. of 1st cluster of root dir */
size_t fs_database; /* Logical block of start data sectors */
size_t fs_fsinfo; /* MBR: Sector number of FSINFO sector */
uint32 fs_nclusters; /* Maximum number of data clusters */
uint32 fs_rootclus; /* MBR: Cluster no. of 1st cluster of root dir */
uint32 fs_fatsize; /* MBR: Count of sectors occupied by one fat */
uint32 fs_fattotsec; /* MBR: Total count of sectors on the volume */
uint32 fs_fsifreecount; /* FSI: Last free cluster count on volume */
uint32 fs_fsinextfree; /* FSI: Cluster number of 1st free cluster */
uint16 fs_fatresvdseccount; /* MBR: The total number of reserved sectors */
uint16 fs_rootentcnt; /* MBR: Count of 32-bit root directory entries */
ubyte fs_type; /* FSTYPE_FAT12, FSTYPE_FAT16, or FSTYPE_FAT32 */
ubyte fs_fatnumfats; /* MBR: Number of FATs (probably 2) */
ubyte fs_fatsecperclus; /* MBR: Sectors per allocation unit: 2**n, n=0..7 */
ubyte *fs_buffer; /* This is an allocated buffer to hold one sector