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 // This code is distributed under the GNU Public License
    00018 //      which can be found at http://www.gnu.org/licenses/gpl.txt
    00019 //
    00020 //*****************************************************************************
    00021
    00022 #ifndef FAT_H
    00023 #define FAT_H
    00024
    00025 #include "global.h"
    00026 #include "device.h"
    00027
    00028
    00029 // Some useful cluster numbers
    00030 #define MSDOSFSROOT     0               // cluster 0 means the root dir
    00031 #define CLUST_FREE      0               // cluster 0 also means a free cluster
    00032 #define MSDOSFSFREE     CLUST_FREE
    00033 #define CLUST_FIRST     2               // first legal cluster number
    00034 #define CLUST_RSRVD     0xfffffff6      // reserved cluster range
    00035 #define CLUST_BAD       0xfffffff7      // a cluster with a defect
    00036 #define CLUST_EOFS      0xfffffff8      // start of eof cluster range
    00037 #define CLUST_EOFE      0xffffffff      // end of eof cluster range
    00038
    00039 #define FAT12_MASK      0x00000fff      // mask for FAT12 bit cluster numbers
    00040 #define FAT16_MASK      0x0000ffff      // mask for FAT16 bit cluster numbers
    00041 #define FAT32_MASK      0x0fffffff      // mask for FAT32 cluster numbers
    00042
    00043 // Format of a boot sector.  This is the first sector on a DOS floppy disk
    00044 // or the first sector of a partition on a hard disk.  But, it is not the
    00045 // first sector of a partitioned hard disk.
    00046 struct bootsector33 {
    00047     BYTE    bsJump[3];                  // jump inst E9xxxx or EBxx90
    00048     CHAR    bsOemName[8];               // OEM name and version
    00049     CHAR    bsBPB[19];                  // BIOS parameter block
    00050     CHAR    bsDriveNumber;              // drive number (0x80)
    00051     CHAR    bsBootCode[479];            // pad so struct is 512b
    00052     BYTE    bsBootSectSig0;             // boot sector signature byte 0x55
    00053     BYTE    bsBootSectSig1;             // boot sector signature byte 0xAA
    00054 #define BOOTSIG0        0x55
    00055 #define BOOTSIG1        0xaa
    00056 } GNUC_PACKED;
    00057
    00058 struct extboot {
    00059     CHAR    exDriveNumber;              // drive number (0x80)
    00060     CHAR    exReserved1;                // reserved
    00061     CHAR    exBootSignature;            // ext. boot signature (0x29)
    00062 #define EXBOOTSIG       0x29
    00063     CHAR    exVolumeID[4];              // volume ID number
    00064     CHAR    exVolumeLabel[11];          // volume label
    00065     CHAR    exFileSysType[8];           // fs type (FAT12 or FAT16)
    00066 } GNUC_PACKED;
    00067
    00068 struct bootsector50 {
    00069     BYTE    bsJump[3];                  // jump inst E9xxxx or EBxx90
    00070     CHAR    bsOemName[8];               // OEM name and version
    00071     CHAR    bsBPB[25];                  // BIOS parameter block
    00072     CHAR    bsExt[26];                  // Bootsector Extension
    00073     CHAR    bsBootCode[448];            // pad so structure is 512b
    00074     BYTE    bsBootSectSig0;             // boot sector signature byte 0x55
    00075     BYTE    bsBootSectSig1;             // boot sector signature byte 0xAA
    00076 #define BOOTSIG0        0x55
    00077 #define BOOTSIG1        0xaa
    00078 } GNUC_PACKED;
    00079
    00080 struct bootsector710 {
    00081     BYTE    bsJump[3];                  // jump inst E9xxxx or EBxx90
    00082     CHAR    bsOEMName[8];               // OEM name and version
    00083     CHAR    bsBPB[53];                  // BIOS parameter block
    00084     CHAR    bsExt[26];                  // Bootsector Extension
    00085     CHAR    bsBootCode[418];            // pad so structure is 512b
    00086     BYTE    bsBootSectSig2;             // 2 & 3 are only defined for FAT32?
    00087     BYTE    bsBootSectSig3;
    00088     BYTE    bsBootSectSig0;             // boot sector signature byte 0x55
    00089     BYTE    bsBootSectSig1;             // boot sector signature byte 0xAA
    00090 #define BOOTSIG0        0x55
    00091 #define BOOTSIG1        0xaa
    00092 #define BOOTSIG2        0
    00093 #define BOOTSIG3        0
    00094 } GNUC_PACKED;
    00095
    00096
    00097 /***************************************************************/
    00098 /***************************************************************/
    00099
    00100 // BIOS Parameter Block (BPB) for DOS 3.3
    00101 struct bpb33 {
    00102         WORD    bpbBytesPerSec; // bytes per sector
    00103         BYTE    bpbSecPerClust; // sectors per cluster
    00104         WORD    bpbResSectors;  // number of reserved sectors
    00105         BYTE    bpbFATs;        // number of FATs
    00106         WORD    bpbRootDirEnts; // number of root directory entries
    00107         WORD    bpbSectors;     // total number of sectors
    00108         BYTE    bpbMedia;       // media descriptor
    00109         WORD    bpbFATsecs;     // number of sectors per FAT
    00110         WORD    bpbSecPerTrack; // sectors per track
    00111         WORD    bpbHeads;       // number of heads
    00112         WORD    bpbHiddenSecs;  // number of hidden sectors
    00113 } GNUC_PACKED;
    00114
    00115 // BPB for DOS 5.0
    00116 // The difference is bpbHiddenSecs is a short for DOS 3.3,
    00117 // and bpbHugeSectors is not present in the DOS 3.3 bpb.
    00118 struct bpb50 {
    00119         WORD    bpbBytesPerSec; // bytes per sector
    00120         BYTE    bpbSecPerClust; // sectors per cluster
    00121         WORD    bpbResSectors;  // number of reserved sectors
    00122         BYTE    bpbFATs;        // number of FATs
    00123         WORD    bpbRootDirEnts; // number of root directory entries
    00124         WORD    bpbSectors;     // total number of sectors
    00125         BYTE    bpbMedia;       // media descriptor
    00126         WORD    bpbFATsecs;     // number of sectors per FAT
    00127         WORD    bpbSecPerTrack; // sectors per track
    00128         WORD    bpbHeads;       // number of heads
    00129         DWORD   bpbHiddenSecs;  // # of hidden sectors
    00130 // 3.3 compat ends here
    00131         DWORD   bpbHugeSectors; // # of sectors if bpbSectors == 0
    00132 } GNUC_PACKED;
    00133
    00134 // BPB for DOS 7.10 (FAT32)
    00135 // This one has a few extensions to bpb50.
    00136 struct bpb710 {
    00137         WORD    bpbBytesPerSec; // bytes per sector
    00138         BYTE    bpbSecPerClust; // sectors per cluster
    00139         WORD    bpbResSectors;  // number of reserved sectors
    00140         BYTE    bpbFATs;        // number of FATs
    00141         WORD    bpbRootDirEnts; // number of root directory entries
    00142         WORD    bpbSectors;     // total number of sectors
    00143         BYTE    bpbMedia;       // media descriptor
    00144         WORD    bpbFATsecs;     // number of sectors per FAT
    00145         WORD    bpbSecPerTrack; // sectors per track
    00146         WORD    bpbHeads;       // number of heads
    00147         DWORD   bpbHiddenSecs;  // # of hidden sectors
    00148 // 3.3 compat ends here
    00149         DWORD   bpbHugeSectors; // # of sectors if bpbSectors == 0
    00150 // 5.0 compat ends here
    00151         DWORD     bpbBigFATsecs;// like bpbFATsecs for FAT32
    00152         WORD      bpbExtFlags;  // extended flags:
    00153 #define FATNUM    0xf           // mask for numbering active FAT
    00154 #define FATMIRROR 0x80          // FAT is mirrored (like it always was)
    00155         WORD      bpbFSVers;    // filesystem version
    00156 #define FSVERS    0             // currently only 0 is understood
    00157         DWORD     bpbRootClust; // start cluster for root directory
    00158         WORD      bpbFSInfo;    // filesystem info structure sector
    00159         WORD      bpbBackup;    // backup boot sector
    00160         // There is a 12 byte filler here, but we ignore it
    00161 } GNUC_PACKED;
    00162
    00163 // ***************************************************************
    00164 // * byte versions of the above structs                          *
    00165 // ***************************************************************
    00166
    00167 // BIOS Parameter Block (BPB) for DOS 3.3
    00168 struct bpb33_byte {
    00169         CHAR bpbBytesPerSec[2];     // bytes per sector
    00170         CHAR bpbSecPerClust;        // sectors per cluster
    00171         CHAR bpbResSectors[2];      // number of reserved sectors
    00172         CHAR bpbFATs;               // number of FATs
    00173         CHAR bpbRootDirEnts[2];     // number of root directory entries
    00174         CHAR bpbSectors[2];         // total number of sectors
    00175         CHAR bpbMedia;              // media descriptor
    00176         CHAR bpbFATsecs[2];         // number of sectors per FAT
    00177         CHAR bpbSecPerTrack[2];     // sectors per track
    00178         CHAR bpbHeads[2];           // number of heads
    00179         CHAR bpbHiddenSecs[2];      // number of hidden sectors
    00180 } GNUC_PACKED;
    00181
    00182 // BPB for DOS 5.0
    00183 // The difference is bpbHiddenSecs is a short for DOS 3.3,
    00184 // and bpbHugeSectors is not in the 3.3 bpb.
    00185 struct bpb50_byte {
    00186         CHAR bpbBytesPerSec[2];     // bytes per sector
    00187         CHAR bpbSecPerClust;        // sectors per cluster
    00188         CHAR bpbResSectors[2];      // number of reserved sectors
    00189         CHAR bpbFATs;               // number of FATs
    00190         CHAR bpbRootDirEnts[2];     // number of root directory entries
    00191         CHAR bpbSectors[2];         // total number of sectors
    00192         CHAR bpbMedia;              // media descriptor
    00193         CHAR bpbFATsecs[2];         // number of sectors per FAT
    00194         CHAR bpbSecPerTrack[2];     // sectors per track
    00195         CHAR bpbHeads[2];           // number of heads
    00196         CHAR bpbHiddenSecs[4];      // number of hidden sectors
    00197         CHAR bpbHugeSectors[4];     // # of sectors if bpbSectors == 0
    00198 } GNUC_PACKED;
    00199
    00200 // BPB for DOS 7.10 (FAT32).
    00201 // This one has a few extensions to bpb50.
    00202 struct bpb710_byte {
    00203         BYTE bpbBytesPerSec[2];     // bytes per sector
    00204         BYTE bpbSecPerClust;        // sectors per cluster
    00205         BYTE bpbResSectors[2];      // number of reserved sectors
    00206         BYTE bpbFATs;               // number of FATs
    00207         BYTE bpbRootDirEnts[2];     // number of root directory entries
    00208         BYTE bpbSectors[2];         // total number of sectors
    00209         BYTE bpbMedia;              // media descriptor
    00210         BYTE bpbFATsecs[2];         // number of sectors per FAT
    00211         BYTE bpbSecPerTrack[2];     // sectors per track
    00212         BYTE bpbHeads[2];           // number of heads
    00213         BYTE bpbHiddenSecs[4];      // # of hidden sectors
    00214         BYTE bpbHugeSectors[4];     // # of sectors if bpbSectors == 0
    00215         BYTE bpbBigFATsecs[4];      // like bpbFATsecs for FAT32
    00216         BYTE bpbExtFlags[2];        // extended flags:
    00217         BYTE bpbFSVers[2];          // filesystem version
    00218         BYTE bpbRootClust[4];       // start cluster for root directory
    00219         BYTE bpbFSInfo[2];          // filesystem info structure sector
    00220         BYTE bpbBackup[2];          // backup boot sector
    00221         // There is a 12 byte filler here, but we ignore it
    00222 } GNUC_PACKED;
    00223
    00224 // FAT32 FSInfo block.
    00225 struct fsinfo {
    00226         BYTE fsisig1[4];
    00227         BYTE fsifill1[480];
    00228         BYTE fsisig2[4];
    00229         BYTE fsinfree[4];
    00230         BYTE fsinxtfree[4];
    00231         BYTE fsifill2[12];
    00232         BYTE fsisig3[4];
    00233         BYTE fsifill3[508];
    00234         BYTE fsisig4[4];
    00235 } GNUC_PACKED;
    00236
    00237
    00238 /***************************************************************/
    00239 /***************************************************************/
    00240
    00241 // Structure of a dos directory entry.
    00242 struct direntry {
    00243         BYTE        deName[8];      // filename, blank filled
    00244 #define SLOT_EMPTY      0x00            // slot has never been used
    00245 #define SLOT_E5         0x05            // the real value is 0xE5
    00246 #define SLOT_DELETED    0xE5            // file in this slot deleted
    00247         BYTE        deExtension[3]; // extension, blank filled
    00248         BYTE        deAttributes;   // file attributes
    00249 #define ATTR_NORMAL     0x00            // normal file
    00250 #define ATTR_READONLY   0x01            // file is readonly
    00251 #define ATTR_HIDDEN     0x02            // file is hidden
    00252 #define ATTR_SYSTEM     0x04            // file is a system file
    00253 #define ATTR_VOLUME     0x08            // entry is a volume label
    00254 #define ATTR_LONG_FILENAME  0x0F        // this is a long filename entry
    00255 #define ATTR_DIRECTORY  0x10            // entry is a directory name
    00256 #define ATTR_ARCHIVE    0x20            // file is new or modified
    00257         BYTE        deLowerCase;    // NT VFAT lower case flags  (set to zero)
    00258 #define LCASE_BASE      0x08            // filename base in lower case
    00259 #define LCASE_EXT       0x10            // filename extension in lower case
    00260         BYTE        deCHundredth;   // hundredth of seconds in CTime
    00261         BYTE        deCTime[2];     // create time
    00262         BYTE        deCDate[2];     // create date
    00263         BYTE        deADate[2];     // access date
    00264         WORD        deHighClust;    // high bytes of cluster number
    00265         BYTE        deMTime[2];     // last update time
    00266         BYTE        deMDate[2];     // last update date
    00267         WORD        deStartCluster; // starting cluster of file
    00268         DWORD       deFileSize;     // size of file in bytes
    00269 } GNUC_PACKED;
    00270
    00271 // number of directory entries in one sector
    00272 #define DIRENTRIES_PER_SECTOR   0x10
    00273
    00274 // Structure of a Win95 long name directory entry
    00275 struct winentry {
    00276         BYTE        weCnt;          //
    00277 #define WIN_LAST        0x40
    00278 #define WIN_CNT         0x3f
    00279         BYTE        wePart1[10];
    00280         BYTE        weAttributes;
    00281 #define ATTR_WIN95      0x0f
    00282         BYTE        weReserved1;
    00283         BYTE        weChksum;
    00284         BYTE        wePart2[12];
    00285         WORD        weReserved2;
    00286         BYTE        wePart3[4];
    00287 } GNUC_PACKED;
    00288
    00289 #define WIN_ENTRY_CHARS 13      // Number of chars per winentry
    00290
    00291 // Maximum filename length in Win95
    00292 // Note: Must be < sizeof(dirent.d_name)
    00293 #define WIN_MAXLEN      255
    00294
    00295 // This is the format of the contents of the deTime field in the direntry
    00296 // structure.
    00297 // We don't use bitfields because we don't know how compilers for
    00298 // arbitrary machines will lay them out.
    00299 #define DT_2SECONDS_MASK        0x1F    // seconds divided by 2
    00300 #define DT_2SECONDS_SHIFT       0
    00301 #define DT_MINUTES_MASK         0x7E0   // minutes
    00302 #define DT_MINUTES_SHIFT        5
    00303 #define DT_HOURS_MASK           0xF800  // hours
    00304 #define DT_HOURS_SHIFT          11
    00305
    00306 // This is the format of the contents of the deDate field in the direntry
    00307 // structure.
    00308 #define DD_DAY_MASK             0x1F    // day of month
    00309 #define DD_DAY_SHIFT            0
    00310 #define DD_MONTH_MASK           0x1E0   // month
    00311 #define DD_MONTH_SHIFT          5
    00312 #define DD_YEAR_MASK            0xFE00  // year - 1980
    00313 #define DD_YEAR_SHIFT           9
    00314
    00315 // Stuctures
    00316 struct FileInfo_s
    00317 {
    00318     unsigned long StartCluster;         //< file starting cluster for last file accessed
    00319     unsigned long Size;                 //< file size for last file accessed
    00320     unsigned char Attr;                 //< file attr for last file accessed
    00321     unsigned short CreateTime;          //< file creation time for last file accessed
    00322     unsigned short CreateDate;          //< file creation date for last file accessed
    00323 } GNUC_PACKED;
    00324
    00325 typedef struct FileInfo_s FileInfo_t;
    00326
    00327 // Prototypes
    00328 unsigned char fatInit(DevDisk_t* disk);
    00329 unsigned int fatClusterSize(void);
    00330 unsigned char fatGetDirEntry(unsigned short entry);
    00331 unsigned char fatChangeDirectory(unsigned short entry);
    00332 void fatPrintDirEntry(void);
    00333 void fatDumpDirSlot(unsigned short entry);
    00334 FileInfo_t* fatGetFileInfo(void);
    00335 unsigned long fatGetFilesize(void);
    00336 char* fatGetFilename(void);
    00337 char* fatGetDirname(void);
    00338 void fatLoadCluster(unsigned long cluster, unsigned char *buffer);
    00339 unsigned long fatClusterToSector(unsigned long cluster);
    00340
    00341 unsigned long fatNextCluster(unsigned long cluster);
    00342 unsigned long fatNextFreeCluster(void);
    00343 unsigned long fatClusterValue(unsigned long cluster);
    00344 int fatWriteClusterValue(unsigned long cluster, unsigned value);
    00345 unsigned char* fatGetFatSector(unsigned long fatsector);
    00346
    00347 int fatCreateFile(unsigned char* filename, FileInfo_t* fileInfo);
    00348 int fatFormat(unsigned long volsize);
    00349
    00350 #endif