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

Generated on Sun Oct 29 03:41:06 2006 for Procyon AVRlib by  doxygen 1.4.2