Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

# fat.h

Go to the documentation of this file.

    00001 /*! \file fat.h \brief FAT16/32 file system driver. */
    00002 //*****************************************************************************
    00003 //
    00004 // File Name    : 'fat.h'
    00005 // Title        : FAT16/32 file system driver
    00006 // Author       : Pascal Stang
    00007 // Date         : 11/07/2000
    00008 // Revised      : 12/12/2000
    00009 // Version      : 0.3
    00010 // Target MCU   : ATmega103 (should work for Atmel AVR Series)
    00011 // Editor Tabs  : 4
    00012 //
    00013 // NOTE: This code is currently below version 1.0, and therefore is considered
    00014 // to be lacking in some functionality or documentation, or may not be fully
    00015 // tested.  Nonetheless, you can expect most functions to work.
    00016 //
    00017 /// \ingroup general
    00018 /// \defgroup fat FAT16/32 File System Interface (fat.c)
    00019 /// \code #include "fat.h" \endcode
    00020 /// \par Overview
    00021 ///     This FAT16/32 interface allows you to detect and mount FAT16/32
    00022 ///     partitions, browse directories and files, and read file data.
    00023 ///     The interface is designed to operate with the avrlib IDE/ATA driver.
    00024 ///     Reading FAT efficiently requires at least 512+ bytes of RAM so this
    00025 ///     interface may not be suitable for processors with less than 1K of RAM.
    00026 ///     This interface will properly follow a file's cluster chain so files
    00027 ///     need not be defragmented.
    00028 ///
    00029 /// \note This code is based in part on work done by Jesper Hansen for his
    00030 ///     excellent YAMPP MP3 player project.
    00031 //
    00032 // This code is distributed under the GNU Public License
    00033 //      which can be found at http://www.gnu.org/licenses/gpl.txt
    00034 //
    00035 //*****************************************************************************
    00036
    00037 #ifndef FAT_H
    00038 #define FAT_H
    00039
    00040 #include "global.h"
    00041
    00042
    00043 // Some useful cluster numbers
    00044 #define MSDOSFSROOT     0               // cluster 0 means the root dir
    00045 #define CLUST_FREE      0               // cluster 0 also means a free cluster
    00046 #define MSDOSFSFREE     CLUST_FREE
    00047 #define CLUST_FIRST     2               // first legal cluster number
    00048 #define CLUST_RSRVD     0xfffffff6      // reserved cluster range
    00049 #define CLUST_BAD       0xfffffff7      // a cluster with a defect
    00050 #define CLUST_EOFS      0xfffffff8      // start of eof cluster range
    00051 #define CLUST_EOFE      0xffffffff      // end of eof cluster range
    00052
    00053 #define FAT12_MASK      0x00000fff      // mask for 12 bit cluster numbers
    00054 #define FAT16_MASK      0x0000ffff      // mask for 16 bit cluster numbers
    00055 #define FAT32_MASK      0x0fffffff      // mask for FAT32 cluster numbers
    00056
    00057
    00058 // Partition Type used in the partition record
    00059 #define PART_TYPE_UNKNOWN       0x00
    00060 #define PART_TYPE_FAT12         0x01
    00061 #define PART_TYPE_XENIX         0x02
    00062 #define PART_TYPE_DOSFAT16      0x04
    00063 #define PART_TYPE_EXTDOS        0x05
    00064 #define PART_TYPE_FAT16         0x06
    00065 #define PART_TYPE_NTFS          0x07
    00066 #define PART_TYPE_FAT32         0x0B
    00067 #define PART_TYPE_FAT32LBA      0x0C
    00068 #define PART_TYPE_FAT16LBA      0x0E
    00069 #define PART_TYPE_EXTDOSLBA     0x0F
    00070 #define PART_TYPE_ONTRACK       0x33
    00071 #define PART_TYPE_NOVELL        0x40
    00072 #define PART_TYPE_PCIX          0x4B
    00073 #define PART_TYPE_PHOENIXSAVE   0xA0
    00074 #define PART_TYPE_CPM           0xDB
    00075 #define PART_TYPE_DBFS          0xE0
    00076 #define PART_TYPE_BBT           0xFF
    00077
    00078 struct partrecord // length 16 bytes
    00079 {
    00080     BYTE    prIsActive;                 // 0x80 indicates active partition
    00081     BYTE    prStartHead;                // starting head for partition
    00082     WORD    prStartCylSect;             // starting cylinder and sector
    00083     BYTE    prPartType;                 // partition type (see above)
    00084     BYTE    prEndHead;                  // ending head for this partition
    00085     WORD    prEndCylSect;               // ending cylinder and sector
    00086     DWORD   prStartLBA;                 // first LBA sector for this partition
    00087     DWORD   prSize;                     // size of this partition (bytes or sectors ?)
    00088 };
    00089
    00090
    00091 struct partsector
    00092 {
    00093     CHAR    psPartCode[512-64-2];       // pad so struct is 512b
    00094     BYTE    psPart[64];                 // four partition records (64 bytes)
    00095     BYTE    psBootSectSig0;             // two signature bytes (2 bytes)
    00096     BYTE    psBootSectSig1;
    00097 #define BOOTSIG0        0x55
    00098 #define BOOTSIG1        0xaa
    00099 };
    00100
    00101
    00102
    00103 // Format of a boot sector.  This is the first sector on a DOS floppy disk
    00104 // or the first sector of a partition on a hard disk.  But, it is not the
    00105 // first sector of a partitioned hard disk.
    00106 struct bootsector33 {
    00107     BYTE    bsJump[3];                  // jump inst E9xxxx or EBxx90
    00108     CHAR    bsOemName[8];               // OEM name and version
    00109     CHAR    bsBPB[19];                  // BIOS parameter block
    00110     CHAR    bsDriveNumber;              // drive number (0x80)
    00111     CHAR    bsBootCode[479];            // pad so struct is 512b
    00112     BYTE    bsBootSectSig0;             // boot sector signature byte 0x55
    00113     BYTE    bsBootSectSig1;             // boot sector signature byte 0xAA
    00114 #define BOOTSIG0        0x55
    00115 #define BOOTSIG1        0xaa
    00116 };
    00117
    00118 struct extboot {
    00119     CHAR    exDriveNumber;              // drive number (0x80)
    00120     CHAR    exReserved1;                // reserved
    00121     CHAR    exBootSignature;            // ext. boot signature (0x29)
    00122 #define EXBOOTSIG       0x29
    00123     CHAR    exVolumeID[4];              // volume ID number
    00124     CHAR    exVolumeLabel[11];          // volume label
    00125     CHAR    exFileSysType[8];           // fs type (FAT12 or FAT16)
    00126 };
    00127
    00128 struct bootsector50 {
    00129     BYTE    bsJump[3];                  // jump inst E9xxxx or EBxx90
    00130     CHAR    bsOemName[8];               // OEM name and version
    00131     CHAR    bsBPB[25];                  // BIOS parameter block
    00132     CHAR    bsExt[26];                  // Bootsector Extension
    00133     CHAR    bsBootCode[448];            // pad so structure is 512b
    00134     BYTE    bsBootSectSig0;             // boot sector signature byte 0x55
    00135     BYTE    bsBootSectSig1;             // boot sector signature byte 0xAA
    00136 #define BOOTSIG0        0x55
    00137 #define BOOTSIG1        0xaa
    00138 };
    00139
    00140 struct bootsector710 {
    00141     BYTE    bsJump[3];                  // jump inst E9xxxx or EBxx90
    00142     CHAR    bsOEMName[8];               // OEM name and version
    00143     CHAR    bsBPB[53];                  // BIOS parameter block
    00144     CHAR    bsExt[26];                  // Bootsector Extension
    00145     CHAR    bsBootCode[418];            // pad so structure is 512b
    00146     BYTE    bsBootSectSig2;             // 2 & 3 are only defined for FAT32?
    00147     BYTE    bsBootSectSig3;
    00148     BYTE    bsBootSectSig0;             // boot sector signature byte 0x55
    00149     BYTE    bsBootSectSig1;             // boot sector signature byte 0xAA
    00150 #define BOOTSIG0        0x55
    00151 #define BOOTSIG1        0xaa
    00152 #define BOOTSIG2        0
    00153 #define BOOTSIG3        0
    00154 };
    00155
    00156
    00157 /***************************************************************/
    00158 /***************************************************************/
    00159
    00160 // BIOS Parameter Block (BPB) for DOS 3.3
    00161 struct bpb33 {
    00162         WORD    bpbBytesPerSec; // bytes per sector
    00163         BYTE    bpbSecPerClust; // sectors per cluster
    00164         WORD    bpbResSectors;  // number of reserved sectors
    00165         BYTE    bpbFATs;        // number of FATs
    00166         WORD    bpbRootDirEnts; // number of root directory entries
    00167         WORD    bpbSectors;     // total number of sectors
    00168         BYTE    bpbMedia;       // media descriptor
    00169         WORD    bpbFATsecs;     // number of sectors per FAT
    00170         WORD    bpbSecPerTrack; // sectors per track
    00171         WORD    bpbHeads;       // number of heads
    00172         WORD    bpbHiddenSecs;  // number of hidden sectors
    00173 };
    00174
    00175 // BPB for DOS 5.0
    00176 // The difference is bpbHiddenSecs is a short for DOS 3.3,
    00177 // and bpbHugeSectors is not present in the DOS 3.3 bpb.
    00178 struct bpb50 {
    00179         WORD    bpbBytesPerSec; // bytes per sector
    00180         BYTE    bpbSecPerClust; // sectors per cluster
    00181         WORD    bpbResSectors;  // number of reserved sectors
    00182         BYTE    bpbFATs;        // number of FATs
    00183         WORD    bpbRootDirEnts; // number of root directory entries
    00184         WORD    bpbSectors;     // total number of sectors
    00185         BYTE    bpbMedia;       // media descriptor
    00186         WORD    bpbFATsecs;     // number of sectors per FAT
    00187         WORD    bpbSecPerTrack; // sectors per track
    00188         WORD    bpbHeads;       // number of heads
    00189         DWORD   bpbHiddenSecs;  // # of hidden sectors
    00190 // 3.3 compat ends here
    00191         DWORD   bpbHugeSectors; // # of sectors if bpbSectors == 0
    00192 };
    00193
    00194 // BPB for DOS 7.10 (FAT32)
    00195 // This one has a few extensions to bpb50.
    00196 struct bpb710 {
    00197         WORD    bpbBytesPerSec; // bytes per sector
    00198         BYTE    bpbSecPerClust; // sectors per cluster
    00199         WORD    bpbResSectors;  // number of reserved sectors
    00200         BYTE    bpbFATs;        // number of FATs
    00201         WORD    bpbRootDirEnts; // number of root directory entries
    00202         WORD    bpbSectors;     // total number of sectors
    00203         BYTE    bpbMedia;       // media descriptor
    00204         WORD    bpbFATsecs;     // number of sectors per FAT
    00205         WORD    bpbSecPerTrack; // sectors per track
    00206         WORD    bpbHeads;       // number of heads
    00207         DWORD   bpbHiddenSecs;  // # of hidden sectors
    00208 // 3.3 compat ends here
    00209         DWORD   bpbHugeSectors; // # of sectors if bpbSectors == 0
    00210 // 5.0 compat ends here
    00211         DWORD     bpbBigFATsecs;// like bpbFATsecs for FAT32
    00212         WORD      bpbExtFlags;  // extended flags:
    00213 #define FATNUM    0xf           // mask for numbering active FAT
    00214 #define FATMIRROR 0x80          // FAT is mirrored (like it always was)
    00215         WORD      bpbFSVers;    // filesystem version
    00216 #define FSVERS    0             // currently only 0 is understood
    00217         DWORD     bpbRootClust; // start cluster for root directory
    00218         WORD      bpbFSInfo;    // filesystem info structure sector
    00219         WORD      bpbBackup;    // backup boot sector
    00220         // There is a 12 byte filler here, but we ignore it
    00221 };
    00222
    00223
    00224
    00225
    00226 // ***************************************************************
    00227 // * byte versions of the above structs                          *
    00228 // ***************************************************************
    00229
    00230
    00231 // BIOS Parameter Block (BPB) for DOS 3.3
    00232 struct byte_bpb33 {
    00233         CHAR bpbBytesPerSec[2];     // bytes per sector
    00234         CHAR bpbSecPerClust;        // sectors per cluster
    00235         CHAR bpbResSectors[2];      // number of reserved sectors
    00236         CHAR bpbFATs;               // number of FATs
    00237         CHAR bpbRootDirEnts[2];     // number of root directory entries
    00238         CHAR bpbSectors[2];         // total number of sectors
    00239         CHAR bpbMedia;              // media descriptor
    00240         CHAR bpbFATsecs[2];         // number of sectors per FAT
    00241         CHAR bpbSecPerTrack[2];     // sectors per track
    00242         CHAR bpbHeads[2];           // number of heads
    00243         CHAR bpbHiddenSecs[2];      // number of hidden sectors
    00244 };
    00245
    00246 // BPB for DOS 5.0
    00247 // The difference is bpbHiddenSecs is a short for DOS 3.3,
    00248 // and bpbHugeSectors is not in the 3.3 bpb.
    00249 struct byte_bpb50 {
    00250         CHAR bpbBytesPerSec[2];     // bytes per sector
    00251         CHAR bpbSecPerClust;        // sectors per cluster
    00252         CHAR bpbResSectors[2];      // number of reserved sectors
    00253         CHAR bpbFATs;               // number of FATs
    00254         CHAR bpbRootDirEnts[2];     // number of root directory entries
    00255         CHAR bpbSectors[2];         // total number of sectors
    00256         CHAR bpbMedia;              // media descriptor
    00257         CHAR bpbFATsecs[2];         // number of sectors per FAT
    00258         CHAR bpbSecPerTrack[2];     // sectors per track
    00259         CHAR bpbHeads[2];           // number of heads
    00260         CHAR bpbHiddenSecs[4];      // number of hidden sectors
    00261         CHAR bpbHugeSectors[4];     // # of sectors if bpbSectors == 0
    00262 };
    00263
    00264 // BPB for DOS 7.10 (FAT32).
    00265 // This one has a few extensions to bpb50.
    00266 struct byte_bpb710 {
    00267         BYTE bpbBytesPerSec[2];     // bytes per sector
    00268         BYTE bpbSecPerClust;        // sectors per cluster
    00269         BYTE bpbResSectors[2];      // number of reserved sectors
    00270         BYTE bpbFATs;               // number of FATs
    00271         BYTE bpbRootDirEnts[2];     // number of root directory entries
    00272         BYTE bpbSectors[2];         // total number of sectors
    00273         BYTE bpbMedia;              // media descriptor
    00274         BYTE bpbFATsecs[2];         // number of sectors per FAT
    00275         BYTE bpbSecPerTrack[2];     // sectors per track
    00276         BYTE bpbHeads[2];           // number of heads
    00277         BYTE bpbHiddenSecs[4];      // # of hidden sectors
    00278         BYTE bpbHugeSectors[4];     // # of sectors if bpbSectors == 0
    00279         BYTE bpbBigFATsecs[4];      // like bpbFATsecs for FAT32
    00280         BYTE bpbExtFlags[2];        // extended flags:
    00281         BYTE bpbFSVers[2];          // filesystem version
    00282         BYTE bpbRootClust[4];       // start cluster for root directory
    00283         BYTE bpbFSInfo[2];          // filesystem info structure sector
    00284         BYTE bpbBackup[2];          // backup boot sector
    00285         // There is a 12 byte filler here, but we ignore it
    00286 };
    00287
    00288 // FAT32 FSInfo block.
    00289 struct fsinfo {
    00290         BYTE fsisig1[4];
    00291         BYTE fsifill1[480];
    00292         BYTE fsisig2[4];
    00293         BYTE fsinfree[4];
    00294         BYTE fsinxtfree[4];
    00295         BYTE fsifill2[12];
    00296         BYTE fsisig3[4];
    00297         BYTE fsifill3[508];
    00298         BYTE fsisig4[4];
    00299 };
    00300
    00301
    00302 /***************************************************************/
    00303 /***************************************************************/
    00304
    00305
    00306 // Structure of a dos directory entry.
    00307 struct direntry {
    00308         BYTE        deName[8];      // filename, blank filled
    00309 #define SLOT_EMPTY      0x00            // slot has never been used
    00310 #define SLOT_E5         0x05            // the real value is 0xE5
    00311 #define SLOT_DELETED    0xE5            // file in this slot deleted
    00312         BYTE        deExtension[3]; // extension, blank filled
    00313         BYTE        deAttributes;   // file attributes
    00314 #define ATTR_NORMAL     0x00            // normal file
    00315 #define ATTR_READONLY   0x01            // file is readonly
    00316 #define ATTR_HIDDEN     0x02            // file is hidden
    00317 #define ATTR_SYSTEM     0x04            // file is a system file
    00318 #define ATTR_VOLUME     0x08            // entry is a volume label
    00319 #define ATTR_LONG_FILENAME  0x0F        // this is a long filename entry
    00320 #define ATTR_DIRECTORY  0x10            // entry is a directory name
    00321 #define ATTR_ARCHIVE    0x20            // file is new or modified
    00322         BYTE        deLowerCase;    // NT VFAT lower case flags  (set to zero)
    00323 #define LCASE_BASE      0x08            // filename base in lower case
    00324 #define LCASE_EXT       0x10            // filename extension in lower case
    00325         BYTE        deCHundredth;   // hundredth of seconds in CTime
    00326         BYTE        deCTime[2];     // create time
    00327         BYTE        deCDate[2];     // create date
    00328         BYTE        deADate[2];     // access date
    00329         WORD        deHighClust;    // high bytes of cluster number
    00330         BYTE        deMTime[2];     // last update time
    00331         BYTE        deMDate[2];     // last update date
    00332         WORD        deStartCluster; // starting cluster of file
    00333         DWORD       deFileSize;     // size of file in bytes
    00334 };
    00335
    00336 // number of directory entries in one sector
    00337 #define DIRENTRIES_PER_SECTOR   0x10
    00338
    00339 // Structure of a Win95 long name directory entry
    00340 struct winentry {
    00341         BYTE        weCnt;          //
    00342 #define WIN_LAST        0x40
    00343 #define WIN_CNT         0x3f
    00344         BYTE        wePart1[10];
    00345         BYTE        weAttributes;
    00346 #define ATTR_WIN95      0x0f
    00347         BYTE        weReserved1;
    00348         BYTE        weChksum;
    00349         BYTE        wePart2[12];
    00350         WORD        weReserved2;
    00351         BYTE        wePart3[4];
    00352 };
    00353
    00354 #define WIN_ENTRY_CHARS 13      // Number of chars per winentry
    00355
    00356 // Maximum filename length in Win95
    00357 // Note: Must be < sizeof(dirent.d_name)
    00358 #define WIN_MAXLEN      255
    00359
    00360 // This is the format of the contents of the deTime field in the direntry
    00361 // structure.
    00362 // We don't use bitfields because we don't know how compilers for
    00363 // arbitrary machines will lay them out.
    00364 #define DT_2SECONDS_MASK        0x1F    // seconds divided by 2
    00365 #define DT_2SECONDS_SHIFT       0
    00366 #define DT_MINUTES_MASK         0x7E0   // minutes
    00367 #define DT_MINUTES_SHIFT        5
    00368 #define DT_HOURS_MASK           0xF800  // hours
    00369 #define DT_HOURS_SHIFT          11
    00370
    00371 // This is the format of the contents of the deDate field in the direntry
    00372 // structure.
    00373 #define DD_DAY_MASK             0x1F    // day of month
    00374 #define DD_DAY_SHIFT            0
    00375 #define DD_MONTH_MASK           0x1E0   // month
    00376 #define DD_MONTH_SHIFT          5
    00377 #define DD_YEAR_MASK            0xFE00  // year - 1980
    00378 #define DD_YEAR_SHIFT           9
    00379
    00380 // Stuctures
    00381 struct FileInfoStruct
    00382 {
    00383     unsigned long StartCluster;         //< file starting cluster for last file accessed
    00384     unsigned long Size;                 //< file size for last file accessed
    00385     unsigned char Attr;                 //< file attr for last file accessed
    00386     unsigned short CreateTime;          //< file creation time for last file accessed
    00387     unsigned short CreateDate;          //< file creation date for last file accessed
    00388 };
    00389
    00390 // Prototypes
    00391 unsigned char fatInit( unsigned char device);
    00392 unsigned int fatClusterSize(void);
    00393 unsigned char fatGetDirEntry(unsigned short entry);
    00394 unsigned char fatChangeDirectory(unsigned short entry);
    00395 void fatPrintDirEntry(void);
    00396 void fatDumpDirSlot(unsigned short entry);
    00397 struct FileInfoStruct* fatGetFileInfo(void);
    00398 unsigned long fatGetFilesize(void);
    00399 char* fatGetFilename(void);
    00400 char* fatGetDirname(void);
    00401 void fatLoadCluster(unsigned long cluster, unsigned char *buffer);
    00402 unsigned long fatNextCluster(unsigned long cluster);
    00403
    00404 #endif