summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/common/dir.c3
-rw-r--r--firmware/common/file.c178
-rw-r--r--firmware/common/file.h16
-rw-r--r--firmware/debug.c11
-rw-r--r--firmware/debug.h6
-rw-r--r--firmware/drivers/fat.c585
-rw-r--r--firmware/drivers/fat.h19
-rw-r--r--firmware/test/fat/README25
-rw-r--r--firmware/test/fat/ata-sim.c7
-rw-r--r--firmware/test/fat/main.c52
10 files changed, 610 insertions, 292 deletions
diff --git a/firmware/common/dir.c b/firmware/common/dir.c
index 70aa4946dc..6bf9a53cad 100644
--- a/firmware/common/dir.c
+++ b/firmware/common/dir.c
@@ -105,8 +105,7 @@ struct dirent* readdir(DIR* dir)
105 return NULL; 105 return NULL;
106 106
107 if ( !entry.name[0] ) 107 if ( !entry.name[0] )
108 return NULL; 108 return NULL;
109
110 109
111 strncpy(theent->d_name, entry.name, sizeof( theent->d_name ) ); 110 strncpy(theent->d_name, entry.name, sizeof( theent->d_name ) );
112 theent->attribute = entry.attr; 111 theent->attribute = entry.attr;
diff --git a/firmware/common/file.c b/firmware/common/file.c
index 2c00c3e3f6..27258e4603 100644
--- a/firmware/common/file.c
+++ b/firmware/common/file.c
@@ -42,23 +42,25 @@ struct filedesc {
42 int size; 42 int size;
43 struct fat_file fatfile; 43 struct fat_file fatfile;
44 bool busy; 44 bool busy;
45 bool write;
45}; 46};
46 47
47static struct filedesc openfiles[MAX_OPEN_FILES]; 48static struct filedesc openfiles[MAX_OPEN_FILES];
48 49
49int open(char* pathname, int flags) 50int creat(const char *pathname, int mode)
51{
52 (void)mode;
53 return open(pathname, O_WRONLY);
54}
55
56int open(const char* pathname, int flags)
50{ 57{
51 DIR* dir; 58 DIR* dir;
52 struct dirent* entry; 59 struct dirent* entry;
53 int fd; 60 int fd;
54 char* name; 61 char* name;
55 62
56 /* For now, we don't support writing */ 63 LDEBUGF("open(\"%s\",%d)\n",pathname,flags);
57 if(flags & (O_WRONLY | O_RDWR))
58 {
59 errno = EROFS;
60 return -1;
61 }
62 64
63 if ( pathname[0] != '/' ) { 65 if ( pathname[0] != '/' ) {
64 DEBUGF("'%s' is not an absolute path.\n",pathname); 66 DEBUGF("'%s' is not an absolute path.\n",pathname);
@@ -75,44 +77,74 @@ int open(char* pathname, int flags)
75 if ( fd == MAX_OPEN_FILES ) { 77 if ( fd == MAX_OPEN_FILES ) {
76 DEBUGF("Too many files open\n"); 78 DEBUGF("Too many files open\n");
77 errno = EMFILE; 79 errno = EMFILE;
78 return -1; 80 return -2;
79 } 81 }
80 82
83 switch ( flags ) {
84 case O_RDONLY:
85 openfiles[fd].write = false;
86 break;
87
88 case O_WRONLY:
89 openfiles[fd].write = true;
90 break;
91
92 default:
93 DEBUGF("Only O_RDONLY and O_WRONLY is supported\n");
94 errno = EROFS;
95 return -3;
96 }
81 openfiles[fd].busy = true; 97 openfiles[fd].busy = true;
82 98
83 /* locate filename */ 99 /* locate filename */
84 name=strrchr(pathname+1,'/'); 100 name=strrchr(pathname+1,'/');
85 if ( name ) { 101 if ( name ) {
86 *name = 0; 102 *name = 0;
87 dir = opendir(pathname); 103 dir = opendir((char*)pathname);
88 *name = '/'; 104 *name = '/';
89 name++; 105 name++;
90 } 106 }
91 else { 107 else {
92 dir = opendir("/"); 108 dir = opendir("/");
93 name = pathname+1; 109 name = (char*)pathname+1;
94 } 110 }
95 if (!dir) { 111 if (!dir) {
96 DEBUGF("Failed opening dir\n"); 112 DEBUGF("Failed opening dir\n");
97 errno = EIO; 113 errno = EIO;
98 openfiles[fd].busy = false; 114 openfiles[fd].busy = false;
99 return -1; 115 return -4;
100 } 116 }
101 117
102 /* scan dir for name */ 118 /* scan dir for name */
103 while ((entry = readdir(dir))) { 119 while ((entry = readdir(dir))) {
104 if ( !strcasecmp(name, entry->d_name) ) { 120 if ( !strcasecmp(name, entry->d_name) ) {
105 fat_open(entry->startcluster, &(openfiles[fd].fatfile)); 121 fat_open(entry->startcluster,
122 &(openfiles[fd].fatfile),
123 &(dir->fatdir));
106 openfiles[fd].size = entry->size; 124 openfiles[fd].size = entry->size;
107 break; 125 break;
108 } 126 }
109 } 127 }
110 closedir(dir); 128 closedir(dir);
111 if ( !entry ) { 129 if ( !entry ) {
112 DEBUGF("Couldn't find %s in %s\n",name,pathname); 130 LDEBUGF("Didn't find file %s\n",name);
113 errno = ENOENT; 131 if ( openfiles[fd].write ) {
114 openfiles[fd].busy = false; 132 if (fat_create_file(name,
115 return -1; 133 &(openfiles[fd].fatfile),
134 &(dir->fatdir)) < 0) {
135 DEBUGF("Couldn't create %s in %s\n",name,pathname);
136 errno = EIO;
137 openfiles[fd].busy = false;
138 return -5;
139 }
140 openfiles[fd].size = 0;
141 }
142 else {
143 DEBUGF("Couldn't find %s in %s\n",name,pathname);
144 errno = ENOENT;
145 openfiles[fd].busy = false;
146 return -6;
147 }
116 } 148 }
117 149
118 openfiles[fd].cacheoffset = -1; 150 openfiles[fd].cacheoffset = -1;
@@ -122,19 +154,37 @@ int open(char* pathname, int flags)
122 154
123int close(int fd) 155int close(int fd)
124{ 156{
157 int rc = 0;
158
159 LDEBUGF("close(%d)\n",fd);
160
125 if (fd < 0 || fd > MAX_OPEN_FILES-1) { 161 if (fd < 0 || fd > MAX_OPEN_FILES-1) {
126 errno = EINVAL; 162 errno = EINVAL;
127 return -1; 163 return -1;
128 } 164 }
129 if (!openfiles[fd].busy) { 165 if (!openfiles[fd].busy) {
130 errno = EBADF; 166 errno = EBADF;
131 return -1; 167 return -2;
168 }
169 if (openfiles[fd].write) {
170 /* flush sector cache */
171 if ( openfiles[fd].cacheoffset != -1 ) {
172 if ( fat_readwrite(&(openfiles[fd].fatfile), 1,
173 &(openfiles[fd].cache),true) < 0 ) {
174 DEBUGF("Failed flushing cache\n");
175 errno = EIO;
176 rc = -1;
177 }
178 }
179
180 /* tie up all loose ends */
181 fat_closewrite(&(openfiles[fd].fatfile), openfiles[fd].size);
132 } 182 }
133 openfiles[fd].busy = false; 183 openfiles[fd].busy = false;
134 return 0; 184 return rc;
135} 185}
136 186
137int read(int fd, void* buf, int count) 187static int readwrite(int fd, void* buf, int count, bool write)
138{ 188{
139 int sectors; 189 int sectors;
140 int nread=0; 190 int nread=0;
@@ -144,9 +194,16 @@ int read(int fd, void* buf, int count)
144 return -1; 194 return -1;
145 } 195 }
146 196
147 /* attempt to read past EOF? */ 197 LDEBUGF( "readwrite(%d,%x,%d,%s)\n",
148 if ( count > openfiles[fd].size - openfiles[fd].fileoffset ) 198 fd,buf,count,write?"write":"read");
149 count = openfiles[fd].size - openfiles[fd].fileoffset; 199
200 /* attempt to access past EOF? */
201 if (count > openfiles[fd].size - openfiles[fd].fileoffset) {
202 if ( write )
203 openfiles[fd].size = openfiles[fd].fileoffset + count;
204 else
205 count = openfiles[fd].size - openfiles[fd].fileoffset;
206 }
150 207
151 /* any head bytes? */ 208 /* any head bytes? */
152 if ( openfiles[fd].cacheoffset != -1 ) { 209 if ( openfiles[fd].cacheoffset != -1 ) {
@@ -163,23 +220,38 @@ int read(int fd, void* buf, int count)
163 openfiles[fd].cacheoffset = -1; 220 openfiles[fd].cacheoffset = -1;
164 } 221 }
165 222
166 /* eof? */ 223 if (write) {
167 if ( openfiles[fd].fileoffset + headbytes > openfiles[fd].size ) 224 memcpy( openfiles[fd].cache + offs, buf, headbytes );
168 headbytes = openfiles[fd].size - openfiles[fd].fileoffset; 225 if (offs+headbytes == SECTOR_SIZE) {
226 int rc = fat_readwrite(&(openfiles[fd].fatfile), 1,
227 openfiles[fd].cache, true );
228 if ( rc < 0 ) {
229 DEBUGF("Failed read/writing %d sectors\n",sectors);
230 errno = EIO;
231 return -2;
232 }
233 openfiles[fd].cacheoffset = -1;
234 }
235 }
236 else {
237 memcpy( buf, openfiles[fd].cache + offs, headbytes );
238 }
169 239
170 memcpy( buf, openfiles[fd].cache + offs, headbytes );
171 nread = headbytes; 240 nread = headbytes;
172 count -= headbytes; 241 count -= headbytes;
242
243 LDEBUGF("readwrite incache: offs=%d\n",openfiles[fd].cacheoffset);
173 } 244 }
174 245
175 /* read whole sectors right into the supplied buffer */ 246 /* read whole sectors right into the supplied buffer */
176 sectors = count / SECTOR_SIZE; 247 sectors = count / SECTOR_SIZE;
177 if ( sectors ) { 248 if ( sectors ) {
178 int rc = fat_read(&(openfiles[fd].fatfile), sectors, buf+nread ); 249 int rc = fat_readwrite(&(openfiles[fd].fatfile), sectors,
250 buf+nread, write );
179 if ( rc < 0 ) { 251 if ( rc < 0 ) {
180 DEBUGF("Failed reading %d sectors\n",sectors); 252 DEBUGF("Failed read/writing %d sectors\n",sectors);
181 errno = EIO; 253 errno = EIO;
182 return -1; 254 return -2;
183 } 255 }
184 else { 256 else {
185 if ( rc > 0 ) { 257 if ( rc > 0 ) {
@@ -197,18 +269,19 @@ int read(int fd, void* buf, int count)
197 269
198 /* any tail bytes? */ 270 /* any tail bytes? */
199 if ( count ) { 271 if ( count ) {
200 if ( fat_read(&(openfiles[fd].fatfile), 1, 272 if (write) {
201 &(openfiles[fd].cache)) < 0 ) { 273 memcpy( openfiles[fd].cache, buf + nread, count );
202 DEBUGF("Failed caching sector\n");
203 errno = EIO;
204 return -1;
205 } 274 }
206 275 else {
207 /* eof? */ 276 if ( fat_readwrite(&(openfiles[fd].fatfile), 1,
208 if ( openfiles[fd].fileoffset + count > openfiles[fd].size ) 277 &(openfiles[fd].cache),false) < 0 ) {
209 count = openfiles[fd].size - openfiles[fd].fileoffset; 278 DEBUGF("Failed caching sector\n");
210 279 errno = EIO;
211 memcpy( buf + nread, openfiles[fd].cache, count ); 280 return -1;
281 }
282 memcpy( buf + nread, openfiles[fd].cache, count );
283 }
284
212 nread += count; 285 nread += count;
213 openfiles[fd].cacheoffset = count; 286 openfiles[fd].cacheoffset = count;
214 } 287 }
@@ -217,6 +290,17 @@ int read(int fd, void* buf, int count)
217 return nread; 290 return nread;
218} 291}
219 292
293int write(int fd, void* buf, int count)
294{
295 return readwrite(fd, buf, count, true);
296}
297
298int read(int fd, void* buf, int count)
299{
300 return readwrite(fd, buf, count, false);
301}
302
303
220int lseek(int fd, int offset, int whence) 304int lseek(int fd, int offset, int whence)
221{ 305{
222 int pos; 306 int pos;
@@ -225,6 +309,8 @@ int lseek(int fd, int offset, int whence)
225 int sectoroffset; 309 int sectoroffset;
226 int rc; 310 int rc;
227 311
312 LDEBUGF("lseek(%d,%d,%d)\n",fd,offset,whence);
313
228 if ( !openfiles[fd].busy ) { 314 if ( !openfiles[fd].busy ) {
229 errno = EBADF; 315 errno = EBADF;
230 return -1; 316 return -1;
@@ -245,11 +331,11 @@ int lseek(int fd, int offset, int whence)
245 331
246 default: 332 default:
247 errno = EINVAL; 333 errno = EINVAL;
248 return -1; 334 return -2;
249 } 335 }
250 if ((pos < 0) || (pos > openfiles[fd].size)) { 336 if ((pos < 0) || (pos > openfiles[fd].size)) {
251 errno = EINVAL; 337 errno = EINVAL;
252 return -1; 338 return -3;
253 } 339 }
254 340
255 /* new sector? */ 341 /* new sector? */
@@ -263,14 +349,14 @@ int lseek(int fd, int offset, int whence)
263 rc = fat_seek(&(openfiles[fd].fatfile), newsector); 349 rc = fat_seek(&(openfiles[fd].fatfile), newsector);
264 if ( rc < 0 ) { 350 if ( rc < 0 ) {
265 errno = EIO; 351 errno = EIO;
266 return -1; 352 return -4;
267 } 353 }
268 } 354 }
269 rc = fat_read(&(openfiles[fd].fatfile), 1, 355 rc = fat_readwrite(&(openfiles[fd].fatfile), 1,
270 &(openfiles[fd].cache)); 356 &(openfiles[fd].cache),false);
271 if ( rc < 0 ) { 357 if ( rc < 0 ) {
272 errno = EIO; 358 errno = EIO;
273 return -1; 359 return -5;
274 } 360 }
275 openfiles[fd].cacheoffset = sectoroffset; 361 openfiles[fd].cacheoffset = sectoroffset;
276 } 362 }
diff --git a/firmware/common/file.h b/firmware/common/file.h
index c95811fc55..7a7c63d665 100644
--- a/firmware/common/file.h
+++ b/firmware/common/file.h
@@ -40,24 +40,22 @@
40#endif 40#endif
41 41
42#if defined(__MINGW32__) && defined(SIMULATOR) 42#if defined(__MINGW32__) && defined(SIMULATOR)
43int open (const char*, int, ...); 43extern int open(const char*, int, ...);
44extern int close(int fd); 44extern int close(int fd);
45int read (int, void*, unsigned int); 45extern int read(int, void*, unsigned int);
46long lseek (int, long, int); 46extern long lseek(int, long, int);
47 47
48#else 48#else
49 49
50#ifndef SIMULATOR 50#ifndef SIMULATOR
51extern int open(char* pathname, int flags); 51extern int open(const char* pathname, int flags);
52extern int close(int fd); 52extern int close(int fd);
53extern int read(int fd, void* buf, int count); 53extern int read(int fd, void* buf, int count);
54extern int lseek(int fd, int offset, int whence); 54extern int lseek(int fd, int offset, int whence);
55 55extern int creat(const char *pathname, int mode);
56#ifdef DISK_WRITE
57extern int write(int fd, void* buf, int count); 56extern int write(int fd, void* buf, int count);
58extern int remove(char* pathname); 57extern int remove(const char* pathname);
59extern int rename(char* oldname, char* newname); 58extern int rename(const char* oldname, const char* newname);
60#endif
61 59
62#else 60#else
63#ifdef WIN32 61#ifdef WIN32
diff --git a/firmware/debug.c b/firmware/debug.c
index 83eb149706..2ebcd86778 100644
--- a/firmware/debug.c
+++ b/firmware/debug.c
@@ -195,7 +195,9 @@ static void debug(char *msg)
195} 195}
196#endif /* end of DEBUG section */ 196#endif /* end of DEBUG section */
197 197
198#ifdef __GNUC__
198void debugf(char *fmt, ...) 199void debugf(char *fmt, ...)
200#endif
199{ 201{
200#ifdef DEBUG 202#ifdef DEBUG
201 va_list ap; 203 va_list ap;
@@ -223,4 +225,13 @@ void debugf(char *fmt, ...)
223 vfprintf( stderr, fmt, ap ); 225 vfprintf( stderr, fmt, ap );
224 va_end( ap ); 226 va_end( ap );
225} 227}
228
229void ldebugf(char* file, int line, char *fmt, ...)
230{
231 va_list ap;
232 va_start( ap, fmt );
233 fprintf( stderr, "%s:%d ", file, line );
234 vfprintf( stderr, fmt, ap );
235 va_end( ap );
236}
226#endif 237#endif
diff --git a/firmware/debug.h b/firmware/debug.h
index e9eec27e86..878da295bc 100644
--- a/firmware/debug.h
+++ b/firmware/debug.h
@@ -21,20 +21,24 @@
21 21
22extern void debug_init(void); 22extern void debug_init(void);
23extern void debugf(char* fmt,...); 23extern void debugf(char* fmt,...);
24extern void ldebugf(char* file, int line, char *fmt, ...);
24 25
25#ifdef __GNUC__ 26#ifdef __GNUC__
26 27
27/* */ 28/* */
28#if defined(DEBUG) || defined(SIMULATOR) 29#if defined(DEBUG) || defined(SIMULATOR)
29//#define DEBUGF(...) debugf(__VA_ARGS__)
30#define DEBUGF debugf 30#define DEBUGF debugf
31#define LDEBUGF(...) ldebugf(__FILE__, __LINE__, __VA_ARGS__)
31#else 32#else
32#define DEBUGF(...) 33#define DEBUGF(...)
34#define LDEBUGF(...)
33#endif 35#endif
34 36
37
35#else 38#else
36 39
37#define DEBUGF debugf 40#define DEBUGF debugf
41#define LDEBUGF debugf
38 42
39#endif /* GCC */ 43#endif /* GCC */
40 44
diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c
index 7bed896748..322ae76a2d 100644
--- a/firmware/drivers/fat.c
+++ b/firmware/drivers/fat.c
@@ -22,14 +22,11 @@
22#include <math.h> 22#include <math.h>
23#include <stdlib.h> 23#include <stdlib.h>
24#include <ctype.h> 24#include <ctype.h>
25#ifdef DISK_WRITE
26#include <time.h>
27#include <sys/timeb.h>
28#endif
29#include <stdbool.h> 25#include <stdbool.h>
30#include "fat.h" 26#include "fat.h"
31#include "ata.h" 27#include "ata.h"
32#include "debug.h" 28#include "debug.h"
29#include "panic.h"
33#include "system.h" 30#include "system.h"
34 31
35#define BYTES2INT16(array,pos) \ 32#define BYTES2INT16(array,pos) \
@@ -38,11 +35,6 @@
38 (array[pos] | (array[pos+1] << 8 ) | \ 35 (array[pos] | (array[pos+1] << 8 ) | \
39 (array[pos+2] << 16 ) | (array[pos+3] << 24 )) 36 (array[pos+2] << 16 ) | (array[pos+3] << 24 ))
40 37
41#define NUM_ROOT_DIR_ENTRIES 512
42#define NUM_FATS 2
43#define NUM_RESERVED_SECTORS 1
44#define NUM_BLOCKS 10000
45
46#define FATTYPE_FAT12 0 38#define FATTYPE_FAT12 0
47#define FATTYPE_FAT16 1 39#define FATTYPE_FAT16 1
48#define FATTYPE_FAT32 2 40#define FATTYPE_FAT32 2
@@ -107,6 +99,12 @@
107#define FATDIR_FSTCLUSLO 26 99#define FATDIR_FSTCLUSLO 26
108#define FATDIR_FILESIZE 28 100#define FATDIR_FILESIZE 28
109 101
102#define CLUSTERS_PER_FAT_SECTOR (SECTOR_SIZE / 4)
103#define DIR_ENTRIES_PER_SECTOR (SECTOR_SIZE / 32)
104#define DIR_ENTRY_SIZE 32
105#define FAT_BAD_MARK 0x0ffffff7
106#define FAT_EOF_MARK 0x0ffffff8
107
110struct fsinfo { 108struct fsinfo {
111 int freecount; /* last known free cluster count */ 109 int freecount; /* last known free cluster count */
112 int nextfree; /* first cluster to start looking for free clusters, 110 int nextfree; /* first cluster to start looking for free clusters,
@@ -155,6 +153,7 @@ struct bpb
155 int rootdirsector; 153 int rootdirsector;
156 int firstdatasector; 154 int firstdatasector;
157 int startsector; 155 int startsector;
156 struct fsinfo fsinfo;
158}; 157};
159 158
160static struct bpb fat_bpb; 159static struct bpb fat_bpb;
@@ -167,6 +166,7 @@ static unsigned int getcurrdostime(unsigned short *dosdate,
167 unsigned short *dostime, 166 unsigned short *dostime,
168 unsigned char *dostenth); 167 unsigned char *dostenth);
169static int create_dos_name(unsigned char *name, unsigned char *newname); 168static int create_dos_name(unsigned char *name, unsigned char *newname);
169static int find_free_cluster(int start);
170#endif 170#endif
171 171
172#define FAT_CACHE_SIZE 0x20 172#define FAT_CACHE_SIZE 0x20
@@ -256,7 +256,6 @@ int fat_mount(int startsector)
256 fat_bpb.bpb_secperclus = buf[BPB_SECPERCLUS]; 256 fat_bpb.bpb_secperclus = buf[BPB_SECPERCLUS];
257 fat_bpb.bpb_rsvdseccnt = BYTES2INT16(buf,BPB_RSVDSECCNT); 257 fat_bpb.bpb_rsvdseccnt = BYTES2INT16(buf,BPB_RSVDSECCNT);
258 fat_bpb.bpb_numfats = buf[BPB_NUMFATS]; 258 fat_bpb.bpb_numfats = buf[BPB_NUMFATS];
259 fat_bpb.bpb_rootentcnt = BYTES2INT16(buf,BPB_ROOTENTCNT);
260 fat_bpb.bpb_totsec16 = BYTES2INT16(buf,BPB_TOTSEC16); 259 fat_bpb.bpb_totsec16 = BYTES2INT16(buf,BPB_TOTSEC16);
261 fat_bpb.bpb_media = buf[BPB_MEDIA]; 260 fat_bpb.bpb_media = buf[BPB_MEDIA];
262 fat_bpb.bpb_fatsz16 = BYTES2INT16(buf,BPB_FATSZ16); 261 fat_bpb.bpb_fatsz16 = BYTES2INT16(buf,BPB_FATSZ16);
@@ -295,7 +294,7 @@ int fat_mount(int startsector)
295#endif 294#endif
296 { 295 {
297 DEBUGF("This is not FAT32. Go away!\n"); 296 DEBUGF("This is not FAT32. Go away!\n");
298 return -1; 297 return -2;
299 } 298 }
300 299
301 fat_bpb.bpb_extflags = BYTES2INT16(buf,BPB_EXTFLAGS); 300 fat_bpb.bpb_extflags = BYTES2INT16(buf,BPB_EXTFLAGS);
@@ -316,11 +315,23 @@ int fat_mount(int startsector)
316 if (bpb_is_sane() < 0) 315 if (bpb_is_sane() < 0)
317 { 316 {
318 DEBUGF( "fat_mount() - BPB is not sane\n"); 317 DEBUGF( "fat_mount() - BPB is not sane\n");
319 return -1; 318 return -3;
320 } 319 }
321 320
322 fat_bpb.rootdirsector = cluster2sec(fat_bpb.bpb_rootclus); 321 fat_bpb.rootdirsector = cluster2sec(fat_bpb.bpb_rootclus);
323 322
323 /* Read the fsinfo sector */
324 err = ata_read_sectors(startsector + fat_bpb.bpb_fsinfo, 1, buf);
325 if (err)
326 {
327 DEBUGF( "fat_mount() - Couldn't read FSInfo (error code %d)\n", err);
328 return -1;
329 }
330 fat_bpb.fsinfo.freecount = BYTES2INT32(buf, FSINFO_FREECOUNT);
331 fat_bpb.fsinfo.nextfree = BYTES2INT32(buf, FSINFO_NEXTFREE);
332 LDEBUGF("Freecount: %x\n",fat_bpb.fsinfo.freecount);
333 LDEBUGF("Nextfree: %x\n",fat_bpb.fsinfo.nextfree);
334
324 return 0; 335 return 0;
325} 336}
326 337
@@ -339,9 +350,9 @@ static int bpb_is_sane(void)
339 fat_bpb.bpb_bytspersec, fat_bpb.bpb_secperclus, 350 fat_bpb.bpb_bytspersec, fat_bpb.bpb_secperclus,
340 fat_bpb.bpb_bytspersec * fat_bpb.bpb_secperclus); 351 fat_bpb.bpb_bytspersec * fat_bpb.bpb_secperclus);
341 } 352 }
342 if(fat_bpb.bpb_rsvdseccnt != 1) 353 if (fat_bpb.bpb_rsvdseccnt != 32)
343 { 354 {
344 DEBUGF( "bpb_is_sane() - Warning: Reserved sectors is not 1 (%d)\n", 355 DEBUGF( "bpb_is_sane() - Warning: Reserved sectors is not 32 (%d)\n",
345 fat_bpb.bpb_rsvdseccnt); 356 fat_bpb.bpb_rsvdseccnt);
346 } 357 }
347 if(fat_bpb.bpb_numfats != 2) 358 if(fat_bpb.bpb_numfats != 2)
@@ -349,11 +360,6 @@ static int bpb_is_sane(void)
349 DEBUGF( "bpb_is_sane() - Warning: NumFATS is not 2 (%d)\n", 360 DEBUGF( "bpb_is_sane() - Warning: NumFATS is not 2 (%d)\n",
350 fat_bpb.bpb_numfats); 361 fat_bpb.bpb_numfats);
351 } 362 }
352 if(fat_bpb.bpb_rootentcnt != 512)
353 {
354 DEBUGF( "bpb_is_sane() - Warning: RootEntCnt is not 512 (%d)\n",
355 fat_bpb.bpb_rootentcnt);
356 }
357 if(fat_bpb.bpb_media != 0xf0 && fat_bpb.bpb_media < 0xf8) 363 if(fat_bpb.bpb_media != 0xf0 && fat_bpb.bpb_media < 0xf8)
358 { 364 {
359 DEBUGF( "bpb_is_sane() - Warning: Non-standard " 365 DEBUGF( "bpb_is_sane() - Warning: Non-standard "
@@ -364,33 +370,42 @@ static int bpb_is_sane(void)
364 { 370 {
365 DEBUGF( "bpb_is_sane() - Error: Last word is not " 371 DEBUGF( "bpb_is_sane() - Error: Last word is not "
366 "0xaa55 (0x%04x)\n", fat_bpb.last_word); 372 "0xaa55 (0x%04x)\n", fat_bpb.last_word);
367 return -1; 373 return -4;
374 }
375
376 if (fat_bpb.fsinfo.freecount >
377 (fat_bpb.totalsectors - fat_bpb.firstdatasector)/
378 fat_bpb.bpb_secperclus)
379 {
380 DEBUGF( "bpb_is_sane() - Error: FSInfo.Freecount > disk size "
381 "(0x%04x)\n", fat_bpb.fsinfo.freecount);
382 return -5;
368 } 383 }
384
369 return 0; 385 return 0;
370} 386}
371 387
372static void *cache_fat_sector(int secnum) 388static void *cache_fat_sector(int fatsector)
373{ 389{
390 int secnum = fatsector + fat_bpb.bpb_rsvdseccnt;
374 int cache_index = secnum & FAT_CACHE_MASK; 391 int cache_index = secnum & FAT_CACHE_MASK;
375 392
376 /* Delete the cache entry if it isn't the sector we want */ 393 /* Delete the cache entry if it isn't the sector we want */
377 if(fat_cache[cache_index].inuse && 394 if(fat_cache[cache_index].inuse &&
378 fat_cache[cache_index].secnum != secnum) 395 fat_cache[cache_index].secnum != secnum)
379 { 396 {
380#ifdef WRITE
381 /* Write back if it is dirty */ 397 /* Write back if it is dirty */
382 if(fat_cache[cache_index].dirty) 398 if(fat_cache[cache_index].dirty)
383 { 399 {
384 if(ata_write_sectors(secnum + fat_bpb.startsector, 1, sec)) 400 if(ata_write_sectors(secnum + fat_bpb.startsector, 1,
401 fat_cache_sectors[cache_index]))
385 { 402 {
386 panic("cache_fat_sector() - Could" 403 panicf("cache_fat_sector() - Could not write sector %d\n",
387 " not write sector %d\n", 404 secnum);
388 secnum);
389 } 405 }
390 } 406 }
391 fat_cache[cache_index].secnum = 8; /* Normally an unused sector */ 407 fat_cache[cache_index].secnum = 8; /* Normally an unused sector */
392 fat_cache[cache_index].dirty = false; 408 fat_cache[cache_index].dirty = false;
393#endif
394 fat_cache[cache_index].inuse = false; 409 fat_cache[cache_index].inuse = false;
395 } 410 }
396 411
@@ -409,101 +424,107 @@ static void *cache_fat_sector(int secnum)
409 return fat_cache_sectors[cache_index]; 424 return fat_cache_sectors[cache_index];
410} 425}
411 426
412#ifdef DISK_WRITE 427static int find_free_cluster(int startcluster)
413static int update_entry(int entry, unsigned int val)
414{ 428{
415 unsigned long *sec; 429 int sector = startcluster / CLUSTERS_PER_FAT_SECTOR;
416 int fatoffset; 430 int offset = startcluster % CLUSTERS_PER_FAT_SECTOR;
417 int thisfatsecnum; 431 int i;
418 int thisfatentoffset;
419 432
420 fatoffset = entry * 4; 433 LDEBUGF("find_free_cluster(%x)\n",startcluster);
421 thisfatsecnum = fatoffset / fat_bpb.bpb_bytspersec + fat_bpb.bpb_rsvdseccnt;
422 thisfatentoffset = fatoffset % fat_bpb.bpb_bytspersec;
423 434
424 /* Load the sector if it is not cached */ 435 for (i = sector; i<fat_bpb.fatsize; i++) {
425 sec = cache_fat_sector(thisfatsecnum); 436 int j;
426 if(!sec) 437 unsigned int* fat = cache_fat_sector(i);
438 if ( !fat )
439 break;
440 for (j = offset; j < CLUSTERS_PER_FAT_SECTOR; j++)
441 if (!(SWAB32(fat[j]) & 0x0fffffff)) {
442 int c = i * CLUSTERS_PER_FAT_SECTOR + j;
443 LDEBUGF("Found free cluster %x\n",c);
444 fat_bpb.fsinfo.nextfree = c;
445 return c;
446 }
447 }
448 return 0; /* 0 is an illegal cluster number */
449}
450
451static int update_fat_entry(int entry, unsigned int val)
452{
453 int sector = entry / CLUSTERS_PER_FAT_SECTOR;
454 int offset = entry % CLUSTERS_PER_FAT_SECTOR;
455 unsigned int* sec;
456
457 LDEBUGF("update_fat_entry(%x,%x)\n",entry,val);
458
459 sec = cache_fat_sector(sector);
460 if (!sec)
427 { 461 {
428 DEBUGF( "update_entry() - Could not cache sector %d\n", 462 DEBUGF( "update_entry() - Could not cache sector %d\n", sector);
429 thisfatsecnum);
430 return -1; 463 return -1;
431 } 464 }
465 fat_cache[sector & FAT_CACHE_MASK].dirty = true;
432 466
433 /* We can safely assume that the correct sector is in the cache, 467 if ( val ) {
434 so we mark it dirty without checking the sector number */ 468 if (!(sec[offset] & 0x0fffffff))
435 fat_cache[thisfatsecnum & FAT_CACHE_MASK].dirty = 1; 469 fat_bpb.fsinfo.freecount--;
470 }
471 else
472 fat_bpb.fsinfo.freecount++;
436 473
437 /* don't change top 4 bits */ 474 /* don't change top 4 bits */
438 sec[thisfatentoffset/sizeof(int)] &= 0xf000000; 475 sec[offset] &= SWAB32(0xf000000);
439 sec[thisfatentoffset/sizeof(int)] |= val & 0x0fffffff; 476 sec[offset] |= SWAB32(val & 0x0fffffff);
440 477
441 return 0; 478 return 0;
442} 479}
443#endif
444 480
445static int read_entry(int entry) 481static int read_fat_entry(int entry)
446{ 482{
447 unsigned long *sec; 483 int sector = entry / CLUSTERS_PER_FAT_SECTOR;
448 int fatoffset; 484 int offset = entry % CLUSTERS_PER_FAT_SECTOR;
449 int thisfatsecnum; 485 unsigned int* sec;
450 int thisfatentoffset;
451 int val = -1;
452
453 fatoffset = entry * 4;
454 thisfatsecnum = fatoffset / fat_bpb.bpb_bytspersec + fat_bpb.bpb_rsvdseccnt;
455 thisfatentoffset = fatoffset % fat_bpb.bpb_bytspersec;
456 486
457 /* Load the sector if it is not cached */ 487 sec = cache_fat_sector(sector);
458 sec = cache_fat_sector(thisfatsecnum); 488 if (!sec)
459 if(!sec)
460 { 489 {
461 DEBUGF( "read_entry() - Could not cache sector %d\n", 490 DEBUGF( "read_fat_entry() - Could not cache sector %d\n", sector);
462 thisfatsecnum);
463 return -1; 491 return -1;
464 } 492 }
465 493
466 val = sec[thisfatentoffset/sizeof(int)]; 494 return SWAB32(sec[offset]);
467
468 val = SWAB32(val);
469
470 return val;
471} 495}
472 496
473static int get_next_cluster(unsigned int cluster) 497static int get_next_cluster(unsigned int cluster)
474{ 498{
475 int next_cluster; 499 int next_cluster;
476 500
477 next_cluster = read_entry(cluster); 501 next_cluster = read_fat_entry(cluster);
478 502
479 /* is this last cluster in chain? */ 503 /* is this last cluster in chain? */
480 if ( next_cluster >= 0x0ffffff8 ) 504 if ( next_cluster >= FAT_EOF_MARK )
481 return 0; 505 return 0;
482 else 506 else
483 return next_cluster; 507 return next_cluster;
484} 508}
485 509
486#ifdef DISK_WRITE 510static int flush_fat(void)
487static int flush_fat(struct bpb *bpb)
488{ 511{
489 int i; 512 int i;
490 int err; 513 int err;
491 unsigned char *sec; 514 unsigned char *sec;
492 int secnum; 515 int secnum;
493 int fatsz; 516 unsigned char fsinfo[SECTOR_SIZE];
494 unsigned short d, t; 517 unsigned int* intptr;
495 char m;
496 518
497 fatsz = fat_bpb.fatsize; 519 LDEBUGF("flush_fat()\n");
498 520
499 for(i = 0;i < FAT_CACHE_SIZE;i++) 521 for(i = 0;i < FAT_CACHE_SIZE;i++)
500 { 522 {
501 if(fat_cache[i].ptr && fat_cache[i].dirty) 523 if(fat_cache[i].inuse && fat_cache[i].dirty)
502 { 524 {
503 secnum = fat_cache[i].secnum + fat_bpb.bpb_rsvdseccnt + 525 secnum = fat_cache[i].secnum + fat_bpb.startsector;
504 fat_bpb.startsector; 526 LDEBUGF("Flushing FAT sector %x\n", secnum);
505 DEBUGF("Flushing FAT sector %d\n", secnum); 527 sec = fat_cache_sectors[i];
506 sec = fat_cache[i].ptr;
507 528
508 /* Write to the first FAT */ 529 /* Write to the first FAT */
509 err = ata_write_sectors(secnum, 1, sec); 530 err = ata_write_sectors(secnum, 1, sec);
@@ -514,19 +535,41 @@ static int flush_fat(struct bpb *bpb)
514 return -1; 535 return -1;
515 } 536 }
516 537
517 /* Write to the second FAT */ 538 if(fat_bpb.bpb_numfats > 1 )
518 err = ata_write_sectors(secnum + fatsz, 1, sec);
519 if(err)
520 { 539 {
521 DEBUGF( "flush_fat() - Couldn't write" 540 /* Write to the second FAT */
522 " sector (%d)\n", secnum + fatsz); 541 err = ata_write_sectors(secnum + fat_bpb.fatsize, 1, sec);
523 return -1; 542 if (err)
543 {
544 DEBUGF( "flush_fat() - Couldn't write"
545 " sector (%d)\n", secnum + fat_bpb.fatsize);
546 return -2;
547 }
524 } 548 }
525 fat_cache[i].dirty = 0; 549 fat_cache[i].dirty = false;
526 } 550 }
527 } 551 }
528 552
529 getcurrdostime(&d, &t, &m); 553 /* update fsinfo */
554 err = ata_read_sectors(fat_bpb.startsector + fat_bpb.bpb_fsinfo, 1,fsinfo);
555 if (err)
556 {
557 DEBUGF( "flush_fat() - Couldn't read FSInfo (error code %d)\n", err);
558 return -1;
559 }
560 intptr = (int*)&(fsinfo[FSINFO_FREECOUNT]);
561 *intptr = SWAB32(fat_bpb.fsinfo.freecount);
562
563 intptr = (int*)&(fsinfo[FSINFO_NEXTFREE]);
564 *intptr = SWAB32(fat_bpb.fsinfo.nextfree);
565
566 err = ata_write_sectors(fat_bpb.startsector + fat_bpb.bpb_fsinfo,1,fsinfo);
567 if (err)
568 {
569 DEBUGF( "flush_fat() - Couldn't write FSInfo (error code %d)\n", err);
570 return -1;
571 }
572
530 return 0; 573 return 0;
531} 574}
532 575
@@ -534,10 +577,9 @@ static unsigned int getcurrdostime(unsigned short *dosdate,
534 unsigned short *dostime, 577 unsigned short *dostime,
535 unsigned char *dostenth) 578 unsigned char *dostenth)
536{ 579{
537 struct timeb tb; 580#if 0
538 struct tm *tm; 581 struct tm *tm;
539 582 unsigned long now = time();
540 ftime(&tb);
541 tm = localtime(&tb.time); 583 tm = localtime(&tb.time);
542 584
543 *dosdate = ((tm->tm_year - 80) << 9) | 585 *dosdate = ((tm->tm_year - 80) << 9) |
@@ -549,102 +591,92 @@ static unsigned int getcurrdostime(unsigned short *dosdate,
549 (tm->tm_sec >> 1); 591 (tm->tm_sec >> 1);
550 592
551 *dostenth = (tm->tm_sec & 1) * 100 + tb.millitm / 10; 593 *dostenth = (tm->tm_sec & 1) * 100 + tb.millitm / 10;
594#else
595 *dosdate = 0;
596 *dostime = 0;
597 *dostenth = 0;
598#endif
552 return 0; 599 return 0;
553} 600}
554 601
555static int add_dir_entry(unsigned int currdir, struct fat_direntry *de) 602static int add_dir_entry(struct fat_dir* dir,
603 struct fat_direntry* de,
604 struct fat_file* file)
556{ 605{
557 unsigned char buf[SECTOR_SIZE]; 606 unsigned char buf[SECTOR_SIZE];
558 unsigned char *eptr; 607 unsigned char *eptr;
559 int i; 608 int i;
560 int err; 609 int err;
561 unsigned int sec; 610 int sec;
562 unsigned int sec_cnt; 611 int sec_cnt;
563 int need_to_update_last_empty_marker = 0; 612 bool need_to_update_last_empty_marker = false;
564 int is_rootdir = (currdir == 0); 613 bool done = false;
565 int done = 0;
566 unsigned char firstbyte; 614 unsigned char firstbyte;
615 int currdir = dir->startcluster;
616 bool is_rootdir = (currdir == 0);
567 617
568 if(is_rootdir) 618 LDEBUGF( "add_dir_entry()\n");
569 { 619
620 if (is_rootdir)
570 sec = fat_bpb.rootdirsector; 621 sec = fat_bpb.rootdirsector;
571 }
572 else 622 else
573 {
574 sec = first_sector_of_cluster(currdir); 623 sec = first_sector_of_cluster(currdir);
575 }
576 624
577 sec_cnt = 0; 625 sec_cnt = 0;
578 626
579 while(!done) 627 while(!done)
580 { 628 {
581 /* The root dir has a fixed size */ 629 if (sec_cnt >= fat_bpb.bpb_secperclus)
582 if(is_rootdir)
583 {
584 if(sec_cnt >= fat_bpb.bpb_rootentcnt * 32 / fat_bpb.bpb_bytspersec)
585 {
586 /* We have reached the last sector of the root dir */
587 if(need_to_update_last_empty_marker)
588 {
589 /* Since the directory is full, there is no room for
590 a marker, so we just exit */
591 return 0;
592 }
593 else
594 {
595 DEBUGF( "add_dir_entry() -"
596 " Root dir is full\n");
597 return -1;
598 }
599 }
600 }
601 else
602 { 630 {
603 if(sec_cnt >= fat_bpb.bpb_secperclus) 631 int oldcluster = currdir;
632 /* We have reached the end of this cluster */
633 LDEBUGF("Moving to the next cluster...");
634 currdir = get_next_cluster(currdir);
635 LDEBUGF("new cluster is %d\n", currdir);
636
637 if (!currdir)
604 { 638 {
605 /* We have reached the end of this cluster */ 639 currdir = find_free_cluster(fat_bpb.fsinfo.nextfree);
606 DEBUGF("Moving to the next cluster..."); 640 if (!currdir) {
607 currdir = get_next_cluster(currdir); 641 currdir = find_free_cluster(0);
608 DEBUGF("new cluster is %d\n", currdir); 642 if (!currdir) {
609 643 DEBUGF("add_dir_entry(): Disk full!\n");
610 if(!currdir) 644 return -1;
611 { 645 }
612 /* This was the last in the chain,
613 we have to allocate a new cluster */
614 /* TODO */
615 } 646 }
647 update_fat_entry(oldcluster, currdir);
616 } 648 }
617 } 649 }
618 650
619 DEBUGF("Reading sector %d...\n", sec); 651 LDEBUGF("Reading sector %d...\n", sec);
620 /* Read the next sector in the current dir */ 652 /* Read the next sector in the current dir */
621 err = ata_read_sectors(sec + fat_bpb.startsector,1,buf); 653 err = ata_read_sectors(sec + fat_bpb.startsector,1,buf);
622 if(err) 654 if (err)
623 { 655 {
624 DEBUGF( "add_dir_entry() - Couldn't read dir sector" 656 DEBUGF( "add_dir_entry() - Couldn't read dir sector"
625 " (error code %d)\n", err); 657 " (error code %d)\n", err);
626 return -1; 658 return -2;
627 } 659 }
628 660
629 if(need_to_update_last_empty_marker) 661 if (need_to_update_last_empty_marker)
630 { 662 {
631 /* All we need to do is to set the first entry to 0 */ 663 /* All we need to do is to set the first entry to 0 */
632 DEBUGF("Clearing the first entry in sector %d\n", sec); 664 LDEBUGF("Clearing the first entry in sector %x\n", sec);
633 buf[0] = 0; 665 buf[0] = 0;
634 done = 1; 666 done = true;
635 } 667 }
636 else 668 else
637 { 669 {
638 /* Look for a free slot */ 670 /* Look for a free slot */
639 for(i = 0;i < SECTOR_SIZE;i+=32) 671 for (i = 0; i < SECTOR_SIZE; i += DIR_ENTRY_SIZE)
640 { 672 {
641 firstbyte = buf[i]; 673 firstbyte = buf[i];
642 if(firstbyte == 0xe5 || firstbyte == 0) 674 if (firstbyte == 0xe5 || firstbyte == 0)
643 { 675 {
644 DEBUGF("Found free slot at entry %d in sector %d\n", 676 LDEBUGF("Found free slot at entry %d in sector %x\n",
645 i/32, sec); 677 i/DIR_ENTRY_SIZE, sec);
646 eptr = &buf[i]; 678 eptr = &buf[i];
647 memset(eptr, 0, 32); 679 memset(eptr, 0, DIR_ENTRY_SIZE);
648 strncpy(&eptr[FATDIR_NAME], de->name, 11); 680 strncpy(&eptr[FATDIR_NAME], de->name, 11);
649 eptr[FATDIR_ATTR] = de->attr; 681 eptr[FATDIR_ATTR] = de->attr;
650 eptr[FATDIR_NTRES] = 0; 682 eptr[FATDIR_NTRES] = 0;
@@ -665,31 +697,37 @@ static int add_dir_entry(unsigned int currdir, struct fat_direntry *de)
665 eptr[FATDIR_FILESIZE+2] = (de->filesize >> 16) & 0xff; 697 eptr[FATDIR_FILESIZE+2] = (de->filesize >> 16) & 0xff;
666 eptr[FATDIR_FILESIZE+3] = (de->filesize >> 24) & 0xff; 698 eptr[FATDIR_FILESIZE+3] = (de->filesize >> 24) & 0xff;
667 699
700 /* remember where the dir entry is located */
701 file->dirsector = sec;
702 file->direntry = i/DIR_ENTRY_SIZE;
703
668 /* Advance the last_empty_entry marker */ 704 /* Advance the last_empty_entry marker */
669 if(firstbyte == 0) 705 if (firstbyte == 0)
670 { 706 {
671 i += 32; 707 i += DIR_ENTRY_SIZE;
672 if(i < SECTOR_SIZE) 708 if (i < SECTOR_SIZE)
673 { 709 {
674 buf[i] = 0; 710 buf[i] = 0;
675 /* We are done */ 711 /* We are done */
676 done = 1; 712 done = true;
677 } 713 }
678 else 714 else
679 { 715 {
680 /* We must fill in the first entry 716 /* We must fill in the first entry
681 in the next sector */ 717 in the next sector */
682 need_to_update_last_empty_marker = 1; 718 need_to_update_last_empty_marker = true;
683 } 719 }
684 } 720 }
721 else
722 done = true;
685 723
686 err = ata_write_sectors(sec + fat_bpb.startsector,1,buf); 724 err = ata_write_sectors(sec + fat_bpb.startsector,1,buf);
687 if(err) 725 if (err)
688 { 726 {
689 DEBUGF( "add_dir_entry() - " 727 DEBUGF( "add_dir_entry() - "
690 " Couldn't write dir" 728 " Couldn't write dir"
691 " sector (error code %d)\n", err); 729 " sector (error code %d)\n", err);
692 return -1; 730 return -3;
693 } 731 }
694 break; 732 break;
695 } 733 }
@@ -746,11 +784,6 @@ static int create_dos_name(unsigned char *name, unsigned char *newname)
746 int i; 784 int i;
747 char *ext; 785 char *ext;
748 786
749 if(strlen(name) > 12)
750 {
751 return -1;
752 }
753
754 strcpy(n, name); 787 strcpy(n, name);
755 788
756 ext = strchr(n, '.'); 789 ext = strchr(n, '.');
@@ -763,7 +796,7 @@ static int create_dos_name(unsigned char *name, unsigned char *newname)
763 In either case it is illegal. */ 796 In either case it is illegal. */
764 if(n[0] == 0) 797 if(n[0] == 0)
765 { 798 {
766 return -1; 799 return -2;
767 } 800 }
768 801
769 /* Name part */ 802 /* Name part */
@@ -781,10 +814,10 @@ static int create_dos_name(unsigned char *name, unsigned char *newname)
781 } 814 }
782 815
783 /* Extension part */ 816 /* Extension part */
784 for(i = 0;ext && ext[i] && (i < 3);i++) 817 for (i = 0;ext && ext[i] && (i < 3);i++)
785 { 818 {
786 c = char2dos(ext[i]); 819 c = char2dos(ext[i]);
787 if(c) 820 if (c)
788 { 821 {
789 newname[8+i] = toupper(c); 822 newname[8+i] = toupper(c);
790 } 823 }
@@ -796,50 +829,48 @@ static int create_dos_name(unsigned char *name, unsigned char *newname)
796 return 0; 829 return 0;
797} 830}
798 831
799int fat_create_dir(unsigned int currdir, char *name) 832static void update_dir_entry( struct fat_file* file, int size )
800{ 833{
801 struct fat_direntry de; 834 unsigned char buf[SECTOR_SIZE];
835 int sector = file->dirsector + fat_bpb.startsector;
836 unsigned char* entry = buf + file->direntry * DIR_ENTRY_SIZE;
837 unsigned int* sizeptr;
838 unsigned short* clusptr;
802 int err; 839 int err;
803 840
804 DEBUGF("fat_create_file()\n"); 841 LDEBUGF("update_dir_entry(cluster:%x entry:%d size:%d)\n",
805 memset(&de, 0, sizeof(struct fat_direntry)); 842 file->firstcluster,file->direntry,size);
806 if(create_dos_name(name, de.name) < 0) 843
844 if ( file->direntry >= (SECTOR_SIZE / DIR_ENTRY_SIZE) ) {
845 DEBUGF("update_dir_entry(): Illegal entry %d!\n",file->direntry);
846 return;
847 }
848
849 err = ata_read_sectors(sector, 1, buf);
850 if (err)
807 { 851 {
808 DEBUGF( "fat_create_file() - Illegal file name (%s)\n", name); 852 DEBUGF( "update_dir_entry() - Couldn't read dir sector %d"
809 return -1; 853 " (error code %d)\n", sector, err);
854 return;
810 } 855 }
856
857 clusptr = (short*)(entry + FATDIR_FSTCLUSHI);
858 *clusptr = SWAB16(file->firstcluster >> 16);
811 859
812 getcurrdostime(&de.crtdate, &de.crttime, &de.crttimetenth); 860 clusptr = (short*)(entry + FATDIR_FSTCLUSLO);
813 de.wrtdate = de.crtdate; 861 *clusptr = SWAB16(file->firstcluster & 0xffff);
814 de.wrttime = de.crttime;
815 de.filesize = 0;
816 de.attr = FAT_ATTR_DIRECTORY;
817
818 err = add_dir_entry(currdir, &de);
819 return 0;
820}
821 862
822int fat_create_file(unsigned int currdir, char *name) 863 sizeptr = (int*)(entry + FATDIR_FILESIZE);
823{ 864 *sizeptr = SWAB32(size);
824 struct fat_direntry de;
825 int err;
826 865
827 DEBUGF("fat_create_file()\n"); 866 err = ata_write_sectors(sector, 1, buf);
828 memset(&de, 0, sizeof(struct fat_direntry)); 867 if (err)
829 if(create_dos_name(name, de.name) < 0)
830 { 868 {
831 DEBUGF( "fat_create_file() - Illegal file name (%s)\n", name); 869 DEBUGF( "update_file_size() - Couldn't write dir sector %d"
832 return -1; 870 " (error code %d)\n", sector, err);
871 return;
833 } 872 }
834 getcurrdostime(&de.crtdate, &de.crttime, &de.crttimetenth);
835 de.wrtdate = de.crtdate;
836 de.wrttime = de.crttime;
837 de.filesize = 0;
838
839 err = add_dir_entry(currdir, &de);
840 return err;
841} 873}
842#endif
843 874
844static int parse_direntry(struct fat_direntry *de, unsigned char *buf) 875static int parse_direntry(struct fat_direntry *de, unsigned char *buf)
845{ 876{
@@ -866,37 +897,138 @@ static int parse_direntry(struct fat_direntry *de, unsigned char *buf)
866 return 1; 897 return 1;
867} 898}
868 899
869int fat_open( unsigned int startcluster, struct fat_file *file) 900int fat_open(unsigned int startcluster,
901 struct fat_file *file,
902 struct fat_dir* dir)
870{ 903{
871 file->firstcluster = startcluster; 904 file->firstcluster = startcluster;
872 file->nextcluster = startcluster; 905 file->nextcluster = startcluster;
873 file->nextsector = cluster2sec(startcluster); 906 file->nextsector = cluster2sec(startcluster);
874 file->sectornum = 0; 907 file->sectornum = 0;
908
909 /* remember where the file's dir entry is located */
910 file->dirsector = dir->cached_sec;
911 file->direntry = (dir->entry % DIR_ENTRIES_PER_SECTOR) - 1;
912 LDEBUGF("fat_open: entry %d\n",file->direntry);
913 return 0;
914}
915
916int fat_create_file(char* name,
917 struct fat_file* file,
918 struct fat_dir* dir)
919{
920 struct fat_direntry de;
921 int err;
922
923 LDEBUGF("fat_create_file(\"%s\",%x,%x)\n",name,file,dir);
924 memset(&de, 0, sizeof(struct fat_direntry));
925 if (create_dos_name(name, de.name) < 0)
926 {
927 DEBUGF( "fat_create_file() - Illegal file name (%s)\n", name);
928 return -1;
929 }
930 getcurrdostime(&de.crtdate, &de.crttime, &de.crttimetenth);
931 de.wrtdate = de.crtdate;
932 de.wrttime = de.crttime;
933 de.filesize = 0;
934
935 err = add_dir_entry(dir, &de, file);
936 if (!err) {
937 file->firstcluster = 0;
938 file->nextcluster = 0;
939 file->nextsector = 0;
940 file->sectornum = 0;
941 }
942
943 return err;
944}
945
946int fat_closewrite(struct fat_file *file, int size)
947{
948 int endcluster = file->nextcluster;
949 int next, last = endcluster;
950
951 /* free unused clusters, if any */
952 for ( next = get_next_cluster(last); next; last = next ) {
953 LDEBUGF("Clearing cluster %x\n",last);
954 update_fat_entry(last,0);
955 }
956
957 /* mark last used cluster as last in chain */
958 update_fat_entry(endcluster, FAT_EOF_MARK);
959
960 flush_fat();
961
962 update_dir_entry(file, size);
963
875 return 0; 964 return 0;
876} 965}
877 966
878int fat_read( struct fat_file *file, int sectorcount, void* buf ) 967int fat_readwrite( struct fat_file *file, int sectorcount,
968 void* buf, bool write )
879{ 969{
880 int cluster = file->nextcluster; 970 int cluster = file->nextcluster;
881 int sector = file->nextsector; 971 int sector = file->nextsector;
882 int numsec = file->sectornum; 972 int numsec = file->sectornum;
883 int first = sector, last = sector; 973 int first, last;
884 int err, i; 974 int err, i;
885 975
976 LDEBUGF( "fat_readwrite(file:%x,count:%d,buf:%x,%s)\n",
977 cluster,sectorcount,buf,write?"write":"read");
978
886 if ( sector == -1 ) 979 if ( sector == -1 )
887 return 0; 980 return 0;
888 981
889 /* find sequential sectors and read them all at once */ 982 if ( write && !cluster) {
983 /* new file */
984 cluster = find_free_cluster(fat_bpb.fsinfo.nextfree);
985 if (!cluster) {
986 cluster = find_free_cluster(0);
987 if (!cluster) {
988 DEBUGF("fat_readwrite(): Disk full!\n");
989 return -3;
990 }
991 }
992 file->firstcluster = cluster;
993 sector = cluster2sec(cluster);
994 if (sector<0)
995 return -1;
996 }
997
998 first = sector;
999 last = sector;
1000
1001 /* find sequential sectors and read/write them all at once */
890 for (i=0; i<sectorcount && sector>=0; i++ ) { 1002 for (i=0; i<sectorcount && sector>=0; i++ ) {
891 numsec++; 1003 numsec++;
892 if ( numsec >= fat_bpb.bpb_secperclus ) { 1004 if ( numsec >= fat_bpb.bpb_secperclus ) {
1005 int oldcluster = cluster;
893 cluster = get_next_cluster(cluster); 1006 cluster = get_next_cluster(cluster);
894 if (!cluster) { 1007 if (!cluster) {
895 /* end of file */ 1008 if ( write ) {
896 sector = -1; 1009 /* writing past end-of-file,
1010 find a new free cluster to use. */
1011 cluster = find_free_cluster(cluster);
1012 if (!cluster) {
1013 /* no cluster found after last,
1014 search from beginning */
1015 cluster = find_free_cluster(0);
1016 if (!cluster) {
1017 /* no free clusters. disk is full. */
1018 sector = -1;
1019 DEBUGF("fat_readwrite(): Disk full!\n");
1020 }
1021 }
1022 if ( cluster )
1023 update_fat_entry(oldcluster, cluster);
1024 }
1025 else {
1026 /* reading past end-of-file */
1027 sector = -1;
1028 }
897 } 1029 }
898 else 1030
899 { 1031 if (cluster) {
900 sector = cluster2sec(cluster); 1032 sector = cluster2sec(cluster);
901 if (sector<0) 1033 if (sector<0)
902 return -1; 1034 return -1;
@@ -910,11 +1042,14 @@ int fat_read( struct fat_file *file, int sectorcount, void* buf )
910 (i == sectorcount-1) || /* last sector requested? */ 1042 (i == sectorcount-1) || /* last sector requested? */
911 (last-first+1 == 256) ) { /* max 256 sectors per ata request */ 1043 (last-first+1 == 256) ) { /* max 256 sectors per ata request */
912 int count = last-first+1; 1044 int count = last-first+1;
913 err = ata_read_sectors(first + fat_bpb.startsector, count, buf); 1045 if (write)
914 if(err) { 1046 err = ata_write_sectors(first + fat_bpb.startsector, count, buf);
915 DEBUGF( "fat_read() - Couldn't read sector %d" 1047 else
1048 err = ata_read_sectors(first + fat_bpb.startsector, count, buf);
1049 if (err) {
1050 DEBUGF( "fat_readwrite() - Couldn't read sector %d"
916 " (error code %d)\n", sector,err); 1051 " (error code %d)\n", sector,err);
917 return -1; 1052 return -2;
918 } 1053 }
919 ((char*)buf) += count * SECTOR_SIZE; 1054 ((char*)buf) += count * SECTOR_SIZE;
920 first = sector; 1055 first = sector;
@@ -970,9 +1105,9 @@ int fat_seek(struct fat_file *file, int seeksector )
970 return 0; 1105 return 0;
971} 1106}
972 1107
973int fat_opendir(struct fat_dir *dir, unsigned int currdir) 1108int fat_opendir(struct fat_dir *dir, unsigned int startcluster)
974{ 1109{
975 int is_rootdir = (currdir == 0); 1110 int is_rootdir = (startcluster == 0);
976 unsigned int sec; 1111 unsigned int sec;
977 int err; 1112 int err;
978 1113
@@ -982,7 +1117,7 @@ int fat_opendir(struct fat_dir *dir, unsigned int currdir)
982 } 1117 }
983 else 1118 else
984 { 1119 {
985 sec = first_sector_of_cluster(currdir); 1120 sec = first_sector_of_cluster(startcluster);
986 } 1121 }
987 1122
988 /* Read the first sector in the current dir */ 1123 /* Read the first sector in the current dir */
@@ -997,13 +1132,14 @@ int fat_opendir(struct fat_dir *dir, unsigned int currdir)
997 dir->entry = 0; 1132 dir->entry = 0;
998 dir->cached_sec = sec; 1133 dir->cached_sec = sec;
999 dir->num_sec = 0; 1134 dir->num_sec = 0;
1135 dir->startcluster = startcluster;
1000 1136
1001 return 0; 1137 return 0;
1002} 1138}
1003 1139
1004int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry) 1140int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry)
1005{ 1141{
1006 int done = 0; 1142 bool done = false;
1007 int i; 1143 int i;
1008 int err; 1144 int err;
1009 unsigned char firstbyte; 1145 unsigned char firstbyte;
@@ -1013,29 +1149,30 @@ int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry)
1013 1149
1014 while(!done) 1150 while(!done)
1015 { 1151 {
1016 for(i = dir->entry;i < SECTOR_SIZE/32;i++) 1152 for (i = dir->entry; i < SECTOR_SIZE/DIR_ENTRY_SIZE; i++)
1017 { 1153 {
1018 firstbyte = dir->cached_buf[i*32]; 1154 firstbyte = dir->cached_buf[i*DIR_ENTRY_SIZE];
1019 1155
1020 if(firstbyte == 0xe5) { 1156 if (firstbyte == 0xe5) {
1021 /* free entry */ 1157 /* free entry */
1022 sectoridx = 0; 1158 sectoridx = 0;
1023 continue; 1159 continue;
1024 } 1160 }
1025 1161
1026 if(firstbyte == 0) { 1162 if (firstbyte == 0) {
1027 /* last entry */ 1163 /* last entry */
1028 entry->name[0] = 0; 1164 entry->name[0] = 0;
1029 return 0; 1165 return 0;
1030 } 1166 }
1031 1167
1032 /* longname entry? */ 1168 /* longname entry? */
1033 if ( ( dir->cached_buf[i*32 + FATDIR_ATTR] & 1169 if ( ( dir->cached_buf[i*DIR_ENTRY_SIZE + FATDIR_ATTR] &
1034 FAT_ATTR_LONG_NAME_MASK ) == FAT_ATTR_LONG_NAME ) { 1170 FAT_ATTR_LONG_NAME_MASK ) == FAT_ATTR_LONG_NAME ) {
1035 longarray[longs++] = i*32 + sectoridx; 1171 longarray[longs++] = i*DIR_ENTRY_SIZE + sectoridx;
1036 } 1172 }
1037 else { 1173 else {
1038 if ( parse_direntry(entry, &dir->cached_buf[i*32]) ) { 1174 if ( parse_direntry(entry,
1175 &dir->cached_buf[i*DIR_ENTRY_SIZE]) ) {
1039 1176
1040 /* don't return volume id entry */ 1177 /* don't return volume id entry */
1041 if ( entry->attr == FAT_ATTR_VOLUME_ID ) 1178 if ( entry->attr == FAT_ATTR_VOLUME_ID )
@@ -1076,7 +1213,7 @@ int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry)
1076 } 1213 }
1077 entry->name[l]=0; 1214 entry->name[l]=0;
1078 } 1215 }
1079 done = 1; 1216 done = true;
1080 sectoridx = 0; 1217 sectoridx = 0;
1081 break; 1218 break;
1082 } 1219 }
@@ -1091,7 +1228,7 @@ int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry)
1091 sectoridx += SECTOR_SIZE; 1228 sectoridx += SECTOR_SIZE;
1092 1229
1093 /* Next sector? */ 1230 /* Next sector? */
1094 if(i < SECTOR_SIZE/32) 1231 if (i < SECTOR_SIZE / DIR_ENTRY_SIZE)
1095 { 1232 {
1096 i++; 1233 i++;
1097 } 1234 }
@@ -1100,7 +1237,7 @@ int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry)
1100 dir->num_sec++; 1237 dir->num_sec++;
1101 1238
1102 /* Do we need to advance one cluster? */ 1239 /* Do we need to advance one cluster? */
1103 if(dir->num_sec < fat_bpb.bpb_secperclus) 1240 if (dir->num_sec < fat_bpb.bpb_secperclus)
1104 { 1241 {
1105 dir->cached_sec++; 1242 dir->cached_sec++;
1106 } 1243 }
@@ -1113,16 +1250,16 @@ int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry)
1113 } 1250 }
1114 dir->num_sec = 0; 1251 dir->num_sec = 0;
1115 cluster = get_next_cluster( cluster ); 1252 cluster = get_next_cluster( cluster );
1116 if(!cluster) 1253 if (!cluster)
1117 { 1254 {
1118 DEBUGF("End of cluster chain.\n"); 1255 DEBUGF("End of cluster chain.\n");
1119 return -1; 1256 return -2;
1120 } 1257 }
1121 dir->cached_sec = cluster2sec(cluster); 1258 dir->cached_sec = cluster2sec(cluster);
1122 if ( dir->cached_sec < 0 ) 1259 if ( dir->cached_sec < 0 )
1123 { 1260 {
1124 DEBUGF("Invalid cluster: %d\n",cluster); 1261 DEBUGF("Invalid cluster: %d\n",cluster);
1125 return -1; 1262 return -3;
1126 } 1263 }
1127 1264
1128 } 1265 }
@@ -1130,11 +1267,11 @@ int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry)
1130 /* Read the next sector */ 1267 /* Read the next sector */
1131 err = ata_read_sectors(dir->cached_sec + fat_bpb.startsector, 1, 1268 err = ata_read_sectors(dir->cached_sec + fat_bpb.startsector, 1,
1132 dir->cached_buf); 1269 dir->cached_buf);
1133 if(err) 1270 if (err)
1134 { 1271 {
1135 DEBUGF( "fat_getnext() - Couldn't read dir sector" 1272 DEBUGF( "fat_getnext() - Couldn't read dir sector"
1136 " (error code %d)\n", err); 1273 " (error code %d)\n", err);
1137 return -1; 1274 return -4;
1138 } 1275 }
1139 1276
1140 i = 0; 1277 i = 0;
diff --git a/firmware/drivers/fat.h b/firmware/drivers/fat.h
index 836d5c6866..3052488c5a 100644
--- a/firmware/drivers/fat.h
+++ b/firmware/drivers/fat.h
@@ -20,6 +20,8 @@
20#ifndef FAT_H 20#ifndef FAT_H
21#define FAT_H 21#define FAT_H
22 22
23#include <stdbool.h>
24
23#define SECTOR_SIZE 512 25#define SECTOR_SIZE 512
24 26
25struct fat_direntry 27struct fat_direntry
@@ -50,6 +52,7 @@ struct fat_dir
50 int cached_sec; 52 int cached_sec;
51 int num_sec; 53 int num_sec;
52 unsigned char cached_buf[SECTOR_SIZE]; 54 unsigned char cached_buf[SECTOR_SIZE];
55 int startcluster;
53}; 56};
54 57
55struct fat_file 58struct fat_file
@@ -58,17 +61,23 @@ struct fat_file
58 int nextcluster; /* cluster of last access */ 61 int nextcluster; /* cluster of last access */
59 int nextsector; /* sector of last access */ 62 int nextsector; /* sector of last access */
60 int sectornum; /* sector number in this cluster */ 63 int sectornum; /* sector number in this cluster */
64 int dirsector; /* sector where the dir entry is located */
65 int direntry; /* dir entry index in sector */
61}; 66};
62 67
63extern int fat_mount(int startsector); 68extern int fat_mount(int startsector);
64 69
65#ifdef DISK_WRITE
66extern int fat_create_file(unsigned int currdir, char *name);
67extern int fat_create_dir(unsigned int currdir, char *name); 70extern int fat_create_dir(unsigned int currdir, char *name);
68#endif
69extern int fat_startsector(void); 71extern int fat_startsector(void);
70extern int fat_open(unsigned int cluster, struct fat_file *ent); 72extern int fat_open(unsigned int cluster,
71extern int fat_read(struct fat_file *ent, int sectorcount, void* buf ); 73 struct fat_file* ent,
74 struct fat_dir* dir);
75extern int fat_create_file(char* name,
76 struct fat_file* ent,
77 struct fat_dir* dir);
78extern int fat_readwrite(struct fat_file *ent, int sectorcount,
79 void* buf, bool write );
80extern int fat_closewrite(struct fat_file *ent, int size);
72extern int fat_seek(struct fat_file *ent, int sector ); 81extern int fat_seek(struct fat_file *ent, int sector );
73 82
74extern int fat_opendir(struct fat_dir *ent, unsigned int currdir); 83extern int fat_opendir(struct fat_dir *ent, unsigned int currdir);
diff --git a/firmware/test/fat/README b/firmware/test/fat/README
new file mode 100644
index 0000000000..76141c0044
--- /dev/null
+++ b/firmware/test/fat/README
@@ -0,0 +1,25 @@
1This code is for testing the Rockbox fat code on a dummy drive image file.
2
3Dummy image
4-----------
5Here's how to create a 1 gig dummy drive image in linux:
6
7# dd if=/dev/hda of=disk.img bs=1M count=1024
8
9You can then format disk.img as a FAT32 partition:
10
11# mkdosfs -F 32 disk.img
12
13To mount the image, your linux kernel must include the loopback device:
14
15# mount -o loop disk.img /mnt/image
16
17Now copy some test data to the disk, umount it and start testing.
18
19
20Test code
21---------
22The files in this dir build the 'fat' program. It will read 'disk.img' and
23treat is as a real disk, thanks to the ata-sim.c module.
24
25Modify the main.c source code to make it perform the tests you want.
diff --git a/firmware/test/fat/ata-sim.c b/firmware/test/fat/ata-sim.c
index ab7266d6a0..a37fabcfc0 100644
--- a/firmware/test/fat/ata-sim.c
+++ b/firmware/test/fat/ata-sim.c
@@ -24,6 +24,13 @@ int ata_read_sectors(unsigned long start, unsigned char count, void* buf)
24 24
25int ata_write_sectors(unsigned long start, unsigned char count, void* buf) 25int ata_write_sectors(unsigned long start, unsigned char count, void* buf)
26{ 26{
27 DEBUGF("Writing block 0x%lx\n",start);
28
29 if (start == 0) {
30 DEBUGF("Holy crap! You're writing on sector 0!\n");
31 exit(0);
32 }
33
27 if(fseek(file,start*BLOCK_SIZE,SEEK_SET)) { 34 if(fseek(file,start*BLOCK_SIZE,SEEK_SET)) {
28 perror("fseek"); 35 perror("fseek");
29 return -1; 36 return -1;
diff --git a/firmware/test/fat/main.c b/firmware/test/fat/main.c
index 4a11e0a08a..1b9fd22183 100644
--- a/firmware/test/fat/main.c
+++ b/firmware/test/fat/main.c
@@ -1,6 +1,7 @@
1#include <stdio.h> 1#include <stdio.h>
2#include <stdlib.h> 2#include <stdlib.h>
3#include <string.h> 3#include <string.h>
4#include <stdarg.h>
4#include "fat.h" 5#include "fat.h"
5#include "debug.h" 6#include "debug.h"
6#include "disk.h" 7#include "disk.h"
@@ -14,6 +15,15 @@ void dbg_dump_sector(int sec);
14void dbg_dump_buffer(unsigned char *buf); 15void dbg_dump_buffer(unsigned char *buf);
15void dbg_console(void); 16void dbg_console(void);
16 17
18void panicf( char *fmt, ...)
19{
20 va_list ap;
21 va_start( ap, fmt );
22 vprintf( fmt, ap );
23 va_end( ap );
24 exit(0);
25}
26
17void dbg_dump_sector(int sec) 27void dbg_dump_sector(int sec)
18{ 28{
19 unsigned char buf[512]; 29 unsigned char buf[512];
@@ -75,14 +85,16 @@ void dbg_dir(char* currdir)
75void dbg_mkfile(char* name) 85void dbg_mkfile(char* name)
76{ 86{
77 char* text = "Detta är en dummy-text\n"; 87 char* text = "Detta är en dummy-text\n";
88 int i;
78 int fd = open(name,O_WRONLY); 89 int fd = open(name,O_WRONLY);
79 if (fd<0) { 90 if (fd<0) {
80 DEBUGF("Failed creating file\n"); 91 DEBUGF("Failed creating file\n");
81 return; 92 return;
82 } 93 }
83 if (write(fd, text, strlen(text)) < 0) 94 for (i=0;i<200;i++)
84 DEBUGF("Failed writing data\n"); 95 if (write(fd, text, strlen(text)) < 0)
85 96 DEBUGF("Failed writing data\n");
97
86 close(fd); 98 close(fd);
87} 99}
88 100
@@ -168,6 +180,33 @@ void dbg_tail(char* name)
168 close(fd); 180 close(fd);
169} 181}
170 182
183void dbg_head(char* name)
184{
185 unsigned char buf[SECTOR_SIZE*5];
186 int fd,rc;
187
188 fd = open(name,O_RDONLY);
189 if (fd<0)
190 return;
191 DEBUGF("Got file descriptor %d\n",fd);
192
193 rc = read(fd, buf, SECTOR_SIZE);
194 if( rc > 0 )
195 {
196 buf[rc]=0;
197 printf("%d: %s\n", strlen(buf), buf);
198 }
199 else if ( rc == 0 ) {
200 DEBUGF("EOF\n");
201 }
202 else
203 {
204 DEBUGF("Failed reading file: %d\n",rc);
205 }
206
207 close(fd);
208}
209
171char current_directory[256] = "\\"; 210char current_directory[256] = "\\";
172int last_secnum = 0; 211int last_secnum = 0;
173 212
@@ -284,9 +323,12 @@ int main(int argc, char *argv[])
284 } 323 }
285 324
286 //dbg_console(); 325 //dbg_console();
287 //dbg_tail("/fat.h");
288 //dbg_dir("/"); 326 //dbg_dir("/");
289 dbg_mkfile("/apa.txt"); 327#if 1
328 dbg_head("/bepa.txt");
329#else
330 dbg_mkfile("/bepa.txt");
331#endif
290 dbg_dir("/"); 332 dbg_dir("/");
291 333
292 return 0; 334 return 0;