diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/drivers/fat.c | 124 | ||||
-rw-r--r-- | firmware/export/fat.h | 8 |
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 | ||
230 | static int update_fsinfo(IF_MV_NONVOID(struct bpb* fat_bpb)); | 231 | static int update_fsinfo(IF_MV_NONVOID(struct bpb* fat_bpb)); |
231 | static int bpb_is_sane(IF_MV_NONVOID(struct bpb* fat_bpb)); | 232 | static int bpb_is_sane(IF_MV_NONVOID(struct bpb* fat_bpb)); |
232 | static int first_sector_of_cluster(IF_MV2(struct bpb* fat_bpb,) int cluster); | ||
233 | static void *cache_fat_sector(IF_MV2(struct bpb* fat_bpb,) int secnum); | 233 | static void *cache_fat_sector(IF_MV2(struct bpb* fat_bpb,) int secnum); |
234 | static int create_dos_name(const unsigned char *name, unsigned char *newname); | 234 | static int create_dos_name(const unsigned char *name, unsigned char *newname); |
235 | static unsigned int find_free_cluster(IF_MV2(struct bpb* fat_bpb,) unsigned int start); | 235 | static unsigned int find_free_cluster(IF_MV2(struct bpb* fat_bpb,) unsigned int start); |
@@ -251,50 +251,28 @@ struct fat_cache_entry | |||
251 | static char fat_cache_sectors[FAT_CACHE_SIZE][SECTOR_SIZE]; | 251 | static char fat_cache_sectors[FAT_CACHE_SIZE][SECTOR_SIZE]; |
252 | static struct fat_cache_entry fat_cache[FAT_CACHE_SIZE]; | 252 | static struct fat_cache_entry fat_cache[FAT_CACHE_SIZE]; |
253 | 253 | ||
254 | static 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 | |||
268 | static int cluster2sec(IF_MV2(struct bpb* fat_bpb,) int cluster) | 254 | static 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 | |||
286 | static 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 | ||
300 | int fat_startsector(IF_MV_NONVOID(int volume)) | 278 | int 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 | ||
1544 | int fat_open(IF_MV2(int volume,) | 1527 | int 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 */ | ||
1578 | static 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 | |||
1602 | int fat_create_file(const char* name, | 1558 | int 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); |
84 | extern int fat_startsector(IF_MV_NONVOID(int volume)); // public for config sector | 84 | extern int fat_startsector(IF_MV_NONVOID(int volume)); // public for config sector |
85 | extern int fat_open(IF_MV2(int volume,) | 85 | extern 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); |
89 | extern int fat_create_file(const char* name, | 89 | extern int fat_create_file(const char* name, |
@@ -96,7 +96,7 @@ extern int fat_seek(struct fat_file *ent, unsigned int sector ); | |||
96 | extern int fat_remove(struct fat_file *ent); | 96 | extern int fat_remove(struct fat_file *ent); |
97 | extern int fat_truncate(const struct fat_file *ent); | 97 | extern int fat_truncate(const struct fat_file *ent); |
98 | extern int fat_rename(struct fat_file* file, | 98 | extern 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 | ||