LPCOpen Platform
LPCOpen Platform for NXP LPC Microcontrollers
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dosfs.h
Go to the documentation of this file.
1 /*
2  DOSFS Embedded FAT-Compatible Filesystem
3  (C) 2005 Lewin A.R.W. Edwards (sysadm@zws.com)
4 */
5 
6 #ifndef _DOSFS_H
7 #define _DOSFS_H
8 
9 #include <stdint.h>
10 
11 //===================================================================
12 // User-supplied functions
13 uint32_t DFS_ReadSector(uint8_t unit, uint8_t *buffer, uint32_t sector, uint32_t count);
14 uint32_t DFS_WriteSector(uint8_t unit, uint8_t *buffer, uint32_t sector, uint32_t count);
15 
16 
17 //===================================================================
18 // Configurable items
19 #define MAX_PATH 64 // Maximum path length (increasing this will
20  // GREATLY increase stack requirements!)
21 #define DIR_SEPARATOR '/' // character separating directory components
22 
23 // End of configurable items
24 //===================================================================
25 
26 //===================================================================
27 // 32-bit error codes
28 #define DFS_OK 0 // no error
29 #define DFS_EOF 1 // end of file (not an error)
30 #define DFS_WRITEPROT 2 // volume is write protected
31 #define DFS_NOTFOUND 3 // path or file not found
32 #define DFS_PATHLEN 4 // path too long
33 #define DFS_ALLOCNEW 5 // must allocate new directory cluster
34 #define DFS_ERRMISC 0xffffffff // generic error
35 
36 //===================================================================
37 // File access modes
38 #define DFS_READ 1 // read-only
39 #define DFS_WRITE 2 // write-only
40 
41 //===================================================================
42 // Miscellaneous constants
43 #define SECTOR_SIZE 512 // sector size in bytes
44 
45 //===================================================================
46 // Internal subformat identifiers
47 #define FAT12 0
48 #define FAT16 1
49 #define FAT32 2
50 
51 //===================================================================
52 // DOS attribute bits
53 #define ATTR_READ_ONLY 0x01
54 #define ATTR_HIDDEN 0x02
55 #define ATTR_SYSTEM 0x04
56 #define ATTR_VOLUME_ID 0x08
57 #define ATTR_DIRECTORY 0x10
58 #define ATTR_ARCHIVE 0x20
59 #define ATTR_LONG_NAME (ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID)
60 
61 
62 /*
63  Directory entry structure
64  note: if name[0] == 0xe5, this is a free dir entry
65  if name[0] == 0x00, this is a free entry and all subsequent entries are free
66  if name[0] == 0x05, the first character of the name is 0xe5 [a kanji nicety]
67 
68  Date format: bit 0-4 = day of month (1-31)
69  bit 5-8 = month, 1=Jan..12=Dec
70  bit 9-15 = count of years since 1980 (0-127)
71  Time format: bit 0-4 = 2-second count, (0-29)
72  bit 5-10 = minutes (0-59)
73  bit 11-15= hours (0-23)
74 */
75 typedef struct _tagDIRENT {
76  uint8_t name[11]; // filename
77  uint8_t attr; // attributes (see ATTR_* constant definitions)
78  uint8_t reserved; // reserved, must be 0
79  uint8_t crttimetenth; // create time, 10ths of a second (0-199 are valid)
80  uint8_t crttime_l; // creation time low byte
81  uint8_t crttime_h; // creation time high byte
82  uint8_t crtdate_l; // creation date low byte
83  uint8_t crtdate_h; // creation date high byte
84  uint8_t lstaccdate_l; // last access date low byte
85  uint8_t lstaccdate_h; // last access date high byte
86  uint8_t startclus_h_l; // high word of first cluster, low byte (FAT32)
87  uint8_t startclus_h_h; // high word of first cluster, high byte (FAT32)
88  uint8_t wrttime_l; // last write time low byte
89  uint8_t wrttime_h; // last write time high byte
90  uint8_t wrtdate_l; // last write date low byte
91  uint8_t wrtdate_h; // last write date high byte
92  uint8_t startclus_l_l; // low word of first cluster, low byte
93  uint8_t startclus_l_h; // low word of first cluster, high byte
94  uint8_t filesize_0; // file size, low byte
95  uint8_t filesize_1; //
96  uint8_t filesize_2; //
97  uint8_t filesize_3; // file size, high byte
98 } DIRENT, *PDIRENT;
99 
100 /*
101  Partition table entry structure
102 */
103 typedef struct _tagPTINFO {
104  uint8_t active; // 0x80 if partition active
105  uint8_t start_h; // starting head
106  uint8_t start_cs_l; // starting cylinder and sector (low byte)
107  uint8_t start_cs_h; // starting cylinder and sector (high byte)
108  uint8_t type; // type ID byte
109  uint8_t end_h; // ending head
110  uint8_t end_cs_l; // ending cylinder and sector (low byte)
111  uint8_t end_cs_h; // ending cylinder and sector (high byte)
112  uint8_t start_0; // starting sector# (low byte)
113  uint8_t start_1; //
114  uint8_t start_2; //
115  uint8_t start_3; // starting sector# (high byte)
116  uint8_t size_0; // size of partition (low byte)
117  uint8_t size_1; //
118  uint8_t size_2; //
119  uint8_t size_3; // size of partition (high byte)
120 } PTINFO, *PPTINFO;
121 
122 /*
123  Master Boot Record structure
124 */
125 typedef struct _tagMBR {
126  uint8_t bootcode[0x1be]; // boot sector
127  PTINFO ptable[4]; // four partition table structures
128  uint8_t sig_55; // 0x55 signature byte
129  uint8_t sig_aa; // 0xaa signature byte
130 } MBR, *PMBR;
131 
132 /*
133  BIOS Parameter Block structure (FAT12/16)
134 */
135 typedef struct _tagBPB {
136  uint8_t bytepersec_l; // bytes per sector low byte (0x00)
137  uint8_t bytepersec_h; // bytes per sector high byte (0x02)
138  uint8_t secperclus; // sectors per cluster (1,2,4,8,16,32,64,128 are valid)
139  uint8_t reserved_l; // reserved sectors low byte
140  uint8_t reserved_h; // reserved sectors high byte
141  uint8_t numfats; // number of FAT copies (2)
142  uint8_t rootentries_l; // number of root dir entries low byte (0x00 normally)
143  uint8_t rootentries_h; // number of root dir entries high byte (0x02 normally)
144  uint8_t sectors_s_l; // small num sectors low byte
145  uint8_t sectors_s_h; // small num sectors high byte
146  uint8_t mediatype; // media descriptor byte
147  uint8_t secperfat_l; // sectors per FAT low byte
148  uint8_t secperfat_h; // sectors per FAT high byte
149  uint8_t secpertrk_l; // sectors per track low byte
150  uint8_t secpertrk_h; // sectors per track high byte
151  uint8_t heads_l; // heads low byte
152  uint8_t heads_h; // heads high byte
153  uint8_t hidden_0; // hidden sectors low byte
154  uint8_t hidden_1; // (note - this is the number of MEDIA sectors before
155  uint8_t hidden_2; // first sector of VOLUME - we rely on the MBR instead)
156  uint8_t hidden_3; // hidden sectors high byte
157  uint8_t sectors_l_0; // large num sectors low byte
158  uint8_t sectors_l_1; //
159  uint8_t sectors_l_2; //
160  uint8_t sectors_l_3; // large num sectors high byte
161 } BPB, *PBPB;
162 
163 /*
164  Extended BIOS Parameter Block structure (FAT12/16)
165 */
166 typedef struct _tagEBPB {
167  uint8_t unit; // int 13h drive#
168  uint8_t head; // archaic, used by Windows NT-class OSes for flags
169  uint8_t signature; // 0x28 or 0x29
170  uint8_t serial_0; // serial#
171  uint8_t serial_1; // serial#
172  uint8_t serial_2; // serial#
173  uint8_t serial_3; // serial#
174  uint8_t label[11]; // volume label
175  uint8_t system[8]; // filesystem ID
176 } EBPB, *PEBPB;
177 
178 /*
179  Extended BIOS Parameter Block structure (FAT32)
180 */
181 typedef struct _tagEBPB32 {
182  uint8_t fatsize_0; // big FAT size in sectors low byte
183  uint8_t fatsize_1; //
184  uint8_t fatsize_2; //
185  uint8_t fatsize_3; // big FAT size in sectors high byte
186  uint8_t extflags_l; // extended flags low byte
187  uint8_t extflags_h; // extended flags high byte
188  uint8_t fsver_l; // filesystem version (0x00) low byte
189  uint8_t fsver_h; // filesystem version (0x00) high byte
190  uint8_t root_0; // cluster of root dir, low byte
191  uint8_t root_1; //
192  uint8_t root_2; //
193  uint8_t root_3; // cluster of root dir, high byte
194  uint8_t fsinfo_l; // sector pointer to FSINFO within reserved area, low byte (2)
195  uint8_t fsinfo_h; // sector pointer to FSINFO within reserved area, high byte (0)
196  uint8_t bkboot_l; // sector pointer to backup boot sector within reserved area, low byte (6)
197  uint8_t bkboot_h; // sector pointer to backup boot sector within reserved area, high byte (0)
198  uint8_t reserved[12]; // reserved, should be 0
199 
200  uint8_t unit; // int 13h drive#
201  uint8_t head; // archaic, used by Windows NT-class OSes for flags
202  uint8_t signature; // 0x28 or 0x29
203  uint8_t serial_0; // serial#
204  uint8_t serial_1; // serial#
205  uint8_t serial_2; // serial#
206  uint8_t serial_3; // serial#
207  uint8_t label[11]; // volume label
208  uint8_t system[8]; // filesystem ID
209 } EBPB32, *PEBPB32;
210 
211 /*
212  Logical Boot Record structure (volume boot sector)
213 */
214 typedef struct _tagLBR {
215  uint8_t jump[3]; // JMP instruction
216  uint8_t oemid[8]; // OEM ID, space-padded
217  BPB bpb; // BIOS Parameter Block
218  union {
219  EBPB ebpb; // FAT12/16 Extended BIOS Parameter Block
220  EBPB32 ebpb32; // FAT32 Extended BIOS Parameter Block
221  } ebpb;
222  uint8_t code[420]; // boot sector code
223  uint8_t sig_55; // 0x55 signature byte
224  uint8_t sig_aa; // 0xaa signature byte
225 } LBR, *PLBR;
226 
227 /*
228  Volume information structure (Internal to DOSFS)
229 */
230 typedef struct _tagVOLINFO {
231  uint8_t unit; // unit on which this volume resides
232  uint8_t filesystem; // formatted filesystem
233 
234 // These two fields aren't very useful, so support for them has been commented out to
235 // save memory. (Note that the "system" tag is not actually used by DOS to determine
236 // filesystem type - that decision is made entirely on the basis of how many clusters
237 // the drive contains. DOSFS works the same way).
238 // See tag: OEMID in dosfs.c
239 // uint8_t oemid[9]; // OEM ID ASCIIZ
240 // uint8_t system[9]; // system ID ASCIIZ
241  uint8_t label[12]; // volume label ASCIIZ
242  uint32_t startsector; // starting sector of filesystem
243  uint8_t secperclus; // sectors per cluster
244  uint16_t reservedsecs; // reserved sectors
245  uint32_t numsecs; // number of sectors in volume
246  uint32_t secperfat; // sectors per FAT
247  uint16_t rootentries; // number of root dir entries
248 
249  uint32_t numclusters; // number of clusters on drive
250 
251  // The fields below are PHYSICAL SECTOR NUMBERS.
252  uint32_t fat1; // starting sector# of FAT copy 1
253  uint32_t rootdir; // starting sector# of root directory (FAT12/FAT16) or cluster (FAT32)
254  uint32_t dataarea; // starting sector# of data area (cluster #2)
255 } VOLINFO, *PVOLINFO;
256 
257 /*
258  Flags in DIRINFO.flags
259 */
260 #define DFS_DI_BLANKENT 0x01 // Searching for blank entry
261 
262 /*
263  Directory search structure (Internal to DOSFS)
264 */
265 typedef struct _tagDIRINFO {
266  uint32_t currentcluster; // current cluster in dir
267  uint8_t currentsector; // current sector in cluster
268  uint8_t currententry; // current dir entry in sector
269  uint8_t *scratch; // ptr to user-supplied scratch buffer (one sector)
270  uint8_t flags; // internal DOSFS flags
271 } DIRINFO, *PDIRINFO;
272 
273 /*
274  File handle structure (Internal to DOSFS)
275 */
276 typedef struct _tagFILEINFO {
277  PVOLINFO volinfo; // VOLINFO used to open this file
278  uint32_t dirsector; // physical sector containing dir entry of this file
279  uint8_t diroffset; // # of this entry within the dir sector
280  uint8_t mode; // mode in which this file was opened
281  uint32_t firstcluster; // first cluster of file
282  uint32_t filelen; // byte length of file
283 
284  uint32_t cluster; // current cluster
285  uint32_t pointer; // current (BYTE) pointer
286 } FILEINFO, *PFILEINFO;
287 
288 /*
289  Get starting sector# of specified partition on drive #unit
290  NOTE: This code ASSUMES an MBR on the disk.
291  scratchsector should point to a SECTOR_SIZE scratch area
292  Returns 0xffffffff for any error.
293  If pactive is non-NULL, this function also returns the partition active flag.
294  If pptype is non-NULL, this function also returns the partition type.
295  If psize is non-NULL, this function also returns the partition size.
296 */
297 uint32_t DFS_GetPtnStart(uint8_t unit, uint8_t *scratchsector, uint8_t pnum, uint8_t *pactive, uint8_t *pptype, uint32_t *psize);
298 
299 /*
300  Retrieve volume info from BPB and store it in a VOLINFO structure
301  You must provide the unit and starting sector of the filesystem, and
302  a pointer to a sector buffer for scratch
303  Attempts to read BPB and glean information about the FS from that.
304  Returns 0 OK, nonzero for any error.
305 */
306 uint32_t DFS_GetVolInfo(uint8_t unit, uint8_t *scratchsector, uint32_t startsector, PVOLINFO volinfo);
307 
308 /*
309  Open a directory for enumeration by DFS_GetNextDirEnt
310  You must supply a populated VOLINFO (see DFS_GetVolInfo)
311  The empty string or a string containing only the directory separator are
312  considered to be the root directory.
313  Returns 0 OK, nonzero for any error.
314 */
315 uint32_t DFS_OpenDir(PVOLINFO volinfo, uint8_t *dirname, PDIRINFO dirinfo);
316 
317 /*
318  Get next entry in opened directory structure. Copies fields into the dirent
319  structure, updates dirinfo. Note that it is the _caller's_ responsibility to
320  handle the '.' and '..' entries.
321  A deleted file will be returned as a NULL entry (first char of filename=0)
322  by this code. Filenames beginning with 0x05 will be translated to 0xE5
323  automatically. Long file name entries will be returned as NULL.
324  returns DFS_EOF if there are no more entries, DFS_OK if this entry is valid,
325  or DFS_ERRMISC for a media error
326 */
327 uint32_t DFS_GetNext(PVOLINFO volinfo, PDIRINFO dirinfo, PDIRENT dirent);
328 
329 /*
330  Open a file for reading or writing. You supply populated VOLINFO, a path to the file,
331  mode (DFS_READ or DFS_WRITE) and an empty fileinfo structure. You also need to
332  provide a pointer to a sector-sized scratch buffer.
333  Returns various DFS_* error states. If the result is DFS_OK, fileinfo can be used
334  to access the file from this point on.
335 */
336 uint32_t DFS_OpenFile(PVOLINFO volinfo, uint8_t *path, uint8_t mode, uint8_t *scratch, PFILEINFO fileinfo);
337 
338 /*
339  Read an open file
340  You must supply a prepopulated FILEINFO as provided by DFS_OpenFile, and a
341  pointer to a SECTOR_SIZE scratch buffer.
342  Note that returning DFS_EOF is not an error condition. This function updates the
343  successcount field with the number of bytes actually read.
344 */
345 uint32_t DFS_ReadFile(PFILEINFO fileinfo, uint8_t *scratch, uint8_t *buffer, uint32_t *successcount, uint32_t len);
346 
347 /*
348  Write an open file
349  You must supply a prepopulated FILEINFO as provided by DFS_OpenFile, and a
350  pointer to a SECTOR_SIZE scratch buffer.
351  This function updates the successcount field with the number of bytes actually written.
352 */
353 uint32_t DFS_WriteFile(PFILEINFO fileinfo, uint8_t *scratch, uint8_t *buffer, uint32_t *successcount, uint32_t len);
354 
355 /*
356  Seek file pointer to a given position
357  This function does not return status - refer to the fileinfo->pointer value
358  to see where the pointer wound up.
359  Requires a SECTOR_SIZE scratch buffer
360 */
361 void DFS_Seek(PFILEINFO fileinfo, uint32_t offset, uint8_t *scratch);
362 
363 /*
364  Delete a file
365  scratch must point to a sector-sized buffer
366 */
367 uint32_t DFS_UnlinkFile(PVOLINFO volinfo, uint8_t *path, uint8_t *scratch);
368 
369 // If we are building a host-emulation version, include host support
370 #ifdef HOSTVER
371 #include "hostemu.h"
372 #endif
373 
374 #endif // _DOSFS_H