summaryrefslogtreecommitdiff
path: root/firmware/drivers/fat.c
diff options
context:
space:
mode:
authorBjörn Stenberg <bjorn@haxx.se>2002-10-20 22:50:58 +0000
committerBjörn Stenberg <bjorn@haxx.se>2002-10-20 22:50:58 +0000
commitb7b48fea02fdac51071eef084a980cee4bcba221 (patch)
treeca2e1f55fd67cda98b395eb0259d14426865af4f /firmware/drivers/fat.c
parent1df1e51a030e3a7c87f7e882f67b3c7588353300 (diff)
downloadrockbox-b7b48fea02fdac51071eef084a980cee4bcba221.tar.gz
rockbox-b7b48fea02fdac51071eef084a980cee4bcba221.zip
Snapshot of file writing code. Bugs remain. Only short names are supported yet.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@2726 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/drivers/fat.c')
-rw-r--r--firmware/drivers/fat.c585
1 files changed, 361 insertions, 224 deletions
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;