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