summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/drivers/fat.c124
-rw-r--r--firmware/export/fat.h8
2 files changed, 46 insertions, 86 deletions
diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c
index b4b256c142..81e12fd0b4 100644
--- a/firmware/drivers/fat.c
+++ b/firmware/drivers/fat.c
@@ -217,7 +217,8 @@ struct bpb
217 int bpb_rootentcnt; /* Number of dir entries in the root */ 217 int bpb_rootentcnt; /* Number of dir entries in the root */
218 /* internals for FAT16 support */ 218 /* internals for FAT16 support */
219 bool is_fat16; /* true if we mounted a FAT16 partition, false if FAT32 */ 219 bool is_fat16; /* true if we mounted a FAT16 partition, false if FAT32 */
220 unsigned int rootdirsectors; /* fixed # of sectors occupied by root dir */ 220 unsigned int rootdiroffset; /* sector offset of root dir relative to start
221 * of first pseudo cluster */
221#endif /* #ifdef HAVE_FAT16SUPPORT */ 222#endif /* #ifdef HAVE_FAT16SUPPORT */
222#ifdef HAVE_MULTIVOLUME 223#ifdef HAVE_MULTIVOLUME
223 int drive; /* on which physical device is this located */ 224 int drive; /* on which physical device is this located */
@@ -229,7 +230,6 @@ static struct bpb fat_bpbs[NUM_VOLUMES]; /* mounted partition info */
229 230
230static int update_fsinfo(IF_MV_NONVOID(struct bpb* fat_bpb)); 231static int update_fsinfo(IF_MV_NONVOID(struct bpb* fat_bpb));
231static int bpb_is_sane(IF_MV_NONVOID(struct bpb* fat_bpb)); 232static int bpb_is_sane(IF_MV_NONVOID(struct bpb* fat_bpb));
232static int first_sector_of_cluster(IF_MV2(struct bpb* fat_bpb,) int cluster);
233static void *cache_fat_sector(IF_MV2(struct bpb* fat_bpb,) int secnum); 233static void *cache_fat_sector(IF_MV2(struct bpb* fat_bpb,) int secnum);
234static int create_dos_name(const unsigned char *name, unsigned char *newname); 234static int create_dos_name(const unsigned char *name, unsigned char *newname);
235static unsigned int find_free_cluster(IF_MV2(struct bpb* fat_bpb,) unsigned int start); 235static unsigned int find_free_cluster(IF_MV2(struct bpb* fat_bpb,) unsigned int start);
@@ -251,50 +251,28 @@ struct fat_cache_entry
251static char fat_cache_sectors[FAT_CACHE_SIZE][SECTOR_SIZE]; 251static char fat_cache_sectors[FAT_CACHE_SIZE][SECTOR_SIZE];
252static struct fat_cache_entry fat_cache[FAT_CACHE_SIZE]; 252static struct fat_cache_entry fat_cache[FAT_CACHE_SIZE];
253 253
254static int sec2cluster(IF_MV2(struct bpb* fat_bpb,) unsigned int sec)
255{
256#ifndef HAVE_MULTIVOLUME
257 struct bpb* fat_bpb = &fat_bpbs[0];
258#endif
259 if ( sec < fat_bpb->firstdatasector )
260 {
261 DEBUGF( "sec2cluster() - Bad sector number (%d)\n", sec);
262 return -1;
263 }
264
265 return ((sec - fat_bpb->firstdatasector) / fat_bpb->bpb_secperclus) + 2;
266}
267
268static int cluster2sec(IF_MV2(struct bpb* fat_bpb,) int cluster) 254static int cluster2sec(IF_MV2(struct bpb* fat_bpb,) int cluster)
269{ 255{
270#ifndef HAVE_MULTIVOLUME 256#ifndef HAVE_MULTIVOLUME
271 struct bpb* fat_bpb = &fat_bpbs[0]; 257 struct bpb* fat_bpb = &fat_bpbs[0];
272#endif 258#endif
259#ifdef HAVE_FAT16SUPPORT
260 /* negative clusters (FAT16 root dir) don't get the 2 offset */
261 int zerocluster = cluster < 0 ? 0 : 2;
262#else
263 const int zerocluster = 2;
264#endif
273 int max_cluster = fat_bpb->totalsectors - 265 int max_cluster = fat_bpb->totalsectors -
274 fat_bpb->firstdatasector / fat_bpb->bpb_secperclus + 1; 266 fat_bpb->firstdatasector / fat_bpb->bpb_secperclus + 1;
275 267
276 if(cluster > max_cluster) 268 if (cluster > max_cluster)
277 { 269 {
278 DEBUGF( "cluster2sec() - Bad cluster number (%d)\n", 270 DEBUGF( "cluster2sec() - Bad cluster number (%d)\n", cluster);
279 cluster);
280 return -1; 271 return -1;
281 } 272 }
282 273
283 return first_sector_of_cluster(IF_MV2(fat_bpb,) cluster); 274 return (cluster - zerocluster) * fat_bpb->bpb_secperclus
284} 275 + fat_bpb->firstdatasector;
285
286static int first_sector_of_cluster(IF_MV2(struct bpb* fat_bpb,) int cluster)
287{
288#ifndef HAVE_MULTIVOLUME
289 struct bpb* fat_bpb = &fat_bpbs[0];
290#endif
291#ifdef HAVE_FAT16SUPPORT
292 /* negative clusters (FAT16 root dir) don't get the 2 offset */
293 int zerocluster = cluster < 0 ? 0 : 2;
294#else
295 const int zerocluster = 2;
296#endif
297 return (cluster - zerocluster) * fat_bpb->bpb_secperclus + fat_bpb->firstdatasector;
298} 276}
299 277
300int fat_startsector(IF_MV_NONVOID(int volume)) 278int fat_startsector(IF_MV_NONVOID(int volume))
@@ -349,6 +327,9 @@ int fat_mount(IF_MV2(int volume,) IF_MV2(int drive,) int startsector)
349 unsigned char buf[SECTOR_SIZE]; 327 unsigned char buf[SECTOR_SIZE];
350 int rc; 328 int rc;
351 int datasec; 329 int datasec;
330#ifdef HAVE_FAT16SUPPORT
331 int rootdirsectors;
332#endif
352 333
353 /* Read the sector */ 334 /* Read the sector */
354 rc = ata_read_sectors(IF_MV2(drive,) startsector,1,buf); 335 rc = ata_read_sectors(IF_MV2(drive,) startsector,1,buf);
@@ -359,7 +340,7 @@ int fat_mount(IF_MV2(int volume,) IF_MV2(int drive,) int startsector)
359 } 340 }
360 341
361 memset(fat_bpb, 0, sizeof(struct bpb)); 342 memset(fat_bpb, 0, sizeof(struct bpb));
362 fat_bpb->startsector = startsector; 343 fat_bpb->startsector = startsector;
363#ifdef HAVE_MULTIVOLUME 344#ifdef HAVE_MULTIVOLUME
364 fat_bpb->drive = drive; 345 fat_bpb->drive = drive;
365#endif 346#endif
@@ -388,13 +369,13 @@ int fat_mount(IF_MV2(int volume,) IF_MV2(int drive,) int startsector)
388 369
389#ifdef HAVE_FAT16SUPPORT 370#ifdef HAVE_FAT16SUPPORT
390 fat_bpb->bpb_rootentcnt = BYTES2INT16(buf,BPB_ROOTENTCNT); 371 fat_bpb->bpb_rootentcnt = BYTES2INT16(buf,BPB_ROOTENTCNT);
391 fat_bpb->rootdirsectors = ((fat_bpb->bpb_rootentcnt * 32) 372 rootdirsectors = ((fat_bpb->bpb_rootentcnt * 32)
392 + (fat_bpb->bpb_bytspersec - 1)) / fat_bpb->bpb_bytspersec; 373 + (fat_bpb->bpb_bytspersec - 1)) / fat_bpb->bpb_bytspersec;
393#endif /* #ifdef HAVE_FAT16SUPPORT */ 374#endif /* #ifdef HAVE_FAT16SUPPORT */
394 375
395 fat_bpb->firstdatasector = fat_bpb->bpb_rsvdseccnt 376 fat_bpb->firstdatasector = fat_bpb->bpb_rsvdseccnt
396#ifdef HAVE_FAT16SUPPORT 377#ifdef HAVE_FAT16SUPPORT
397 + fat_bpb->rootdirsectors 378 + rootdirsectors
398#endif 379#endif
399 + fat_bpb->bpb_numfats * fat_bpb->fatsize; 380 + fat_bpb->bpb_numfats * fat_bpb->fatsize;
400 381
@@ -431,11 +412,13 @@ int fat_mount(IF_MV2(int volume,) IF_MV2(int drive,) int startsector)
431 int dirclusters; 412 int dirclusters;
432 fat_bpb->rootdirsector = fat_bpb->bpb_rsvdseccnt 413 fat_bpb->rootdirsector = fat_bpb->bpb_rsvdseccnt
433 + fat_bpb->bpb_numfats * fat_bpb->bpb_fatsz16; 414 + fat_bpb->bpb_numfats * fat_bpb->bpb_fatsz16;
434 dirclusters = ((fat_bpb->rootdirsectors + fat_bpb->bpb_secperclus - 1) 415 dirclusters = ((rootdirsectors + fat_bpb->bpb_secperclus - 1)
435 / fat_bpb->bpb_secperclus); /* rounded up, to full clusters */ 416 / fat_bpb->bpb_secperclus); /* rounded up, to full clusters */
436 /* I assign negative pseudo cluster numbers for the root directory, 417 /* I assign negative pseudo cluster numbers for the root directory,
437 their range is counted upward until -1. */ 418 their range is counted upward until -1. */
438 fat_bpb->bpb_rootclus = 0 - dirclusters; /* backwards, before the data */ 419 fat_bpb->bpb_rootclus = 0 - dirclusters; /* backwards, before the data */
420 fat_bpb->rootdiroffset = dirclusters * fat_bpb->bpb_secperclus
421 - rootdirsectors;
439 } 422 }
440 else 423 else
441#endif /* #ifdef HAVE_FAT16SUPPORT */ 424#endif /* #ifdef HAVE_FAT16SUPPORT */
@@ -610,7 +593,7 @@ static void flush_fat_sector(struct fat_cache_entry *fce,
610 sectorbuf); 593 sectorbuf);
611 if(rc < 0) 594 if(rc < 0)
612 { 595 {
613 panicf("cache_fat_sector() - Could not write sector %d" 596 panicf("flush_fat_sector() - Could not write sector %d"
614 " (error %d)\n", 597 " (error %d)\n",
615 secnum, rc); 598 secnum, rc);
616 } 599 }
@@ -630,7 +613,7 @@ static void flush_fat_sector(struct fat_cache_entry *fce,
630 secnum, 1, sectorbuf); 613 secnum, 1, sectorbuf);
631 if(rc < 0) 614 if(rc < 0)
632 { 615 {
633 panicf("cache_fat_sector() - Could not write sector %d" 616 panicf("flush_fat_sector() - Could not write sector %d"
634 " (error %d)\n", 617 " (error %d)\n",
635 secnum, rc); 618 secnum, rc);
636 } 619 }
@@ -667,7 +650,7 @@ static void *cache_fat_sector(IF_MV2(struct bpb* fat_bpb,) int fatsector)
667 /* Load the sector if it is not cached */ 650 /* Load the sector if it is not cached */
668 if(!fce->inuse) 651 if(!fce->inuse)
669 { 652 {
670 rc = ata_read_sectors(IF_MV2(fat_bpb->drive,) 653 rc = ata_read_sectors(IF_MV2(fat_bpb->drive,)
671 secnum + fat_bpb->startsector,1, 654 secnum + fat_bpb->startsector,1,
672 sectorbuf); 655 sectorbuf);
673 if(rc < 0) 656 if(rc < 0)
@@ -780,7 +763,7 @@ static int update_fat_entry(IF_MV2(struct bpb* fat_bpb,) unsigned int entry, uns
780 sec = cache_fat_sector(IF_MV2(fat_bpb,) sector); 763 sec = cache_fat_sector(IF_MV2(fat_bpb,) sector);
781 if (!sec) 764 if (!sec)
782 { 765 {
783 DEBUGF( "update_entry() - Could not cache sector %d\n", sector); 766 DEBUGF( "update_fat_entry() - Could not cache sector %d\n", sector);
784 return -1; 767 return -1;
785 } 768 }
786 fat_cache[(sector + fat_bpb->bpb_rsvdseccnt) & FAT_CACHE_MASK].dirty = true; 769 fat_cache[(sector + fat_bpb->bpb_rsvdseccnt) & FAT_CACHE_MASK].dirty = true;
@@ -816,7 +799,7 @@ static int update_fat_entry(IF_MV2(struct bpb* fat_bpb,) unsigned int entry, uns
816 sec = cache_fat_sector(IF_MV2(fat_bpb,) sector); 799 sec = cache_fat_sector(IF_MV2(fat_bpb,) sector);
817 if (!sec) 800 if (!sec)
818 { 801 {
819 DEBUGF( "update_entry() - Could not cache sector %d\n", sector); 802 DEBUGF( "update_fat_entry() - Could not cache sector %d\n", sector);
820 return -1; 803 return -1;
821 } 804 }
822 fat_cache[(sector + fat_bpb->bpb_rsvdseccnt) & FAT_CACHE_MASK].dirty = true; 805 fat_cache[(sector + fat_bpb->bpb_rsvdseccnt) & FAT_CACHE_MASK].dirty = true;
@@ -1541,8 +1524,8 @@ static int parse_direntry(struct fat_direntry *de, const unsigned char *buf)
1541 return 1; 1524 return 1;
1542} 1525}
1543 1526
1544int fat_open(IF_MV2(int volume,) 1527int fat_open(IF_MV2(int volume,)
1545 unsigned int startcluster, 1528 int startcluster,
1546 struct fat_file *file, 1529 struct fat_file *file,
1547 const struct fat_dir* dir) 1530 const struct fat_dir* dir)
1548{ 1531{
@@ -1572,33 +1555,6 @@ int fat_open(IF_MV2(int volume,)
1572 return 0; 1555 return 0;
1573} 1556}
1574 1557
1575#ifdef HAVE_FAT16SUPPORT
1576/* special function to open the FAT16 root dir,
1577 which may not be on cluster boundary */
1578static int fat_open_root(IF_MV2(int volume,)
1579 struct fat_file *file)
1580{
1581 int dirclusters;
1582#ifdef HAVE_MULTIVOLUME
1583 struct bpb* fat_bpb = &fat_bpbs[volume];
1584 file->volume = volume;
1585#else
1586 struct bpb* fat_bpb = &fat_bpbs[0];
1587#endif
1588 file->firstcluster = fat_bpb->bpb_rootclus;
1589 file->lastcluster = fat_bpb->bpb_rootclus;
1590 file->lastsector = 0;
1591 file->clusternum = 0;
1592 dirclusters = 0 - fat_bpb->bpb_rootclus; /* bpb_rootclus is the negative */
1593 file->sectornum = (dirclusters * fat_bpb->bpb_secperclus)
1594 - fat_bpb->rootdirsectors; /* cluster sectors minus real sectors */
1595 file->eof = false;
1596
1597 LDEBUGF("fat_open_root(), sector %d\n", cluster2sec(fat_bpb->bpb_rootclus));
1598 return 0;
1599}
1600#endif /* #ifdef HAVE_FAT16SUPPORT */
1601
1602int fat_create_file(const char* name, 1558int fat_create_file(const char* name,
1603 struct fat_file* file, 1559 struct fat_file* file,
1604 struct fat_dir* dir) 1560 struct fat_dir* dir)
@@ -2054,6 +2010,13 @@ int fat_readwrite( struct fat_file *file, int sectorcount,
2054 /* look up first sector of file */ 2010 /* look up first sector of file */
2055 sector = cluster2sec(IF_MV2(fat_bpb,) file->firstcluster); 2011 sector = cluster2sec(IF_MV2(fat_bpb,) file->firstcluster);
2056 numsec=1; 2012 numsec=1;
2013#ifdef HAVE_FAT16SUPPORT
2014 if (file->firstcluster < 0)
2015 { /* FAT16 root dir */
2016 sector += fat_bpb->rootdiroffset;
2017 numsec += fat_bpb->rootdiroffset;
2018 }
2019#endif
2057 } 2020 }
2058 } 2021 }
2059 2022
@@ -2108,6 +2071,11 @@ int fat_seek(struct fat_file *file, unsigned int seeksector )
2108 int cluster = file->firstcluster; 2071 int cluster = file->firstcluster;
2109 int i; 2072 int i;
2110 2073
2074#ifdef HAVE_FAT16SUPPORT
2075 if (cluster < 0) /* FAT16 root dir */
2076 seeksector += fat_bpb->rootdiroffset;
2077#endif
2078
2111 file->eof = false; 2079 file->eof = false;
2112 if (seeksector) { 2080 if (seeksector) {
2113 /* we need to find the sector BEFORE the requested, since 2081 /* we need to find the sector BEFORE the requested, since
@@ -2168,15 +2136,7 @@ int fat_opendir(IF_MV2(int volume,)
2168 dir->sector = 0; 2136 dir->sector = 0;
2169 2137
2170 if (startcluster == 0) 2138 if (startcluster == 0)
2171 { 2139 startcluster = fat_bpb->bpb_rootclus;
2172#ifdef HAVE_FAT16SUPPORT
2173 if (fat_bpb->is_fat16)
2174 { /* FAT16 has the root dir outside of the data area */
2175 return fat_open_root(IF_MV2(volume,) &dir->file);
2176 }
2177#endif
2178 startcluster = sec2cluster(IF_MV2(fat_bpb,) fat_bpb->rootdirsector);
2179 }
2180 2140
2181 rc = fat_open(IF_MV2(volume,) startcluster, &dir->file, parent_dir); 2141 rc = fat_open(IF_MV2(volume,) startcluster, &dir->file, parent_dir);
2182 if(rc) 2142 if(rc)
diff --git a/firmware/export/fat.h b/firmware/export/fat.h
index 7150d2b09f..2f1c7be0a8 100644
--- a/firmware/export/fat.h
+++ b/firmware/export/fat.h
@@ -57,10 +57,10 @@ struct fat_file
57 int sectornum; /* sector number in this cluster */ 57 int sectornum; /* sector number in this cluster */
58 unsigned int direntry; /* short dir entry index from start of dir */ 58 unsigned int direntry; /* short dir entry index from start of dir */
59 unsigned int direntries; /* number of dir entries used by this file */ 59 unsigned int direntries; /* number of dir entries used by this file */
60 unsigned int dircluster; /* first cluster of dir */ 60 int dircluster; /* first cluster of dir */
61 bool eof; 61 bool eof;
62#ifdef HAVE_MULTIVOLUME 62#ifdef HAVE_MULTIVOLUME
63 int volume; /* file resides on which volume */ 63 int volume; /* file resides on which volume */
64#endif 64#endif
65}; 65};
66 66
@@ -83,7 +83,7 @@ extern int fat_create_dir(const char* name,
83 struct fat_dir* dir); 83 struct fat_dir* dir);
84extern int fat_startsector(IF_MV_NONVOID(int volume)); // public for config sector 84extern int fat_startsector(IF_MV_NONVOID(int volume)); // public for config sector
85extern int fat_open(IF_MV2(int volume,) 85extern int fat_open(IF_MV2(int volume,)
86 unsigned int cluster, 86 int cluster,
87 struct fat_file* ent, 87 struct fat_file* ent,
88 const struct fat_dir* dir); 88 const struct fat_dir* dir);
89extern int fat_create_file(const char* name, 89extern int fat_create_file(const char* name,
@@ -96,7 +96,7 @@ extern int fat_seek(struct fat_file *ent, unsigned int sector );
96extern int fat_remove(struct fat_file *ent); 96extern int fat_remove(struct fat_file *ent);
97extern int fat_truncate(const struct fat_file *ent); 97extern int fat_truncate(const struct fat_file *ent);
98extern int fat_rename(struct fat_file* file, 98extern int fat_rename(struct fat_file* file,
99 struct fat_dir* dir, 99 struct fat_dir* dir,
100 const unsigned char* newname, 100 const unsigned char* newname,
101 int size, int attr); 101 int size, int attr);
102 102