forked from len0rd/rockbox
Add support (runtime detection) for 2048 bytes/sector filesystem.
Large sectors are enabled for iPod Video (including 5.5G) only. Might still cause FS corruption (however, unlikely), so beware! Based on FS#6169 by Robert Carboneau. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11651 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
1612275960
commit
ae66c2b9ee
4 changed files with 135 additions and 59 deletions
|
@ -157,7 +157,21 @@ int disk_mount(int drive)
|
||||||
mounted++;
|
mounted++;
|
||||||
vol_drive[volume] = drive; /* remember the drive for this volume */
|
vol_drive[volume] = drive; /* remember the drive for this volume */
|
||||||
volume = get_free_volume(); /* prepare next entry */
|
volume = get_free_volume(); /* prepare next entry */
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# if MAX_SECTOR_SIZE != PHYSICAL_SECTOR_SIZE
|
||||||
|
/* Try again with sector size 2048 */
|
||||||
|
if (!fat_mount(IF_MV2(volume,) IF_MV2(drive,) pinfo[i].start
|
||||||
|
* (MAX_SECTOR_SIZE/PHYSICAL_SECTOR_SIZE)))
|
||||||
|
{
|
||||||
|
pinfo[i].start *= MAX_SECTOR_SIZE/PHYSICAL_SECTOR_SIZE;
|
||||||
|
pinfo[i].size *= MAX_SECTOR_SIZE/PHYSICAL_SECTOR_SIZE;
|
||||||
|
mounted++;
|
||||||
|
vol_drive[volume] = drive; /* remember the drive for this volume */
|
||||||
|
volume = get_free_volume(); /* prepare next entry */
|
||||||
|
}
|
||||||
|
# endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct filedesc {
|
struct filedesc {
|
||||||
unsigned char cache[SECTOR_SIZE];
|
unsigned char cache[MAX_SECTOR_SIZE];
|
||||||
int cacheoffset; /* invariant: 0 <= cacheoffset <= SECTOR_SIZE */
|
int cacheoffset; /* invariant: 0 <= cacheoffset <= SECTOR_SIZE */
|
||||||
long fileoffset;
|
long fileoffset;
|
||||||
long size;
|
long size;
|
||||||
|
@ -415,9 +415,10 @@ int ftruncate(int fd, off_t size)
|
||||||
{
|
{
|
||||||
int rc, sector;
|
int rc, sector;
|
||||||
struct filedesc* file = &openfiles[fd];
|
struct filedesc* file = &openfiles[fd];
|
||||||
|
int secsize = fat_get_secsize(&(file->fatfile));
|
||||||
|
|
||||||
sector = size / SECTOR_SIZE;
|
sector = size / secsize;
|
||||||
if (size % SECTOR_SIZE)
|
if (size % secsize)
|
||||||
sector++;
|
sector++;
|
||||||
|
|
||||||
rc = fat_seek(&(file->fatfile), sector);
|
rc = fat_seek(&(file->fatfile), sector);
|
||||||
|
@ -444,7 +445,7 @@ static int flush_cache(int fd)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
struct filedesc* file = &openfiles[fd];
|
struct filedesc* file = &openfiles[fd];
|
||||||
long sector = file->fileoffset / SECTOR_SIZE;
|
long sector = file->fileoffset / fat_get_secsize(&(file->fatfile));
|
||||||
|
|
||||||
DEBUGF("Flushing dirty sector cache\n");
|
DEBUGF("Flushing dirty sector cache\n");
|
||||||
|
|
||||||
|
@ -473,6 +474,7 @@ static int readwrite(int fd, void* buf, long count, bool write)
|
||||||
long sectors;
|
long sectors;
|
||||||
long nread=0;
|
long nread=0;
|
||||||
struct filedesc* file = &openfiles[fd];
|
struct filedesc* file = &openfiles[fd];
|
||||||
|
int secsize = fat_get_secsize(&(file->fatfile));
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if ( !file->busy ) {
|
if ( !file->busy ) {
|
||||||
|
@ -490,7 +492,7 @@ static int readwrite(int fd, void* buf, long count, bool write)
|
||||||
/* any head bytes? */
|
/* any head bytes? */
|
||||||
if ( file->cacheoffset != -1 ) {
|
if ( file->cacheoffset != -1 ) {
|
||||||
int offs = file->cacheoffset;
|
int offs = file->cacheoffset;
|
||||||
int headbytes = MIN(count, SECTOR_SIZE - offs);
|
int headbytes = MIN(count, secsize - offs);
|
||||||
|
|
||||||
if (write) {
|
if (write) {
|
||||||
memcpy( file->cache + offs, buf, headbytes );
|
memcpy( file->cache + offs, buf, headbytes );
|
||||||
|
@ -500,7 +502,7 @@ static int readwrite(int fd, void* buf, long count, bool write)
|
||||||
memcpy( buf, file->cache + offs, headbytes );
|
memcpy( buf, file->cache + offs, headbytes );
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offs + headbytes == SECTOR_SIZE) {
|
if (offs + headbytes == secsize) {
|
||||||
if (file->dirty) {
|
if (file->dirty) {
|
||||||
int rc = flush_cache(fd);
|
int rc = flush_cache(fd);
|
||||||
if ( rc < 0 ) {
|
if ( rc < 0 ) {
|
||||||
|
@ -523,7 +525,7 @@ static int readwrite(int fd, void* buf, long count, bool write)
|
||||||
* more data to follow in this call). Do NOT flush here. */
|
* more data to follow in this call). Do NOT flush here. */
|
||||||
|
|
||||||
/* read/write whole sectors right into/from the supplied buffer */
|
/* read/write whole sectors right into/from the supplied buffer */
|
||||||
sectors = count / SECTOR_SIZE;
|
sectors = count / secsize;
|
||||||
if ( sectors ) {
|
if ( sectors ) {
|
||||||
int rc = fat_readwrite(&(file->fatfile), sectors,
|
int rc = fat_readwrite(&(file->fatfile), sectors,
|
||||||
(unsigned char*)buf+nread, write );
|
(unsigned char*)buf+nread, write );
|
||||||
|
@ -541,8 +543,8 @@ static int readwrite(int fd, void* buf, long count, bool write)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ( rc > 0 ) {
|
if ( rc > 0 ) {
|
||||||
nread += rc * SECTOR_SIZE;
|
nread += rc * secsize;
|
||||||
count -= sectors * SECTOR_SIZE;
|
count -= sectors * secsize;
|
||||||
|
|
||||||
/* if eof, skip tail bytes */
|
/* if eof, skip tail bytes */
|
||||||
if ( rc < sectors )
|
if ( rc < sectors )
|
||||||
|
@ -575,7 +577,7 @@ static int readwrite(int fd, void* buf, long count, bool write)
|
||||||
/* seek back one sector to put file position right */
|
/* seek back one sector to put file position right */
|
||||||
rc = fat_seek(&(file->fatfile),
|
rc = fat_seek(&(file->fatfile),
|
||||||
(file->fileoffset + nread) /
|
(file->fileoffset + nread) /
|
||||||
SECTOR_SIZE);
|
secsize);
|
||||||
if ( rc < 0 ) {
|
if ( rc < 0 ) {
|
||||||
DEBUGF("fat_seek() failed\n");
|
DEBUGF("fat_seek() failed\n");
|
||||||
errno = EIO;
|
errno = EIO;
|
||||||
|
@ -641,6 +643,7 @@ off_t lseek(int fd, off_t offset, int whence)
|
||||||
int sectoroffset;
|
int sectoroffset;
|
||||||
int rc;
|
int rc;
|
||||||
struct filedesc* file = &openfiles[fd];
|
struct filedesc* file = &openfiles[fd];
|
||||||
|
int secsize = fat_get_secsize(&(file->fatfile));
|
||||||
|
|
||||||
LDEBUGF("lseek(%d,%ld,%d)\n",fd,offset,whence);
|
LDEBUGF("lseek(%d,%ld,%d)\n",fd,offset,whence);
|
||||||
|
|
||||||
|
@ -672,9 +675,9 @@ off_t lseek(int fd, off_t offset, int whence)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* new sector? */
|
/* new sector? */
|
||||||
newsector = pos / SECTOR_SIZE;
|
newsector = pos / secsize;
|
||||||
oldsector = file->fileoffset / SECTOR_SIZE;
|
oldsector = file->fileoffset / secsize;
|
||||||
sectoroffset = pos % SECTOR_SIZE;
|
sectoroffset = pos % secsize;
|
||||||
|
|
||||||
if ( (newsector != oldsector) ||
|
if ( (newsector != oldsector) ||
|
||||||
((file->cacheoffset==-1) && sectoroffset) ) {
|
((file->cacheoffset==-1) && sectoroffset) ) {
|
||||||
|
|
|
@ -109,9 +109,9 @@
|
||||||
#define FATLONG_TYPE 12
|
#define FATLONG_TYPE 12
|
||||||
#define FATLONG_CHKSUM 13
|
#define FATLONG_CHKSUM 13
|
||||||
|
|
||||||
#define CLUSTERS_PER_FAT_SECTOR (SECTOR_SIZE / 4)
|
#define CLUSTERS_PER_FAT_SECTOR ((unsigned int)(fat_bpb->bpb_bytspersec / 4))
|
||||||
#define CLUSTERS_PER_FAT16_SECTOR (SECTOR_SIZE / 2)
|
#define CLUSTERS_PER_FAT16_SECTOR ((unsigned int)(fat_bpb->bpb_bytspersec / 2))
|
||||||
#define DIR_ENTRIES_PER_SECTOR (SECTOR_SIZE / DIR_ENTRY_SIZE)
|
#define DIR_ENTRIES_PER_SECTOR ((unsigned int)(fat_bpb->bpb_bytspersec / DIR_ENTRY_SIZE))
|
||||||
#define DIR_ENTRY_SIZE 32
|
#define DIR_ENTRY_SIZE 32
|
||||||
#define NAME_BYTES_PER_ENTRY 13
|
#define NAME_BYTES_PER_ENTRY 13
|
||||||
#define FAT_BAD_MARK 0x0ffffff7
|
#define FAT_BAD_MARK 0x0ffffff7
|
||||||
|
@ -165,8 +165,12 @@ struct bpb
|
||||||
int drive; /* on which physical device is this located */
|
int drive; /* on which physical device is this located */
|
||||||
bool mounted; /* flag if this volume is mounted */
|
bool mounted; /* flag if this volume is mounted */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int secmult; /* bpb_bytspersec / PHYSICAL_SECTOR_SIZE */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int fat_sector_size;
|
||||||
|
|
||||||
static struct bpb fat_bpbs[NUM_VOLUMES]; /* mounted partition info */
|
static struct bpb fat_bpbs[NUM_VOLUMES]; /* mounted partition info */
|
||||||
|
|
||||||
static int update_fsinfo(IF_MV_NONVOID(struct bpb* fat_bpb));
|
static int update_fsinfo(IF_MV_NONVOID(struct bpb* fat_bpb));
|
||||||
|
@ -191,7 +195,7 @@ struct fat_cache_entry
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static char fat_cache_sectors[FAT_CACHE_SIZE][SECTOR_SIZE];
|
static char fat_cache_sectors[FAT_CACHE_SIZE][MAX_SECTOR_SIZE];
|
||||||
static struct fat_cache_entry fat_cache[FAT_CACHE_SIZE];
|
static struct fat_cache_entry fat_cache[FAT_CACHE_SIZE];
|
||||||
static struct mutex cache_mutex;
|
static struct mutex cache_mutex;
|
||||||
|
|
||||||
|
@ -233,9 +237,11 @@ void fat_size(IF_MV2(int volume,) unsigned long* size, unsigned long* free)
|
||||||
#endif
|
#endif
|
||||||
struct bpb* fat_bpb = &fat_bpbs[volume];
|
struct bpb* fat_bpb = &fat_bpbs[volume];
|
||||||
if (size)
|
if (size)
|
||||||
*size = fat_bpb->dataclusters * fat_bpb->bpb_secperclus / 2;
|
*size = (fat_bpb->dataclusters * fat_bpb->bpb_secperclus
|
||||||
|
* fat_bpb->bpb_bytspersec) / 1024;
|
||||||
if (free)
|
if (free)
|
||||||
*free = fat_bpb->fsinfo.freecount * fat_bpb->bpb_secperclus / 2;
|
*free = (fat_bpb->fsinfo.freecount * fat_bpb->bpb_secperclus
|
||||||
|
* fat_bpb->bpb_bytspersec) / 1024;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fat_init(void)
|
void fat_init(void)
|
||||||
|
@ -269,7 +275,7 @@ int fat_mount(IF_MV2(int volume,) IF_MV2(int drive,) long startsector)
|
||||||
const int volume = 0;
|
const int volume = 0;
|
||||||
#endif
|
#endif
|
||||||
struct bpb* fat_bpb = &fat_bpbs[volume];
|
struct bpb* fat_bpb = &fat_bpbs[volume];
|
||||||
unsigned char buf[SECTOR_SIZE];
|
unsigned char buf[MAX_SECTOR_SIZE];
|
||||||
int rc;
|
int rc;
|
||||||
long datasec;
|
long datasec;
|
||||||
#ifdef HAVE_FAT16SUPPORT
|
#ifdef HAVE_FAT16SUPPORT
|
||||||
|
@ -302,6 +308,8 @@ int fat_mount(IF_MV2(int volume,) IF_MV2(int drive,) long startsector)
|
||||||
fat_bpb->last_word = BYTES2INT16(buf,BPB_LAST_WORD);
|
fat_bpb->last_word = BYTES2INT16(buf,BPB_LAST_WORD);
|
||||||
|
|
||||||
/* calculate a few commonly used values */
|
/* calculate a few commonly used values */
|
||||||
|
fat_bpb->secmult = fat_bpb->bpb_bytspersec / PHYSICAL_SECTOR_SIZE;
|
||||||
|
|
||||||
if (fat_bpb->bpb_fatsz16 != 0)
|
if (fat_bpb->bpb_fatsz16 != 0)
|
||||||
fat_bpb->fatsize = fat_bpb->bpb_fatsz16;
|
fat_bpb->fatsize = fat_bpb->bpb_fatsz16;
|
||||||
else
|
else
|
||||||
|
@ -391,7 +399,7 @@ int fat_mount(IF_MV2(int volume,) IF_MV2(int drive,) long startsector)
|
||||||
{
|
{
|
||||||
/* Read the fsinfo sector */
|
/* Read the fsinfo sector */
|
||||||
rc = ata_read_sectors(IF_MV2(drive,)
|
rc = ata_read_sectors(IF_MV2(drive,)
|
||||||
startsector + fat_bpb->bpb_fsinfo, 1, buf);
|
startsector + (fat_bpb->bpb_fsinfo * fat_bpb->secmult), 1, buf);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
{
|
{
|
||||||
DEBUGF( "fat_mount() - Couldn't read FSInfo (error code %d)\n", rc);
|
DEBUGF( "fat_mount() - Couldn't read FSInfo (error code %d)\n", rc);
|
||||||
|
@ -506,12 +514,15 @@ static int bpb_is_sane(IF_MV_NONVOID(struct bpb* fat_bpb))
|
||||||
#ifndef HAVE_MULTIVOLUME
|
#ifndef HAVE_MULTIVOLUME
|
||||||
struct bpb* fat_bpb = &fat_bpbs[0];
|
struct bpb* fat_bpb = &fat_bpbs[0];
|
||||||
#endif
|
#endif
|
||||||
if(fat_bpb->bpb_bytspersec != 512)
|
if(fat_bpb->bpb_bytspersec > MAX_SECTOR_SIZE
|
||||||
|
|| fat_bpb->bpb_bytspersec < PHYSICAL_SECTOR_SIZE
|
||||||
|
|| fat_bpb->bpb_bytspersec % PHYSICAL_SECTOR_SIZE)
|
||||||
{
|
{
|
||||||
DEBUGF( "bpb_is_sane() - Error: sector size is not 512 (%d)\n",
|
DEBUGF( "bpb_is_sane() - Error: sector size is not sane (%d)\n",
|
||||||
fat_bpb->bpb_bytspersec);
|
fat_bpb->bpb_bytspersec);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((long)fat_bpb->bpb_secperclus * (long)fat_bpb->bpb_bytspersec > 128L*1024L)
|
if((long)fat_bpb->bpb_secperclus * (long)fat_bpb->bpb_bytspersec > 128L*1024L)
|
||||||
{
|
{
|
||||||
DEBUGF( "bpb_is_sane() - Error: cluster size is larger than 128K "
|
DEBUGF( "bpb_is_sane() - Error: cluster size is larger than 128K "
|
||||||
|
@ -555,17 +566,20 @@ static void flush_fat_sector(struct fat_cache_entry *fce,
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
long secnum;
|
long secnum;
|
||||||
|
int secmult;
|
||||||
|
|
||||||
/* With multivolume, use only the FAT info from the cached sector! */
|
/* With multivolume, use only the FAT info from the cached sector! */
|
||||||
#ifdef HAVE_MULTIVOLUME
|
#ifdef HAVE_MULTIVOLUME
|
||||||
secnum = fce->secnum + fce->fat_vol->startsector;
|
secmult = fce->fat_vol->secmult;
|
||||||
|
secnum = (fce->secnum * secmult) + fce->fat_vol->startsector;
|
||||||
#else
|
#else
|
||||||
secnum = fce->secnum + fat_bpbs[0].startsector;
|
secmult = fat_bpbs[0].secmult;
|
||||||
|
secnum = (fce->secnum * secmult) + fat_bpbs[0].startsector;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Write to the first FAT */
|
/* Write to the first FAT */
|
||||||
rc = ata_write_sectors(IF_MV2(fce->fat_vol->drive,)
|
rc = ata_write_sectors(IF_MV2(fce->fat_vol->drive,)
|
||||||
secnum, 1,
|
secnum, secmult,
|
||||||
sectorbuf);
|
sectorbuf);
|
||||||
if(rc < 0)
|
if(rc < 0)
|
||||||
{
|
{
|
||||||
|
@ -581,12 +595,12 @@ static void flush_fat_sector(struct fat_cache_entry *fce,
|
||||||
{
|
{
|
||||||
/* Write to the second FAT */
|
/* Write to the second FAT */
|
||||||
#ifdef HAVE_MULTIVOLUME
|
#ifdef HAVE_MULTIVOLUME
|
||||||
secnum += fce->fat_vol->fatsize;
|
secnum += fce->fat_vol->fatsize * secmult;
|
||||||
#else
|
#else
|
||||||
secnum += fat_bpbs[0].fatsize;
|
secnum += fat_bpbs[0].fatsize * secmult;
|
||||||
#endif
|
#endif
|
||||||
rc = ata_write_sectors(IF_MV2(fce->fat_vol->drive,)
|
rc = ata_write_sectors(IF_MV2(fce->fat_vol->drive,)
|
||||||
secnum, 1, sectorbuf);
|
secnum, secmult, sectorbuf);
|
||||||
if(rc < 0)
|
if(rc < 0)
|
||||||
{
|
{
|
||||||
panicf("flush_fat_sector() - Could not write sector %ld"
|
panicf("flush_fat_sector() - Could not write sector %ld"
|
||||||
|
@ -632,8 +646,8 @@ static void *cache_fat_sector(IF_MV2(struct bpb* fat_bpb,)
|
||||||
if(!fce->inuse)
|
if(!fce->inuse)
|
||||||
{
|
{
|
||||||
rc = ata_read_sectors(IF_MV2(fat_bpb->drive,)
|
rc = ata_read_sectors(IF_MV2(fat_bpb->drive,)
|
||||||
secnum + fat_bpb->startsector,1,
|
(secnum * fat_bpb->secmult) + fat_bpb->startsector,
|
||||||
sectorbuf);
|
fat_bpb->secmult, sectorbuf);
|
||||||
if(rc < 0)
|
if(rc < 0)
|
||||||
{
|
{
|
||||||
DEBUGF( "cache_fat_sector() - Could not read sector %ld"
|
DEBUGF( "cache_fat_sector() - Could not read sector %ld"
|
||||||
|
@ -809,10 +823,10 @@ static int update_fat_entry(IF_MV2(struct bpb* fat_bpb,) unsigned long entry, un
|
||||||
|
|
||||||
static long read_fat_entry(IF_MV2(struct bpb* fat_bpb,) unsigned long entry)
|
static long read_fat_entry(IF_MV2(struct bpb* fat_bpb,) unsigned long entry)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_FAT16SUPPORT
|
|
||||||
#ifndef HAVE_MULTIVOLUME
|
#ifndef HAVE_MULTIVOLUME
|
||||||
struct bpb* fat_bpb = &fat_bpbs[0];
|
struct bpb* fat_bpb = &fat_bpbs[0];
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_FAT16SUPPORT
|
||||||
if (fat_bpb->is_fat16)
|
if (fat_bpb->is_fat16)
|
||||||
{
|
{
|
||||||
int sector = entry / CLUSTERS_PER_FAT16_SECTOR;
|
int sector = entry / CLUSTERS_PER_FAT16_SECTOR;
|
||||||
|
@ -876,7 +890,7 @@ static int update_fsinfo(IF_MV_NONVOID(struct bpb* fat_bpb))
|
||||||
#ifndef HAVE_MULTIVOLUME
|
#ifndef HAVE_MULTIVOLUME
|
||||||
struct bpb* fat_bpb = &fat_bpbs[0];
|
struct bpb* fat_bpb = &fat_bpbs[0];
|
||||||
#endif
|
#endif
|
||||||
unsigned char fsinfo[SECTOR_SIZE];
|
unsigned char fsinfo[MAX_SECTOR_SIZE];
|
||||||
unsigned long* intptr;
|
unsigned long* intptr;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
@ -887,7 +901,8 @@ static int update_fsinfo(IF_MV_NONVOID(struct bpb* fat_bpb))
|
||||||
|
|
||||||
/* update fsinfo */
|
/* update fsinfo */
|
||||||
rc = ata_read_sectors(IF_MV2(fat_bpb->drive,)
|
rc = ata_read_sectors(IF_MV2(fat_bpb->drive,)
|
||||||
fat_bpb->startsector + fat_bpb->bpb_fsinfo, 1,fsinfo);
|
fat_bpb->startsector +
|
||||||
|
(fat_bpb->bpb_fsinfo * fat_bpb->secmult), 1, fsinfo);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
{
|
{
|
||||||
DEBUGF( "flush_fat() - Couldn't read FSInfo (error code %d)\n", rc);
|
DEBUGF( "flush_fat() - Couldn't read FSInfo (error code %d)\n", rc);
|
||||||
|
@ -900,7 +915,8 @@ static int update_fsinfo(IF_MV_NONVOID(struct bpb* fat_bpb))
|
||||||
*intptr = htole32(fat_bpb->fsinfo.nextfree);
|
*intptr = htole32(fat_bpb->fsinfo.nextfree);
|
||||||
|
|
||||||
rc = ata_write_sectors(IF_MV2(fat_bpb->drive,)
|
rc = ata_write_sectors(IF_MV2(fat_bpb->drive,)
|
||||||
fat_bpb->startsector + fat_bpb->bpb_fsinfo,1,fsinfo);
|
fat_bpb->startsector +
|
||||||
|
(fat_bpb->bpb_fsinfo * fat_bpb->secmult), 1, fsinfo);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
{
|
{
|
||||||
DEBUGF( "flush_fat() - Couldn't write FSInfo (error code %d)\n", rc);
|
DEBUGF( "flush_fat() - Couldn't write FSInfo (error code %d)\n", rc);
|
||||||
|
@ -1036,7 +1052,12 @@ static int write_long_name(struct fat_file* file,
|
||||||
const unsigned char* shortname,
|
const unsigned char* shortname,
|
||||||
bool is_directory)
|
bool is_directory)
|
||||||
{
|
{
|
||||||
unsigned char buf[SECTOR_SIZE];
|
#ifdef HAVE_MULTIVOLUME
|
||||||
|
struct bpb *fat_bpb = &fat_bpbs[file->volume];
|
||||||
|
#else
|
||||||
|
struct bpb *fat_bpb = &fat_bpbs[0];
|
||||||
|
#endif
|
||||||
|
unsigned char buf[MAX_SECTOR_SIZE];
|
||||||
unsigned char* entry;
|
unsigned char* entry;
|
||||||
unsigned int idx = firstentry % DIR_ENTRIES_PER_SECTOR;
|
unsigned int idx = firstentry % DIR_ENTRIES_PER_SECTOR;
|
||||||
unsigned int sector = firstentry / DIR_ENTRIES_PER_SECTOR;
|
unsigned int sector = firstentry / DIR_ENTRIES_PER_SECTOR;
|
||||||
|
@ -1194,7 +1215,7 @@ static int add_dir_entry(struct fat_dir* dir,
|
||||||
#else
|
#else
|
||||||
struct bpb* fat_bpb = &fat_bpbs[0];
|
struct bpb* fat_bpb = &fat_bpbs[0];
|
||||||
#endif
|
#endif
|
||||||
unsigned char buf[SECTOR_SIZE];
|
unsigned char buf[MAX_SECTOR_SIZE];
|
||||||
unsigned char shortname[12];
|
unsigned char shortname[12];
|
||||||
int rc;
|
int rc;
|
||||||
unsigned int sector;
|
unsigned int sector;
|
||||||
|
@ -1429,7 +1450,12 @@ static void randomize_dos_name(unsigned char *name)
|
||||||
|
|
||||||
static int update_short_entry( struct fat_file* file, long size, int attr )
|
static int update_short_entry( struct fat_file* file, long size, int attr )
|
||||||
{
|
{
|
||||||
unsigned char buf[SECTOR_SIZE];
|
#ifdef HAVE_MULTIVOLUME
|
||||||
|
struct bpb *fat_bpb = &fat_bpbs[file->volume];
|
||||||
|
#else
|
||||||
|
struct bpb *fat_bpb = &fat_bpbs[0];
|
||||||
|
#endif
|
||||||
|
unsigned char buf[MAX_SECTOR_SIZE];
|
||||||
int sector = file->direntry / DIR_ENTRIES_PER_SECTOR;
|
int sector = file->direntry / DIR_ENTRIES_PER_SECTOR;
|
||||||
unsigned char* entry =
|
unsigned char* entry =
|
||||||
buf + DIR_ENTRY_SIZE * (file->direntry % DIR_ENTRIES_PER_SECTOR);
|
buf + DIR_ENTRY_SIZE * (file->direntry % DIR_ENTRIES_PER_SECTOR);
|
||||||
|
@ -1594,7 +1620,7 @@ int fat_create_dir(const char* name,
|
||||||
#else
|
#else
|
||||||
struct bpb* fat_bpb = &fat_bpbs[0];
|
struct bpb* fat_bpb = &fat_bpbs[0];
|
||||||
#endif
|
#endif
|
||||||
unsigned char buf[SECTOR_SIZE];
|
unsigned char buf[MAX_SECTOR_SIZE];
|
||||||
int i;
|
int i;
|
||||||
long sector;
|
long sector;
|
||||||
int rc;
|
int rc;
|
||||||
|
@ -1716,10 +1742,10 @@ int fat_closewrite(struct fat_file *file, long size, int attr)
|
||||||
LDEBUGF("cluster %ld: %lx\n", count, next);
|
LDEBUGF("cluster %ld: %lx\n", count, next);
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
len = count * fat_bpb->bpb_secperclus * SECTOR_SIZE;
|
len = count * fat_bpb->bpb_secperclus * fat_bpb->bpb_bytspersec;
|
||||||
LDEBUGF("File is %ld clusters (chainlen=%ld, size=%ld)\n",
|
LDEBUGF("File is %ld clusters (chainlen=%ld, size=%ld)\n",
|
||||||
count, len, size );
|
count, len, size );
|
||||||
if ( len > size + fat_bpb->bpb_secperclus * SECTOR_SIZE)
|
if ( len > size + fat_bpb->bpb_secperclus * fat_bpb->bpb_bytspersec)
|
||||||
panicf("Cluster chain is too long\n");
|
panicf("Cluster chain is too long\n");
|
||||||
if ( len < size )
|
if ( len < size )
|
||||||
panicf("Cluster chain is too short\n");
|
panicf("Cluster chain is too short\n");
|
||||||
|
@ -1731,7 +1757,12 @@ int fat_closewrite(struct fat_file *file, long size, int attr)
|
||||||
|
|
||||||
static int free_direntries(struct fat_file* file)
|
static int free_direntries(struct fat_file* file)
|
||||||
{
|
{
|
||||||
unsigned char buf[SECTOR_SIZE];
|
#ifdef HAVE_MULTIVOLUME
|
||||||
|
struct bpb *fat_bpb = &fat_bpbs[file->volume];
|
||||||
|
#else
|
||||||
|
struct bpb *fat_bpb = &fat_bpbs[0];
|
||||||
|
#endif
|
||||||
|
unsigned char buf[MAX_SECTOR_SIZE];
|
||||||
struct fat_file dir;
|
struct fat_file dir;
|
||||||
int numentries = file->direntries;
|
int numentries = file->direntries;
|
||||||
unsigned int entry = file->direntry - numentries + 1;
|
unsigned int entry = file->direntry - numentries + 1;
|
||||||
|
@ -1934,6 +1965,9 @@ static int transfer(IF_MV2(struct bpb* fat_bpb,)
|
||||||
#endif
|
#endif
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
start *= fat_bpb->secmult;
|
||||||
|
count *= fat_bpb->secmult;
|
||||||
|
|
||||||
LDEBUGF("transfer(s=%lx, c=%lx, %s)\n",
|
LDEBUGF("transfer(s=%lx, c=%lx, %s)\n",
|
||||||
start+ fat_bpb->startsector, count, write?"write":"read");
|
start+ fat_bpb->startsector, count, write?"write":"read");
|
||||||
if (write) {
|
if (write) {
|
||||||
|
@ -1945,9 +1979,9 @@ static int transfer(IF_MV2(struct bpb* fat_bpb,)
|
||||||
#endif
|
#endif
|
||||||
firstallowed = fat_bpb->firstdatasector;
|
firstallowed = fat_bpb->firstdatasector;
|
||||||
|
|
||||||
if (start < firstallowed)
|
if (start < (firstallowed * fat_bpb->secmult))
|
||||||
panicf("Write %ld before data\n", firstallowed - start);
|
panicf("Write %ld before data\n", firstallowed - start);
|
||||||
if (start + count > fat_bpb->totalsectors)
|
if (start + count > (fat_bpb->totalsectors * fat_bpb->secmult))
|
||||||
panicf("Write %ld after data\n",
|
panicf("Write %ld after data\n",
|
||||||
start + count - fat_bpb->totalsectors);
|
start + count - fat_bpb->totalsectors);
|
||||||
rc = ata_write_sectors(IF_MV2(fat_bpb->drive,)
|
rc = ata_write_sectors(IF_MV2(fat_bpb->drive,)
|
||||||
|
@ -2041,13 +2075,14 @@ long fat_readwrite( struct fat_file *file, long sectorcount,
|
||||||
first = sector;
|
first = sector;
|
||||||
|
|
||||||
if ( ((sector != first) && (sector != last+1)) || /* not sequential */
|
if ( ((sector != first) && (sector != last+1)) || /* not sequential */
|
||||||
(last-first+1 == 256) ) { /* max 256 sectors per ata request */
|
(last-first+1 == (256 / fat_bpb->secmult)) ) {
|
||||||
|
/* max 256 sectors per ata request */
|
||||||
long count = last - first + 1;
|
long count = last - first + 1;
|
||||||
rc = transfer(IF_MV2(fat_bpb,) first, count, buf, write );
|
rc = transfer(IF_MV2(fat_bpb,) first, count, buf, write );
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
return rc * 10 - 1;
|
return rc * 10 - 1;
|
||||||
|
|
||||||
buf = (char *)buf + count * SECTOR_SIZE;
|
buf = (char *)buf + count * fat_bpb->bpb_bytspersec;
|
||||||
first = sector;
|
first = sector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2077,6 +2112,16 @@ long fat_readwrite( struct fat_file *file, long sectorcount,
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int fat_get_secsize(const struct fat_file *file)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_MULTIVOLUME
|
||||||
|
fat_bpbs[file->volume].bpb_bytspersec;
|
||||||
|
#else
|
||||||
|
(void)file;
|
||||||
|
return fat_bpbs[0].bpb_bytspersec;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int fat_seek(struct fat_file *file, unsigned long seeksector )
|
int fat_seek(struct fat_file *file, unsigned long seeksector )
|
||||||
{
|
{
|
||||||
#ifdef HAVE_MULTIVOLUME
|
#ifdef HAVE_MULTIVOLUME
|
||||||
|
@ -2196,6 +2241,11 @@ static int fat_copy_long_name_segment(unsigned char *utf16src,
|
||||||
|
|
||||||
int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry)
|
int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry)
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_MULTIVOLUME
|
||||||
|
struct bpb* fat_bpb = &fat_bpbs[dir->file.volume];
|
||||||
|
#else
|
||||||
|
struct bpb* fat_bpb = &fat_bpbs[0];
|
||||||
|
#endif
|
||||||
bool done = false;
|
bool done = false;
|
||||||
int i;
|
int i;
|
||||||
int rc;
|
int rc;
|
||||||
|
@ -2229,7 +2279,7 @@ int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = dir->entry % DIR_ENTRIES_PER_SECTOR;
|
for (i = dir->entry % DIR_ENTRIES_PER_SECTOR;
|
||||||
i < DIR_ENTRIES_PER_SECTOR; i++)
|
i < (int)DIR_ENTRIES_PER_SECTOR; i++)
|
||||||
{
|
{
|
||||||
unsigned int entrypos = i * DIR_ENTRY_SIZE;
|
unsigned int entrypos = i * DIR_ENTRY_SIZE;
|
||||||
|
|
||||||
|
@ -2283,20 +2333,20 @@ int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry)
|
||||||
unsigned char* ptr = cached_buf;
|
unsigned char* ptr = cached_buf;
|
||||||
int index = longarray[j];
|
int index = longarray[j];
|
||||||
/* current or cached sector? */
|
/* current or cached sector? */
|
||||||
if ( sectoridx >= SECTOR_SIZE ) {
|
if ( sectoridx >= fat_bpb->bpb_bytspersec ) {
|
||||||
if ( sectoridx >= SECTOR_SIZE*2 ) {
|
if ( sectoridx >= fat_bpb->bpb_bytspersec*2 ) {
|
||||||
if ( ( index >= SECTOR_SIZE ) &&
|
if ( ( index >= fat_bpb->bpb_bytspersec ) &&
|
||||||
( index < SECTOR_SIZE*2 ))
|
( index < fat_bpb->bpb_bytspersec*2 ))
|
||||||
ptr = dir->sectorcache[1];
|
ptr = dir->sectorcache[1];
|
||||||
else
|
else
|
||||||
ptr = dir->sectorcache[2];
|
ptr = dir->sectorcache[2];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ( index < SECTOR_SIZE )
|
if ( index < fat_bpb->bpb_bytspersec )
|
||||||
ptr = dir->sectorcache[1];
|
ptr = dir->sectorcache[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
index &= SECTOR_SIZE-1;
|
index &= fat_bpb->bpb_bytspersec-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Try to append each segment of the long name. Check if we'd
|
/* Try to append each segment of the long name. Check if we'd
|
||||||
|
@ -2356,10 +2406,10 @@ int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry)
|
||||||
|
|
||||||
/* save this sector, for longname use */
|
/* save this sector, for longname use */
|
||||||
if ( sectoridx )
|
if ( sectoridx )
|
||||||
memcpy( dir->sectorcache[2], dir->sectorcache[0], SECTOR_SIZE );
|
memcpy( dir->sectorcache[2], dir->sectorcache[0], fat_bpb->bpb_bytspersec );
|
||||||
else
|
else
|
||||||
memcpy( dir->sectorcache[1], dir->sectorcache[0], SECTOR_SIZE );
|
memcpy( dir->sectorcache[1], dir->sectorcache[0], fat_bpb->bpb_bytspersec );
|
||||||
sectoridx += SECTOR_SIZE;
|
sectoridx += fat_bpb->bpb_bytspersec;
|
||||||
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2371,7 +2421,7 @@ unsigned int fat_get_cluster_size(IF_MV_NONVOID(int volume))
|
||||||
const int volume = 0;
|
const int volume = 0;
|
||||||
#endif
|
#endif
|
||||||
struct bpb* fat_bpb = &fat_bpbs[volume];
|
struct bpb* fat_bpb = &fat_bpbs[volume];
|
||||||
return fat_bpb->bpb_secperclus * SECTOR_SIZE;
|
return fat_bpb->bpb_secperclus * fat_bpb->bpb_bytspersec;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_MULTIVOLUME
|
#ifdef HAVE_MULTIVOLUME
|
||||||
|
|
|
@ -22,8 +22,16 @@
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "ata.h" /* for volume definitions */
|
#include "ata.h" /* for volume definitions */
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
#define SECTOR_SIZE 512
|
#define PHYSICAL_SECTOR_SIZE 512
|
||||||
|
|
||||||
|
/* Some never players (such as iPod 5.5G) might have 2048 bytes per sector. */
|
||||||
|
#ifdef IPOD_VIDEO
|
||||||
|
#define MAX_SECTOR_SIZE 2048
|
||||||
|
#else
|
||||||
|
#define MAX_SECTOR_SIZE 512
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Number of bytes reserved for a file name (including the trailing \0).
|
/* Number of bytes reserved for a file name (including the trailing \0).
|
||||||
Since names are stored in the entry as UTF-8, we won't be able to
|
Since names are stored in the entry as UTF-8, we won't be able to
|
||||||
|
@ -78,7 +86,7 @@ struct fat_dir
|
||||||
unsigned int entrycount;
|
unsigned int entrycount;
|
||||||
long sector;
|
long sector;
|
||||||
struct fat_file file;
|
struct fat_file file;
|
||||||
unsigned char sectorcache[3][SECTOR_SIZE];
|
unsigned char sectorcache[3][MAX_SECTOR_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -101,6 +109,7 @@ extern int fat_create_file(const char* name,
|
||||||
extern long fat_readwrite(struct fat_file *ent, long sectorcount,
|
extern long fat_readwrite(struct fat_file *ent, long sectorcount,
|
||||||
void* buf, bool write );
|
void* buf, bool write );
|
||||||
extern int fat_closewrite(struct fat_file *ent, long size, int attr);
|
extern int fat_closewrite(struct fat_file *ent, long size, int attr);
|
||||||
|
extern int fat_get_secsize(const struct fat_file *file);
|
||||||
extern int fat_seek(struct fat_file *ent, unsigned long sector );
|
extern int fat_seek(struct fat_file *ent, unsigned long sector );
|
||||||
extern int fat_remove(struct fat_file *ent);
|
extern int fat_remove(struct fat_file *ent);
|
||||||
extern int fat_truncate(const struct fat_file *ent);
|
extern int fat_truncate(const struct fat_file *ent);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue