summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2007-05-13 23:13:42 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2007-05-13 23:13:42 +0000
commit51ea417e2ea2fb4e339cb55d4e5ccd02368f62ab (patch)
treed8b7c6f4584ba8c89ac92cbe1b6eb9b1611fe43f
parent116ec488ee7d616e562aecbc236e63ef43a90c7c (diff)
downloadnuttx-51ea417e2ea2fb4e339cb55d4e5ccd02368f62ab.tar.gz
nuttx-51ea417e2ea2fb4e339cb55d4e5ccd02368f62ab.tar.bz2
nuttx-51ea417e2ea2fb4e339cb55d4e5ccd02368f62ab.zip
Support FAT12/16
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@223 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r--nuttx/fs/fs_fat32.c99
-rw-r--r--nuttx/fs/fs_fat32.h21
2 files changed, 95 insertions, 25 deletions
diff --git a/nuttx/fs/fs_fat32.c b/nuttx/fs/fs_fat32.c
index 9edd320c4..f4bed845e 100644
--- a/nuttx/fs/fs_fat32.c
+++ b/nuttx/fs/fs_fat32.c
@@ -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! */
diff --git a/nuttx/fs/fs_fat32.h b/nuttx/fs/fs_fat32.h
index 996af5c54..3368029ba 100644
--- a/nuttx/fs/fs_fat32.h
+++ b/nuttx/fs/fs_fat32.h
@@ -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