| Line No. | Rev | Author | Line |
|---|---|---|---|
| 1 | 6 | kaklik | /*! \file fat.h \brief FAT16/32 file system driver. */ |
| 2 | //***************************************************************************** |
||
| 3 | // |
||
| 4 | // File Name : 'fat.h' |
||
| 5 | // Title : FAT16/32 file system driver |
||
| 6 | // Author : Pascal Stang |
||
| 7 | // Date : 11/07/2000 |
||
| 8 | // Revised : 12/12/2000 |
||
| 9 | // Version : 0.3 |
||
| 10 | // Target MCU : ATmega103 (should work for Atmel AVR Series) |
||
| 11 | // Editor Tabs : 4 |
||
| 12 | // |
||
| 13 | // NOTE: This code is currently below version 1.0, and therefore is considered |
||
| 14 | // to be lacking in some functionality or documentation, or may not be fully |
||
| 15 | // tested. Nonetheless, you can expect most functions to work. |
||
| 16 | // |
||
| 17 | /// \ingroup general |
||
| 18 | /// \defgroup fat FAT16/32 File System Interface (fat.c) |
||
| 19 | /// \code #include "fat.h" \endcode |
||
| 20 | /// \par Overview |
||
| 21 | /// This FAT16/32 interface allows you to detect and mount FAT16/32 |
||
| 22 | /// partitions, browse directories and files, and read file data. |
||
| 23 | /// The interface is designed to operate with the avrlib IDE/ATA driver. |
||
| 24 | /// Reading FAT efficiently requires at least 512+ bytes of RAM so this |
||
| 25 | /// interface may not be suitable for processors with less than 1K of RAM. |
||
| 26 | /// This interface will properly follow a file's cluster chain so files |
||
| 27 | /// need not be defragmented. |
||
| 28 | /// |
||
| 29 | /// \note This code is based in part on work done by Jesper Hansen for his |
||
| 30 | /// excellent YAMPP MP3 player project. |
||
| 31 | // |
||
| 32 | // This code is distributed under the GNU Public License |
||
| 33 | // which can be found at http://www.gnu.org/licenses/gpl.txt |
||
| 34 | // |
||
| 35 | //***************************************************************************** |
||
| 36 | |||
| 37 | #ifndef FAT_H |
||
| 38 | #define FAT_H |
||
| 39 | |||
| 40 | #include "global.h" |
||
| 41 | |||
| 42 | |||
| 43 | // Some useful cluster numbers |
||
| 44 | #define MSDOSFSROOT 0 // cluster 0 means the root dir |
||
| 45 | #define CLUST_FREE 0 // cluster 0 also means a free cluster |
||
| 46 | #define MSDOSFSFREE CLUST_FREE |
||
| 47 | #define CLUST_FIRST 2 // first legal cluster number |
||
| 48 | #define CLUST_RSRVD 0xfffffff6 // reserved cluster range |
||
| 49 | #define CLUST_BAD 0xfffffff7 // a cluster with a defect |
||
| 50 | #define CLUST_EOFS 0xfffffff8 // start of eof cluster range |
||
| 51 | #define CLUST_EOFE 0xffffffff // end of eof cluster range |
||
| 52 | |||
| 53 | #define FAT12_MASK 0x00000fff // mask for 12 bit cluster numbers |
||
| 54 | #define FAT16_MASK 0x0000ffff // mask for 16 bit cluster numbers |
||
| 55 | #define FAT32_MASK 0x0fffffff // mask for FAT32 cluster numbers |
||
| 56 | |||
| 57 | |||
| 58 | // Partition Type used in the partition record |
||
| 59 | #define PART_TYPE_UNKNOWN 0x00 |
||
| 60 | #define PART_TYPE_FAT12 0x01 |
||
| 61 | #define PART_TYPE_XENIX 0x02 |
||
| 62 | #define PART_TYPE_DOSFAT16 0x04 |
||
| 63 | #define PART_TYPE_EXTDOS 0x05 |
||
| 64 | #define PART_TYPE_FAT16 0x06 |
||
| 65 | #define PART_TYPE_NTFS 0x07 |
||
| 66 | #define PART_TYPE_FAT32 0x0B |
||
| 67 | #define PART_TYPE_FAT32LBA 0x0C |
||
| 68 | #define PART_TYPE_FAT16LBA 0x0E |
||
| 69 | #define PART_TYPE_EXTDOSLBA 0x0F |
||
| 70 | #define PART_TYPE_ONTRACK 0x33 |
||
| 71 | #define PART_TYPE_NOVELL 0x40 |
||
| 72 | #define PART_TYPE_PCIX 0x4B |
||
| 73 | #define PART_TYPE_PHOENIXSAVE 0xA0 |
||
| 74 | #define PART_TYPE_CPM 0xDB |
||
| 75 | #define PART_TYPE_DBFS 0xE0 |
||
| 76 | #define PART_TYPE_BBT 0xFF |
||
| 77 | |||
| 78 | struct partrecord // length 16 bytes |
||
| 79 | { |
||
| 80 | BYTE prIsActive; // 0x80 indicates active partition |
||
| 81 | BYTE prStartHead; // starting head for partition |
||
| 82 | WORD prStartCylSect; // starting cylinder and sector |
||
| 83 | BYTE prPartType; // partition type (see above) |
||
| 84 | BYTE prEndHead; // ending head for this partition |
||
| 85 | WORD prEndCylSect; // ending cylinder and sector |
||
| 86 | DWORD prStartLBA; // first LBA sector for this partition |
||
| 87 | DWORD prSize; // size of this partition (bytes or sectors ?) |
||
| 88 | }; |
||
| 89 | |||
| 90 | |||
| 91 | struct partsector |
||
| 92 | { |
||
| 93 | CHAR psPartCode[512-64-2]; // pad so struct is 512b |
||
| 94 | BYTE psPart[64]; // four partition records (64 bytes) |
||
| 95 | BYTE psBootSectSig0; // two signature bytes (2 bytes) |
||
| 96 | BYTE psBootSectSig1; |
||
| 97 | #define BOOTSIG0 0x55 |
||
| 98 | #define BOOTSIG1 0xaa |
||
| 99 | }; |
||
| 100 | |||
| 101 | |||
| 102 | |||
| 103 | // Format of a boot sector. This is the first sector on a DOS floppy disk |
||
| 104 | // or the first sector of a partition on a hard disk. But, it is not the |
||
| 105 | // first sector of a partitioned hard disk. |
||
| 106 | struct bootsector33 { |
||
| 107 | BYTE bsJump[3]; // jump inst E9xxxx or EBxx90 |
||
| 108 | CHAR bsOemName[8]; // OEM name and version |
||
| 109 | CHAR bsBPB[19]; // BIOS parameter block |
||
| 110 | CHAR bsDriveNumber; // drive number (0x80) |
||
| 111 | CHAR bsBootCode[479]; // pad so struct is 512b |
||
| 112 | BYTE bsBootSectSig0; // boot sector signature byte 0x55 |
||
| 113 | BYTE bsBootSectSig1; // boot sector signature byte 0xAA |
||
| 114 | #define BOOTSIG0 0x55 |
||
| 115 | #define BOOTSIG1 0xaa |
||
| 116 | }; |
||
| 117 | |||
| 118 | struct extboot { |
||
| 119 | CHAR exDriveNumber; // drive number (0x80) |
||
| 120 | CHAR exReserved1; // reserved |
||
| 121 | CHAR exBootSignature; // ext. boot signature (0x29) |
||
| 122 | #define EXBOOTSIG 0x29 |
||
| 123 | CHAR exVolumeID[4]; // volume ID number |
||
| 124 | CHAR exVolumeLabel[11]; // volume label |
||
| 125 | CHAR exFileSysType[8]; // fs type (FAT12 or FAT16) |
||
| 126 | }; |
||
| 127 | |||
| 128 | struct bootsector50 { |
||
| 129 | BYTE bsJump[3]; // jump inst E9xxxx or EBxx90 |
||
| 130 | CHAR bsOemName[8]; // OEM name and version |
||
| 131 | CHAR bsBPB[25]; // BIOS parameter block |
||
| 132 | CHAR bsExt[26]; // Bootsector Extension |
||
| 133 | CHAR bsBootCode[448]; // pad so structure is 512b |
||
| 134 | BYTE bsBootSectSig0; // boot sector signature byte 0x55 |
||
| 135 | BYTE bsBootSectSig1; // boot sector signature byte 0xAA |
||
| 136 | #define BOOTSIG0 0x55 |
||
| 137 | #define BOOTSIG1 0xaa |
||
| 138 | }; |
||
| 139 | |||
| 140 | struct bootsector710 { |
||
| 141 | BYTE bsJump[3]; // jump inst E9xxxx or EBxx90 |
||
| 142 | CHAR bsOEMName[8]; // OEM name and version |
||
| 143 | CHAR bsBPB[53]; // BIOS parameter block |
||
| 144 | CHAR bsExt[26]; // Bootsector Extension |
||
| 145 | CHAR bsBootCode[418]; // pad so structure is 512b |
||
| 146 | BYTE bsBootSectSig2; // 2 & 3 are only defined for FAT32? |
||
| 147 | BYTE bsBootSectSig3; |
||
| 148 | BYTE bsBootSectSig0; // boot sector signature byte 0x55 |
||
| 149 | BYTE bsBootSectSig1; // boot sector signature byte 0xAA |
||
| 150 | #define BOOTSIG0 0x55 |
||
| 151 | #define BOOTSIG1 0xaa |
||
| 152 | #define BOOTSIG2 0 |
||
| 153 | #define BOOTSIG3 0 |
||
| 154 | }; |
||
| 155 | |||
| 156 | |||
| 157 | /***************************************************************/ |
||
| 158 | /***************************************************************/ |
||
| 159 | |||
| 160 | // BIOS Parameter Block (BPB) for DOS 3.3 |
||
| 161 | struct bpb33 { |
||
| 162 | WORD bpbBytesPerSec; // bytes per sector |
||
| 163 | BYTE bpbSecPerClust; // sectors per cluster |
||
| 164 | WORD bpbResSectors; // number of reserved sectors |
||
| 165 | BYTE bpbFATs; // number of FATs |
||
| 166 | WORD bpbRootDirEnts; // number of root directory entries |
||
| 167 | WORD bpbSectors; // total number of sectors |
||
| 168 | BYTE bpbMedia; // media descriptor |
||
| 169 | WORD bpbFATsecs; // number of sectors per FAT |
||
| 170 | WORD bpbSecPerTrack; // sectors per track |
||
| 171 | WORD bpbHeads; // number of heads |
||
| 172 | WORD bpbHiddenSecs; // number of hidden sectors |
||
| 173 | }; |
||
| 174 | |||
| 175 | // BPB for DOS 5.0 |
||
| 176 | // The difference is bpbHiddenSecs is a short for DOS 3.3, |
||
| 177 | // and bpbHugeSectors is not present in the DOS 3.3 bpb. |
||
| 178 | struct bpb50 { |
||
| 179 | WORD bpbBytesPerSec; // bytes per sector |
||
| 180 | BYTE bpbSecPerClust; // sectors per cluster |
||
| 181 | WORD bpbResSectors; // number of reserved sectors |
||
| 182 | BYTE bpbFATs; // number of FATs |
||
| 183 | WORD bpbRootDirEnts; // number of root directory entries |
||
| 184 | WORD bpbSectors; // total number of sectors |
||
| 185 | BYTE bpbMedia; // media descriptor |
||
| 186 | WORD bpbFATsecs; // number of sectors per FAT |
||
| 187 | WORD bpbSecPerTrack; // sectors per track |
||
| 188 | WORD bpbHeads; // number of heads |
||
| 189 | DWORD bpbHiddenSecs; // # of hidden sectors |
||
| 190 | // 3.3 compat ends here |
||
| 191 | DWORD bpbHugeSectors; // # of sectors if bpbSectors == 0 |
||
| 192 | }; |
||
| 193 | |||
| 194 | // BPB for DOS 7.10 (FAT32) |
||
| 195 | // This one has a few extensions to bpb50. |
||
| 196 | struct bpb710 { |
||
| 197 | WORD bpbBytesPerSec; // bytes per sector |
||
| 198 | BYTE bpbSecPerClust; // sectors per cluster |
||
| 199 | WORD bpbResSectors; // number of reserved sectors |
||
| 200 | BYTE bpbFATs; // number of FATs |
||
| 201 | WORD bpbRootDirEnts; // number of root directory entries |
||
| 202 | WORD bpbSectors; // total number of sectors |
||
| 203 | BYTE bpbMedia; // media descriptor |
||
| 204 | WORD bpbFATsecs; // number of sectors per FAT |
||
| 205 | WORD bpbSecPerTrack; // sectors per track |
||
| 206 | WORD bpbHeads; // number of heads |
||
| 207 | DWORD bpbHiddenSecs; // # of hidden sectors |
||
| 208 | // 3.3 compat ends here |
||
| 209 | DWORD bpbHugeSectors; // # of sectors if bpbSectors == 0 |
||
| 210 | // 5.0 compat ends here |
||
| 211 | DWORD bpbBigFATsecs;// like bpbFATsecs for FAT32 |
||
| 212 | WORD bpbExtFlags; // extended flags: |
||
| 213 | #define FATNUM 0xf // mask for numbering active FAT |
||
| 214 | #define FATMIRROR 0x80 // FAT is mirrored (like it always was) |
||
| 215 | WORD bpbFSVers; // filesystem version |
||
| 216 | #define FSVERS 0 // currently only 0 is understood |
||
| 217 | DWORD bpbRootClust; // start cluster for root directory |
||
| 218 | WORD bpbFSInfo; // filesystem info structure sector |
||
| 219 | WORD bpbBackup; // backup boot sector |
||
| 220 | // There is a 12 byte filler here, but we ignore it |
||
| 221 | }; |
||
| 222 | |||
| 223 | |||
| 224 | |||
| 225 | |||
| 226 | // *************************************************************** |
||
| 227 | // * byte versions of the above structs * |
||
| 228 | // *************************************************************** |
||
| 229 | |||
| 230 | |||
| 231 | // BIOS Parameter Block (BPB) for DOS 3.3 |
||
| 232 | struct byte_bpb33 { |
||
| 233 | CHAR bpbBytesPerSec[2]; // bytes per sector |
||
| 234 | CHAR bpbSecPerClust; // sectors per cluster |
||
| 235 | CHAR bpbResSectors[2]; // number of reserved sectors |
||
| 236 | CHAR bpbFATs; // number of FATs |
||
| 237 | CHAR bpbRootDirEnts[2]; // number of root directory entries |
||
| 238 | CHAR bpbSectors[2]; // total number of sectors |
||
| 239 | CHAR bpbMedia; // media descriptor |
||
| 240 | CHAR bpbFATsecs[2]; // number of sectors per FAT |
||
| 241 | CHAR bpbSecPerTrack[2]; // sectors per track |
||
| 242 | CHAR bpbHeads[2]; // number of heads |
||
| 243 | CHAR bpbHiddenSecs[2]; // number of hidden sectors |
||
| 244 | }; |
||
| 245 | |||
| 246 | // BPB for DOS 5.0 |
||
| 247 | // The difference is bpbHiddenSecs is a short for DOS 3.3, |
||
| 248 | // and bpbHugeSectors is not in the 3.3 bpb. |
||
| 249 | struct byte_bpb50 { |
||
| 250 | CHAR bpbBytesPerSec[2]; // bytes per sector |
||
| 251 | CHAR bpbSecPerClust; // sectors per cluster |
||
| 252 | CHAR bpbResSectors[2]; // number of reserved sectors |
||
| 253 | CHAR bpbFATs; // number of FATs |
||
| 254 | CHAR bpbRootDirEnts[2]; // number of root directory entries |
||
| 255 | CHAR bpbSectors[2]; // total number of sectors |
||
| 256 | CHAR bpbMedia; // media descriptor |
||
| 257 | CHAR bpbFATsecs[2]; // number of sectors per FAT |
||
| 258 | CHAR bpbSecPerTrack[2]; // sectors per track |
||
| 259 | CHAR bpbHeads[2]; // number of heads |
||
| 260 | CHAR bpbHiddenSecs[4]; // number of hidden sectors |
||
| 261 | CHAR bpbHugeSectors[4]; // # of sectors if bpbSectors == 0 |
||
| 262 | }; |
||
| 263 | |||
| 264 | // BPB for DOS 7.10 (FAT32). |
||
| 265 | // This one has a few extensions to bpb50. |
||
| 266 | struct byte_bpb710 { |
||
| 267 | BYTE bpbBytesPerSec[2]; // bytes per sector |
||
| 268 | BYTE bpbSecPerClust; // sectors per cluster |
||
| 269 | BYTE bpbResSectors[2]; // number of reserved sectors |
||
| 270 | BYTE bpbFATs; // number of FATs |
||
| 271 | BYTE bpbRootDirEnts[2]; // number of root directory entries |
||
| 272 | BYTE bpbSectors[2]; // total number of sectors |
||
| 273 | BYTE bpbMedia; // media descriptor |
||
| 274 | BYTE bpbFATsecs[2]; // number of sectors per FAT |
||
| 275 | BYTE bpbSecPerTrack[2]; // sectors per track |
||
| 276 | BYTE bpbHeads[2]; // number of heads |
||
| 277 | BYTE bpbHiddenSecs[4]; // # of hidden sectors |
||
| 278 | BYTE bpbHugeSectors[4]; // # of sectors if bpbSectors == 0 |
||
| 279 | BYTE bpbBigFATsecs[4]; // like bpbFATsecs for FAT32 |
||
| 280 | BYTE bpbExtFlags[2]; // extended flags: |
||
| 281 | BYTE bpbFSVers[2]; // filesystem version |
||
| 282 | BYTE bpbRootClust[4]; // start cluster for root directory |
||
| 283 | BYTE bpbFSInfo[2]; // filesystem info structure sector |
||
| 284 | BYTE bpbBackup[2]; // backup boot sector |
||
| 285 | // There is a 12 byte filler here, but we ignore it |
||
| 286 | }; |
||
| 287 | |||
| 288 | // FAT32 FSInfo block. |
||
| 289 | struct fsinfo { |
||
| 290 | BYTE fsisig1[4]; |
||
| 291 | BYTE fsifill1[480]; |
||
| 292 | BYTE fsisig2[4]; |
||
| 293 | BYTE fsinfree[4]; |
||
| 294 | BYTE fsinxtfree[4]; |
||
| 295 | BYTE fsifill2[12]; |
||
| 296 | BYTE fsisig3[4]; |
||
| 297 | BYTE fsifill3[508]; |
||
| 298 | BYTE fsisig4[4]; |
||
| 299 | }; |
||
| 300 | |||
| 301 | |||
| 302 | /***************************************************************/ |
||
| 303 | /***************************************************************/ |
||
| 304 | |||
| 305 | |||
| 306 | // Structure of a dos directory entry. |
||
| 307 | struct direntry { |
||
| 308 | BYTE deName[8]; // filename, blank filled |
||
| 309 | #define SLOT_EMPTY 0x00 // slot has never been used |
||
| 310 | #define SLOT_E5 0x05 // the real value is 0xE5 |
||
| 311 | #define SLOT_DELETED 0xE5 // file in this slot deleted |
||
| 312 | BYTE deExtension[3]; // extension, blank filled |
||
| 313 | BYTE deAttributes; // file attributes |
||
| 314 | #define ATTR_NORMAL 0x00 // normal file |
||
| 315 | #define ATTR_READONLY 0x01 // file is readonly |
||
| 316 | #define ATTR_HIDDEN 0x02 // file is hidden |
||
| 317 | #define ATTR_SYSTEM 0x04 // file is a system file |
||
| 318 | #define ATTR_VOLUME 0x08 // entry is a volume label |
||
| 319 | #define ATTR_LONG_FILENAME 0x0F // this is a long filename entry |
||
| 320 | #define ATTR_DIRECTORY 0x10 // entry is a directory name |
||
| 321 | #define ATTR_ARCHIVE 0x20 // file is new or modified |
||
| 322 | BYTE deLowerCase; // NT VFAT lower case flags (set to zero) |
||
| 323 | #define LCASE_BASE 0x08 // filename base in lower case |
||
| 324 | #define LCASE_EXT 0x10 // filename extension in lower case |
||
| 325 | BYTE deCHundredth; // hundredth of seconds in CTime |
||
| 326 | BYTE deCTime[2]; // create time |
||
| 327 | BYTE deCDate[2]; // create date |
||
| 328 | BYTE deADate[2]; // access date |
||
| 329 | WORD deHighClust; // high bytes of cluster number |
||
| 330 | BYTE deMTime[2]; // last update time |
||
| 331 | BYTE deMDate[2]; // last update date |
||
| 332 | WORD deStartCluster; // starting cluster of file |
||
| 333 | DWORD deFileSize; // size of file in bytes |
||
| 334 | }; |
||
| 335 | |||
| 336 | // number of directory entries in one sector |
||
| 337 | #define DIRENTRIES_PER_SECTOR 0x10 |
||
| 338 | |||
| 339 | // Structure of a Win95 long name directory entry |
||
| 340 | struct winentry { |
||
| 341 | BYTE weCnt; // |
||
| 342 | #define WIN_LAST 0x40 |
||
| 343 | #define WIN_CNT 0x3f |
||
| 344 | BYTE wePart1[10]; |
||
| 345 | BYTE weAttributes; |
||
| 346 | #define ATTR_WIN95 0x0f |
||
| 347 | BYTE weReserved1; |
||
| 348 | BYTE weChksum; |
||
| 349 | BYTE wePart2[12]; |
||
| 350 | WORD weReserved2; |
||
| 351 | BYTE wePart3[4]; |
||
| 352 | }; |
||
| 353 | |||
| 354 | #define WIN_ENTRY_CHARS 13 // Number of chars per winentry |
||
| 355 | |||
| 356 | // Maximum filename length in Win95 |
||
| 357 | // Note: Must be < sizeof(dirent.d_name) |
||
| 358 | #define WIN_MAXLEN 255 |
||
| 359 | |||
| 360 | // This is the format of the contents of the deTime field in the direntry |
||
| 361 | // structure. |
||
| 362 | // We don't use bitfields because we don't know how compilers for |
||
| 363 | // arbitrary machines will lay them out. |
||
| 364 | #define DT_2SECONDS_MASK 0x1F // seconds divided by 2 |
||
| 365 | #define DT_2SECONDS_SHIFT 0 |
||
| 366 | #define DT_MINUTES_MASK 0x7E0 // minutes |
||
| 367 | #define DT_MINUTES_SHIFT 5 |
||
| 368 | #define DT_HOURS_MASK 0xF800 // hours |
||
| 369 | #define DT_HOURS_SHIFT 11 |
||
| 370 | |||
| 371 | // This is the format of the contents of the deDate field in the direntry |
||
| 372 | // structure. |
||
| 373 | #define DD_DAY_MASK 0x1F // day of month |
||
| 374 | #define DD_DAY_SHIFT 0 |
||
| 375 | #define DD_MONTH_MASK 0x1E0 // month |
||
| 376 | #define DD_MONTH_SHIFT 5 |
||
| 377 | #define DD_YEAR_MASK 0xFE00 // year - 1980 |
||
| 378 | #define DD_YEAR_SHIFT 9 |
||
| 379 | |||
| 380 | // Stuctures |
||
| 381 | struct FileInfoStruct |
||
| 382 | { |
||
| 383 | unsigned long StartCluster; //< file starting cluster for last file accessed |
||
| 384 | unsigned long Size; //< file size for last file accessed |
||
| 385 | unsigned char Attr; //< file attr for last file accessed |
||
| 386 | unsigned short CreateTime; //< file creation time for last file accessed |
||
| 387 | unsigned short CreateDate; //< file creation date for last file accessed |
||
| 388 | }; |
||
| 389 | |||
| 390 | // Prototypes |
||
| 391 | unsigned char fatInit( unsigned char device); |
||
| 392 | unsigned int fatClusterSize(void); |
||
| 393 | unsigned char fatGetDirEntry(unsigned short entry); |
||
| 394 | unsigned char fatChangeDirectory(unsigned short entry); |
||
| 395 | void fatPrintDirEntry(void); |
||
| 396 | void fatDumpDirSlot(unsigned short entry); |
||
| 397 | struct FileInfoStruct* fatGetFileInfo(void); |
||
| 398 | unsigned long fatGetFilesize(void); |
||
| 399 | char* fatGetFilename(void); |
||
| 400 | char* fatGetDirname(void); |
||
| 401 | void fatLoadCluster(unsigned long cluster, unsigned char *buffer); |
||
| 402 | unsigned long fatNextCluster(unsigned long cluster); |
||
| 403 | |||
| 404 | #endif |
Powered by WebSVN v2.8.3