mirror of
https://github.com/wiiu-env/libfat.git
synced 2024-11-25 19:36:52 +01:00
support > 512 bytes per sector in libfat (dimok)
This commit is contained in:
parent
566206a741
commit
d5f437723f
@ -46,7 +46,7 @@
|
||||
|
||||
#define CACHE_FREE UINT_MAX
|
||||
|
||||
CACHE* _FAT_cache_constructor (unsigned int numberOfPages, unsigned int sectorsPerPage, const DISC_INTERFACE* discInterface, sec_t endOfPartition) {
|
||||
CACHE* _FAT_cache_constructor (unsigned int numberOfPages, unsigned int sectorsPerPage, const DISC_INTERFACE* discInterface, sec_t endOfPartition, unsigned int bytesPerSector) {
|
||||
CACHE* cache;
|
||||
unsigned int i;
|
||||
CACHE_ENTRY* cacheEntries;
|
||||
@ -68,6 +68,7 @@ CACHE* _FAT_cache_constructor (unsigned int numberOfPages, unsigned int sectorsP
|
||||
cache->endOfPartition = endOfPartition;
|
||||
cache->numberOfPages = numberOfPages;
|
||||
cache->sectorsPerPage = sectorsPerPage;
|
||||
cache->bytesPerSector = bytesPerSector;
|
||||
|
||||
|
||||
cacheEntries = (CACHE_ENTRY*) _FAT_mem_allocate ( sizeof(CACHE_ENTRY) * numberOfPages);
|
||||
@ -81,7 +82,7 @@ CACHE* _FAT_cache_constructor (unsigned int numberOfPages, unsigned int sectorsP
|
||||
cacheEntries[i].count = 0;
|
||||
cacheEntries[i].last_access = 0;
|
||||
cacheEntries[i].dirty = false;
|
||||
cacheEntries[i].cache = (uint8_t*) _FAT_mem_align ( sectorsPerPage * BYTES_PER_READ );
|
||||
cacheEntries[i].cache = (uint8_t*) _FAT_mem_align ( sectorsPerPage * bytesPerSector );
|
||||
}
|
||||
|
||||
cache->cacheEntries = cacheEntries;
|
||||
@ -168,9 +169,9 @@ bool _FAT_cache_readSectors(CACHE *cache,sec_t sector,sec_t numSectors,void *buf
|
||||
secs_to_read = entry->count - sec;
|
||||
if(secs_to_read>numSectors) secs_to_read = numSectors;
|
||||
|
||||
memcpy(dest,entry->cache + (sec*BYTES_PER_READ),(secs_to_read*BYTES_PER_READ));
|
||||
memcpy(dest,entry->cache + (sec*cache->bytesPerSector),(secs_to_read*cache->bytesPerSector));
|
||||
|
||||
dest += (secs_to_read*BYTES_PER_READ);
|
||||
dest += (secs_to_read*cache->bytesPerSector);
|
||||
sector += secs_to_read;
|
||||
numSectors -= secs_to_read;
|
||||
}
|
||||
@ -186,13 +187,13 @@ bool _FAT_cache_readPartialSector (CACHE* cache, void* buffer, sec_t sector, uns
|
||||
sec_t sec;
|
||||
CACHE_ENTRY *entry;
|
||||
|
||||
if (offset + size > BYTES_PER_READ) return false;
|
||||
if (offset + size > cache->bytesPerSector) return false;
|
||||
|
||||
entry = _FAT_cache_getPage(cache,sector);
|
||||
if(entry==NULL) return false;
|
||||
|
||||
sec = sector - entry->sector;
|
||||
memcpy(buffer,entry->cache + ((sec*BYTES_PER_READ) + offset),size);
|
||||
memcpy(buffer,entry->cache + ((sec*cache->bytesPerSector) + offset),size);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -218,13 +219,13 @@ bool _FAT_cache_writePartialSector (CACHE* cache, const void* buffer, sec_t sect
|
||||
sec_t sec;
|
||||
CACHE_ENTRY *entry;
|
||||
|
||||
if (offset + size > BYTES_PER_READ) return false;
|
||||
if (offset + size > cache->bytesPerSector) return false;
|
||||
|
||||
entry = _FAT_cache_getPage(cache,sector);
|
||||
if(entry==NULL) return false;
|
||||
|
||||
sec = sector - entry->sector;
|
||||
memcpy(entry->cache + ((sec*BYTES_PER_READ) + offset),buffer,size);
|
||||
memcpy(entry->cache + ((sec*cache->bytesPerSector) + offset),buffer,size);
|
||||
|
||||
entry->dirty = true;
|
||||
return true;
|
||||
@ -251,14 +252,14 @@ bool _FAT_cache_eraseWritePartialSector (CACHE* cache, const void* buffer, sec_t
|
||||
sec_t sec;
|
||||
CACHE_ENTRY *entry;
|
||||
|
||||
if (offset + size > BYTES_PER_READ) return false;
|
||||
if (offset + size > cache->bytesPerSector) return false;
|
||||
|
||||
entry = _FAT_cache_getPage(cache,sector);
|
||||
if(entry==NULL) return false;
|
||||
|
||||
sec = sector - entry->sector;
|
||||
memset(entry->cache + (sec*BYTES_PER_READ),0,BYTES_PER_READ);
|
||||
memcpy(entry->cache + ((sec*BYTES_PER_READ) + offset),buffer,size);
|
||||
memset(entry->cache + (sec*cache->bytesPerSector),0,cache->bytesPerSector);
|
||||
memcpy(entry->cache + ((sec*cache->bytesPerSector) + offset),buffer,size);
|
||||
|
||||
entry->dirty = true;
|
||||
return true;
|
||||
@ -281,9 +282,9 @@ bool _FAT_cache_writeSectors (CACHE* cache, sec_t sector, sec_t numSectors, cons
|
||||
secs_to_write = entry->count - sec;
|
||||
if(secs_to_write>numSectors) secs_to_write = numSectors;
|
||||
|
||||
memcpy(entry->cache + (sec*BYTES_PER_READ),src,(secs_to_write*BYTES_PER_READ));
|
||||
memcpy(entry->cache + (sec*cache->bytesPerSector),src,(secs_to_write*cache->bytesPerSector));
|
||||
|
||||
src += (secs_to_write*BYTES_PER_READ);
|
||||
src += (secs_to_write*cache->bytesPerSector);
|
||||
sector += secs_to_write;
|
||||
numSectors -= secs_to_write;
|
||||
|
||||
|
@ -39,9 +39,6 @@
|
||||
#include "common.h"
|
||||
#include "disc.h"
|
||||
|
||||
#define PAGE_SECTORS 64
|
||||
#define CACHE_PAGE_SIZE (BYTES_PER_READ * PAGE_SECTORS)
|
||||
|
||||
typedef struct {
|
||||
sec_t sector;
|
||||
unsigned int count;
|
||||
@ -55,6 +52,7 @@ typedef struct {
|
||||
sec_t endOfPartition;
|
||||
unsigned int numberOfPages;
|
||||
unsigned int sectorsPerPage;
|
||||
unsigned int bytesPerSector;
|
||||
CACHE_ENTRY* cacheEntries;
|
||||
} CACHE;
|
||||
|
||||
@ -100,14 +98,14 @@ bool _FAT_cache_readSectors (CACHE* cache, sec_t sector, sec_t numSectors, void*
|
||||
Read a full sector from the cache
|
||||
*/
|
||||
static inline bool _FAT_cache_readSector (CACHE* cache, void* buffer, sec_t sector) {
|
||||
return _FAT_cache_readPartialSector (cache, buffer, sector, 0, BYTES_PER_READ);
|
||||
return _FAT_cache_readPartialSector (cache, buffer, sector, 0, cache->bytesPerSector);
|
||||
}
|
||||
|
||||
/*
|
||||
Write a full sector to the cache
|
||||
*/
|
||||
static inline bool _FAT_cache_writeSector (CACHE* cache, const void* buffer, sec_t sector) {
|
||||
return _FAT_cache_writePartialSector (cache, buffer, sector, 0, BYTES_PER_READ);
|
||||
return _FAT_cache_writePartialSector (cache, buffer, sector, 0, cache->bytesPerSector);
|
||||
}
|
||||
|
||||
bool _FAT_cache_writeSectors (CACHE* cache, sec_t sector, sec_t numSectors, const void* buffer);
|
||||
@ -122,7 +120,7 @@ Clear out the contents of the cache without writing any dirty sectors first
|
||||
*/
|
||||
void _FAT_cache_invalidate (CACHE* cache);
|
||||
|
||||
CACHE* _FAT_cache_constructor (unsigned int numberOfPages, unsigned int sectorsPerPage, const DISC_INTERFACE* discInterface, sec_t endOfPartition);
|
||||
CACHE* _FAT_cache_constructor (unsigned int numberOfPages, unsigned int sectorsPerPage, const DISC_INTERFACE* discInterface, sec_t endOfPartition, unsigned int bytesPerSector);
|
||||
|
||||
void _FAT_cache_destructor (CACHE* cache);
|
||||
|
||||
|
@ -29,7 +29,6 @@
|
||||
#ifndef _COMMON_H
|
||||
#define _COMMON_H
|
||||
|
||||
#define BYTES_PER_READ 512
|
||||
#include <fat.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
@ -251,7 +251,7 @@ static bool _FAT_directory_incrementDirEntryPosition (PARTITION* partition, DIR_
|
||||
|
||||
// Increment offset, wrapping at the end of a sector
|
||||
++ position.offset;
|
||||
if (position.offset == BYTES_PER_READ / DIR_ENTRY_DATA_SIZE) {
|
||||
if (position.offset == partition->bytesPerSector / DIR_ENTRY_DATA_SIZE) {
|
||||
position.offset = 0;
|
||||
// Increment sector when wrapping
|
||||
++ position.sector;
|
||||
@ -1113,8 +1113,8 @@ void _FAT_directory_entryStat (PARTITION* partition, DIR_ENTRY* entry, struct st
|
||||
u8array_to_u16 (entry->entryData, DIR_ENTRY_cDate)
|
||||
);
|
||||
st->st_spare3 = 0;
|
||||
st->st_blksize = BYTES_PER_READ; // Prefered file I/O block size
|
||||
st->st_blocks = (st->st_size + BYTES_PER_READ - 1) / BYTES_PER_READ; // File size in blocks
|
||||
st->st_blksize = partition->bytesPerSector; // Prefered file I/O block size
|
||||
st->st_blocks = (st->st_size + partition->bytesPerSector - 1) / partition->bytesPerSector; // File size in blocks
|
||||
st->st_spare4[0] = 0;
|
||||
st->st_spare4[1] = 0;
|
||||
}
|
||||
|
@ -216,8 +216,8 @@ int _FAT_open_r (struct _reent *r, void *fileStruct, const char *path, int flags
|
||||
|
||||
// Set append pointer to the end of the file
|
||||
file->appendPosition.cluster = _FAT_fat_lastCluster (partition, file->startCluster);
|
||||
file->appendPosition.sector = (file->filesize % partition->bytesPerCluster) / BYTES_PER_READ;
|
||||
file->appendPosition.byte = file->filesize % BYTES_PER_READ;
|
||||
file->appendPosition.sector = (file->filesize % partition->bytesPerCluster) / partition->bytesPerSector;
|
||||
file->appendPosition.byte = file->filesize % partition->bytesPerSector;
|
||||
|
||||
// Check if the end of the file is on the end of a cluster
|
||||
if ( (file->filesize > 0) && ((file->filesize % partition->bytesPerCluster)==0) ){
|
||||
@ -381,12 +381,12 @@ ssize_t _FAT_read_r (struct _reent *r, int fd, char *ptr, size_t len) {
|
||||
cache = file->partition->cache;
|
||||
|
||||
// Align to sector
|
||||
tempVar = BYTES_PER_READ - position.byte;
|
||||
tempVar = partition->bytesPerSector - position.byte;
|
||||
if (tempVar > remain) {
|
||||
tempVar = remain;
|
||||
}
|
||||
|
||||
if ((tempVar < BYTES_PER_READ) && flagNoError)
|
||||
if ((tempVar < partition->bytesPerSector) && flagNoError)
|
||||
{
|
||||
_FAT_cache_readPartialSector ( cache, ptr, _FAT_fat_clusterToSector (partition, position.cluster) + position.sector,
|
||||
position.byte, tempVar);
|
||||
@ -395,7 +395,7 @@ ssize_t _FAT_read_r (struct _reent *r, int fd, char *ptr, size_t len) {
|
||||
ptr += tempVar;
|
||||
|
||||
position.byte += tempVar;
|
||||
if (position.byte >= BYTES_PER_READ) {
|
||||
if (position.byte >= partition->bytesPerSector) {
|
||||
position.byte = 0;
|
||||
position.sector++;
|
||||
}
|
||||
@ -403,10 +403,10 @@ ssize_t _FAT_read_r (struct _reent *r, int fd, char *ptr, size_t len) {
|
||||
|
||||
// align to cluster
|
||||
// tempVar is number of sectors to read
|
||||
if (remain > (partition->sectorsPerCluster - position.sector) * BYTES_PER_READ) {
|
||||
if (remain > (partition->sectorsPerCluster - position.sector) * partition->bytesPerSector) {
|
||||
tempVar = partition->sectorsPerCluster - position.sector;
|
||||
} else {
|
||||
tempVar = remain / BYTES_PER_READ;
|
||||
tempVar = remain / partition->bytesPerSector;
|
||||
}
|
||||
|
||||
if ((tempVar > 0) && flagNoError) {
|
||||
@ -416,8 +416,8 @@ ssize_t _FAT_read_r (struct _reent *r, int fd, char *ptr, size_t len) {
|
||||
flagNoError = false;
|
||||
r->_errno = EIO;
|
||||
} else {
|
||||
ptr += tempVar * BYTES_PER_READ;
|
||||
remain -= tempVar * BYTES_PER_READ;
|
||||
ptr += tempVar * partition->bytesPerSector;
|
||||
remain -= tempVar * partition->bytesPerSector;
|
||||
position.sector += tempVar;
|
||||
}
|
||||
}
|
||||
@ -449,12 +449,12 @@ ssize_t _FAT_read_r (struct _reent *r, int fd, char *ptr, size_t len) {
|
||||
chunkSize += partition->bytesPerCluster;
|
||||
} while ((nextChunkStart == chunkEnd + 1) &&
|
||||
#ifdef LIMIT_SECTORS
|
||||
(chunkSize + partition->bytesPerCluster <= LIMIT_SECTORS * BYTES_PER_READ) &&
|
||||
(chunkSize + partition->bytesPerCluster <= LIMIT_SECTORS * partition->bytesPerSector) &&
|
||||
#endif
|
||||
(chunkSize + partition->bytesPerCluster <= remain));
|
||||
|
||||
if (!_FAT_cache_readSectors (cache, _FAT_fat_clusterToSector (partition, position.cluster),
|
||||
chunkSize / BYTES_PER_READ, ptr))
|
||||
chunkSize / partition->bytesPerSector, ptr))
|
||||
{
|
||||
flagNoError = false;
|
||||
r->_errno = EIO;
|
||||
@ -477,7 +477,7 @@ ssize_t _FAT_read_r (struct _reent *r, int fd, char *ptr, size_t len) {
|
||||
}
|
||||
|
||||
// Read remaining sectors
|
||||
tempVar = remain / BYTES_PER_READ; // Number of sectors left
|
||||
tempVar = remain / partition->bytesPerSector; // Number of sectors left
|
||||
if ((tempVar > 0) && flagNoError) {
|
||||
if (!_FAT_cache_readSectors (cache, _FAT_fat_clusterToSector (partition, position.cluster),
|
||||
tempVar, ptr))
|
||||
@ -485,8 +485,8 @@ ssize_t _FAT_read_r (struct _reent *r, int fd, char *ptr, size_t len) {
|
||||
flagNoError = false;
|
||||
r->_errno = EIO;
|
||||
} else {
|
||||
ptr += tempVar * BYTES_PER_READ;
|
||||
remain -= tempVar * BYTES_PER_READ;
|
||||
ptr += tempVar * partition->bytesPerSector;
|
||||
remain -= tempVar * partition->bytesPerSector;
|
||||
position.sector += tempVar;
|
||||
}
|
||||
}
|
||||
@ -555,13 +555,14 @@ static bool _FAT_file_extend_r (struct _reent *r, FILE_STRUCT* file) {
|
||||
PARTITION* partition = file->partition;
|
||||
CACHE* cache = file->partition->cache;
|
||||
FILE_POSITION position;
|
||||
uint8_t zeroBuffer [BYTES_PER_READ] = {0};
|
||||
uint8_t zeroBuffer [partition->bytesPerSector];
|
||||
memset(zeroBuffer, 0, partition->bytesPerSector);
|
||||
uint32_t remain;
|
||||
uint32_t tempNextCluster;
|
||||
unsigned int sector;
|
||||
|
||||
position.byte = file->filesize % BYTES_PER_READ;
|
||||
position.sector = (file->filesize % partition->bytesPerCluster) / BYTES_PER_READ;
|
||||
position.byte = file->filesize % partition->bytesPerSector;
|
||||
position.sector = (file->filesize % partition->bytesPerCluster) / partition->bytesPerSector;
|
||||
// It is assumed that there is always a startCluster
|
||||
// This will be true when _FAT_file_extend_r is called from _FAT_write_r
|
||||
position.cluster = _FAT_fat_lastCluster (partition, file->startCluster);
|
||||
@ -580,7 +581,7 @@ static bool _FAT_file_extend_r (struct _reent *r, FILE_STRUCT* file) {
|
||||
position.sector = 0;
|
||||
}
|
||||
|
||||
if (remain + position.byte < BYTES_PER_READ) {
|
||||
if (remain + position.byte < partition->bytesPerSector) {
|
||||
// Only need to clear to the end of the sector
|
||||
_FAT_cache_writePartialSector (cache, zeroBuffer,
|
||||
_FAT_fat_clusterToSector (partition, position.cluster) + position.sector, position.byte, remain);
|
||||
@ -589,13 +590,13 @@ static bool _FAT_file_extend_r (struct _reent *r, FILE_STRUCT* file) {
|
||||
if (position.byte > 0) {
|
||||
_FAT_cache_writePartialSector (cache, zeroBuffer,
|
||||
_FAT_fat_clusterToSector (partition, position.cluster) + position.sector, position.byte,
|
||||
BYTES_PER_READ - position.byte);
|
||||
remain -= (BYTES_PER_READ - position.byte);
|
||||
partition->bytesPerSector - position.byte);
|
||||
remain -= (partition->bytesPerSector - position.byte);
|
||||
position.byte = 0;
|
||||
position.sector ++;
|
||||
}
|
||||
|
||||
while (remain >= BYTES_PER_READ) {
|
||||
while (remain >= partition->bytesPerSector) {
|
||||
if (position.sector >= partition->sectorsPerCluster) {
|
||||
position.sector = 0;
|
||||
// Ran out of clusters so get a new one
|
||||
@ -611,7 +612,7 @@ static bool _FAT_file_extend_r (struct _reent *r, FILE_STRUCT* file) {
|
||||
sector = _FAT_fat_clusterToSector (partition, position.cluster) + position.sector;
|
||||
_FAT_cache_writeSectors (cache, sector, 1, zeroBuffer);
|
||||
|
||||
remain -= BYTES_PER_READ;
|
||||
remain -= partition->bytesPerSector;
|
||||
position.sector ++;
|
||||
}
|
||||
|
||||
@ -712,12 +713,12 @@ ssize_t _FAT_write_r (struct _reent *r, int fd, const char *ptr, size_t len) {
|
||||
_FAT_check_position_for_next_cluster(r, &position, partition, remain, &flagNoError);
|
||||
|
||||
// Align to sector
|
||||
tempVar = BYTES_PER_READ - position.byte;
|
||||
tempVar = partition->bytesPerSector - position.byte;
|
||||
if (tempVar > remain) {
|
||||
tempVar = remain;
|
||||
}
|
||||
|
||||
if ((tempVar < BYTES_PER_READ) && flagNoError) {
|
||||
if ((tempVar < partition->bytesPerSector) && flagNoError) {
|
||||
// Write partial sector to disk
|
||||
_FAT_cache_writePartialSector (cache, ptr,
|
||||
_FAT_fat_clusterToSector (partition, position.cluster) + position.sector, position.byte, tempVar);
|
||||
@ -728,7 +729,7 @@ ssize_t _FAT_write_r (struct _reent *r, int fd, const char *ptr, size_t len) {
|
||||
|
||||
|
||||
// Move onto next sector
|
||||
if (position.byte >= BYTES_PER_READ) {
|
||||
if (position.byte >= partition->bytesPerSector) {
|
||||
position.byte = 0;
|
||||
position.sector ++;
|
||||
}
|
||||
@ -736,10 +737,10 @@ ssize_t _FAT_write_r (struct _reent *r, int fd, const char *ptr, size_t len) {
|
||||
|
||||
// Align to cluster
|
||||
// tempVar is number of sectors to write
|
||||
if (remain > (partition->sectorsPerCluster - position.sector) * BYTES_PER_READ) {
|
||||
if (remain > (partition->sectorsPerCluster - position.sector) * partition->bytesPerSector) {
|
||||
tempVar = partition->sectorsPerCluster - position.sector;
|
||||
} else {
|
||||
tempVar = remain / BYTES_PER_READ;
|
||||
tempVar = remain / partition->bytesPerSector;
|
||||
}
|
||||
|
||||
if ((tempVar > 0 && tempVar < partition->sectorsPerCluster) && flagNoError) {
|
||||
@ -749,8 +750,8 @@ ssize_t _FAT_write_r (struct _reent *r, int fd, const char *ptr, size_t len) {
|
||||
flagNoError = false;
|
||||
r->_errno = EIO;
|
||||
} else {
|
||||
ptr += tempVar * BYTES_PER_READ;
|
||||
remain -= tempVar * BYTES_PER_READ;
|
||||
ptr += tempVar * partition->bytesPerSector;
|
||||
remain -= tempVar * partition->bytesPerSector;
|
||||
position.sector += tempVar;
|
||||
}
|
||||
}
|
||||
@ -769,7 +770,7 @@ ssize_t _FAT_write_r (struct _reent *r, int fd, const char *ptr, size_t len) {
|
||||
// group consecutive clusters
|
||||
while (flagNoError &&
|
||||
#ifdef LIMIT_SECTORS
|
||||
(chunkSize + partition->bytesPerCluster <= LIMIT_SECTORS * BYTES_PER_READ) &&
|
||||
(chunkSize + partition->bytesPerCluster <= LIMIT_SECTORS * partition->bytesPerSector) &&
|
||||
#endif
|
||||
(chunkSize + partition->bytesPerCluster < remain))
|
||||
{
|
||||
@ -786,7 +787,7 @@ ssize_t _FAT_write_r (struct _reent *r, int fd, const char *ptr, size_t len) {
|
||||
}
|
||||
|
||||
if ( !_FAT_cache_writeSectors (cache,
|
||||
_FAT_fat_clusterToSector(partition, position.cluster), chunkSize / BYTES_PER_READ, ptr))
|
||||
_FAT_fat_clusterToSector(partition, position.cluster), chunkSize / partition->bytesPerSector, ptr))
|
||||
{
|
||||
flagNoError = false;
|
||||
r->_errno = EIO;
|
||||
@ -810,15 +811,15 @@ ssize_t _FAT_write_r (struct _reent *r, int fd, const char *ptr, size_t len) {
|
||||
_FAT_check_position_for_next_cluster(r, &position, partition, remain, &flagNoError);
|
||||
|
||||
// Write remaining sectors
|
||||
tempVar = remain / BYTES_PER_READ; // Number of sectors left
|
||||
tempVar = remain / partition->bytesPerSector; // Number of sectors left
|
||||
if ((tempVar > 0) && flagNoError) {
|
||||
if (!_FAT_cache_writeSectors (cache, _FAT_fat_clusterToSector (partition, position.cluster), tempVar, ptr))
|
||||
{
|
||||
flagNoError = false;
|
||||
r->_errno = EIO;
|
||||
} else {
|
||||
ptr += tempVar * BYTES_PER_READ;
|
||||
remain -= tempVar * BYTES_PER_READ;
|
||||
ptr += tempVar * partition->bytesPerSector;
|
||||
remain -= tempVar * partition->bytesPerSector;
|
||||
position.sector += tempVar;
|
||||
}
|
||||
}
|
||||
@ -927,8 +928,8 @@ off_t _FAT_seek_r (struct _reent *r, int fd, off_t pos, int dir) {
|
||||
}
|
||||
// Calculate the sector and byte of the current position,
|
||||
// and store them
|
||||
file->rwPosition.sector = (position % partition->bytesPerCluster) / BYTES_PER_READ;
|
||||
file->rwPosition.byte = position % BYTES_PER_READ;
|
||||
file->rwPosition.sector = (position % partition->bytesPerCluster) / partition->bytesPerSector;
|
||||
file->rwPosition.byte = position % partition->bytesPerSector;
|
||||
|
||||
nextCluster = _FAT_fat_nextCluster (partition, cluster);
|
||||
while ((clusCount > 0) && (nextCluster != CLUSTER_FREE) && (nextCluster != CLUSTER_EOF)) {
|
||||
@ -1087,13 +1088,13 @@ int _FAT_ftruncate_r (struct _reent *r, int fd, off_t len) {
|
||||
lastCluster = _FAT_fat_trimChain (partition, file->startCluster, chainLength);
|
||||
|
||||
if (file->append) {
|
||||
file->appendPosition.byte = newSize % BYTES_PER_READ;
|
||||
file->appendPosition.byte = newSize % partition->bytesPerSector;
|
||||
// Does the end of the file fall on the edge of a cluster?
|
||||
if (newSize % partition->bytesPerCluster == 0) {
|
||||
// Set a flag to allocate a new cluster
|
||||
file->appendPosition.sector = partition->sectorsPerCluster;
|
||||
} else {
|
||||
file->appendPosition.sector = (newSize % partition->bytesPerCluster) / BYTES_PER_READ;
|
||||
file->appendPosition.sector = (newSize % partition->bytesPerCluster) / partition->bytesPerSector;
|
||||
}
|
||||
file->appendPosition.cluster = lastCluster;
|
||||
}
|
||||
|
@ -54,15 +54,15 @@ uint32_t _FAT_fat_nextCluster(PARTITION* partition, uint32_t cluster)
|
||||
case FS_FAT12:
|
||||
{
|
||||
u32 nextCluster_h;
|
||||
sector = partition->fat.fatStart + (((cluster * 3) / 2) / BYTES_PER_READ);
|
||||
offset = ((cluster * 3) / 2) % BYTES_PER_READ;
|
||||
sector = partition->fat.fatStart + (((cluster * 3) / 2) / partition->bytesPerSector);
|
||||
offset = ((cluster * 3) / 2) % partition->bytesPerSector;
|
||||
|
||||
|
||||
_FAT_cache_readLittleEndianValue (partition->cache, &nextCluster, sector, offset, sizeof(u8));
|
||||
|
||||
offset++;
|
||||
|
||||
if (offset >= BYTES_PER_READ) {
|
||||
if (offset >= partition->bytesPerSector) {
|
||||
offset = 0;
|
||||
sector++;
|
||||
}
|
||||
@ -85,8 +85,8 @@ uint32_t _FAT_fat_nextCluster(PARTITION* partition, uint32_t cluster)
|
||||
break;
|
||||
}
|
||||
case FS_FAT16:
|
||||
sector = partition->fat.fatStart + ((cluster << 1) / BYTES_PER_READ);
|
||||
offset = (cluster % (BYTES_PER_READ >> 1)) << 1;
|
||||
sector = partition->fat.fatStart + ((cluster << 1) / partition->bytesPerSector);
|
||||
offset = (cluster % (partition->bytesPerSector >> 1)) << 1;
|
||||
|
||||
_FAT_cache_readLittleEndianValue (partition->cache, &nextCluster, sector, offset, sizeof(u16));
|
||||
|
||||
@ -96,8 +96,8 @@ uint32_t _FAT_fat_nextCluster(PARTITION* partition, uint32_t cluster)
|
||||
break;
|
||||
|
||||
case FS_FAT32:
|
||||
sector = partition->fat.fatStart + ((cluster << 2) / BYTES_PER_READ);
|
||||
offset = (cluster % (BYTES_PER_READ >> 2)) << 2;
|
||||
sector = partition->fat.fatStart + ((cluster << 2) / partition->bytesPerSector);
|
||||
offset = (cluster % (partition->bytesPerSector >> 2)) << 2;
|
||||
|
||||
_FAT_cache_readLittleEndianValue (partition->cache, &nextCluster, sector, offset, sizeof(u32));
|
||||
|
||||
@ -135,8 +135,8 @@ static bool _FAT_fat_writeFatEntry (PARTITION* partition, uint32_t cluster, uint
|
||||
break;
|
||||
|
||||
case FS_FAT12:
|
||||
sector = partition->fat.fatStart + (((cluster * 3) / 2) / BYTES_PER_READ);
|
||||
offset = ((cluster * 3) / 2) % BYTES_PER_READ;
|
||||
sector = partition->fat.fatStart + (((cluster * 3) / 2) / partition->bytesPerSector);
|
||||
offset = ((cluster * 3) / 2) % partition->bytesPerSector;
|
||||
|
||||
if (cluster & 0x01) {
|
||||
|
||||
@ -147,7 +147,7 @@ static bool _FAT_fat_writeFatEntry (PARTITION* partition, uint32_t cluster, uint
|
||||
_FAT_cache_writeLittleEndianValue (partition->cache, value & 0xFF, sector, offset, sizeof(u8));
|
||||
|
||||
offset++;
|
||||
if (offset >= BYTES_PER_READ) {
|
||||
if (offset >= partition->bytesPerSector) {
|
||||
offset = 0;
|
||||
sector++;
|
||||
}
|
||||
@ -159,7 +159,7 @@ static bool _FAT_fat_writeFatEntry (PARTITION* partition, uint32_t cluster, uint
|
||||
_FAT_cache_writeLittleEndianValue (partition->cache, value, sector, offset, sizeof(u8));
|
||||
|
||||
offset++;
|
||||
if (offset >= BYTES_PER_READ) {
|
||||
if (offset >= partition->bytesPerSector) {
|
||||
offset = 0;
|
||||
sector++;
|
||||
}
|
||||
@ -174,16 +174,16 @@ static bool _FAT_fat_writeFatEntry (PARTITION* partition, uint32_t cluster, uint
|
||||
break;
|
||||
|
||||
case FS_FAT16:
|
||||
sector = partition->fat.fatStart + ((cluster << 1) / BYTES_PER_READ);
|
||||
offset = (cluster % (BYTES_PER_READ >> 1)) << 1;
|
||||
sector = partition->fat.fatStart + ((cluster << 1) / partition->bytesPerSector);
|
||||
offset = (cluster % (partition->bytesPerSector >> 1)) << 1;
|
||||
|
||||
_FAT_cache_writeLittleEndianValue (partition->cache, value, sector, offset, sizeof(u16));
|
||||
|
||||
break;
|
||||
|
||||
case FS_FAT32:
|
||||
sector = partition->fat.fatStart + ((cluster << 2) / BYTES_PER_READ);
|
||||
offset = (cluster % (BYTES_PER_READ >> 2)) << 2;
|
||||
sector = partition->fat.fatStart + ((cluster << 2) / partition->bytesPerSector);
|
||||
offset = (cluster % (partition->bytesPerSector >> 2)) << 2;
|
||||
|
||||
_FAT_cache_writeLittleEndianValue (partition->cache, value, sector, offset, sizeof(u32));
|
||||
|
||||
@ -269,7 +269,7 @@ If an error occurs, return CLUSTER_ERROR
|
||||
uint32_t _FAT_fat_linkFreeClusterCleared (PARTITION* partition, uint32_t cluster) {
|
||||
uint32_t newCluster;
|
||||
uint32_t i;
|
||||
uint8_t emptySector[BYTES_PER_READ];
|
||||
uint8_t emptySector[partition->bytesPerSector];
|
||||
|
||||
// Link the cluster
|
||||
newCluster = _FAT_fat_linkFreeCluster(partition, cluster);
|
||||
@ -279,7 +279,7 @@ uint32_t _FAT_fat_linkFreeClusterCleared (PARTITION* partition, uint32_t cluster
|
||||
}
|
||||
|
||||
// Clear all the sectors within the cluster
|
||||
memset (emptySector, 0, BYTES_PER_READ);
|
||||
memset (emptySector, 0, partition->bytesPerSector);
|
||||
for (i = 0; i < partition->sectorsPerCluster; i++) {
|
||||
_FAT_cache_writeSectors (partition->cache,
|
||||
_FAT_fat_clusterToSector (partition, newCluster) + i,
|
||||
|
@ -103,16 +103,20 @@ static const char FAT_SIG[3] = {'F', 'A', 'T'};
|
||||
static const char FS_INFO_SIG1[4] = {'R', 'R', 'a', 'A'};
|
||||
static const char FS_INFO_SIG2[4] = {'r', 'r', 'A', 'a'};
|
||||
|
||||
static uint8_t sectorBuffer[BYTES_PER_READ] __attribute__((aligned(32)));
|
||||
|
||||
sec_t FindFirstValidPartition(const DISC_INTERFACE* disc)
|
||||
{
|
||||
uint8_t part_table[16*4];
|
||||
uint8_t *ptr;
|
||||
int i;
|
||||
|
||||
uint8_t *sectorBuffer = (uint8_t*) _FAT_mem_allocate(MAX_SECTOR_SIZE);
|
||||
if(!sectorBuffer) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Read first sector of disc
|
||||
if (!_FAT_disc_readSectors (disc, 0, 1, sectorBuffer)) {
|
||||
_FAT_mem_free(sectorBuffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -124,6 +128,7 @@ sec_t FindFirstValidPartition(const DISC_INTERFACE* disc)
|
||||
|
||||
if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG)) ||
|
||||
!memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) {
|
||||
_FAT_mem_free(sectorBuffer);
|
||||
return part_lba;
|
||||
}
|
||||
|
||||
@ -136,29 +141,40 @@ sec_t FindFirstValidPartition(const DISC_INTERFACE* disc)
|
||||
|
||||
for(n=0;n<8;n++) // max 8 logic partitions
|
||||
{
|
||||
if(!_FAT_disc_readSectors (disc, part_lba+next_lba2, 1, sectorBuffer)) return 0;
|
||||
if(!_FAT_disc_readSectors (disc, part_lba+next_lba2, 1, sectorBuffer)) {
|
||||
_FAT_mem_free(sectorBuffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
part_lba2 = part_lba + next_lba2 + u8array_to_u32(sectorBuffer, 0x1C6) ;
|
||||
next_lba2 = u8array_to_u32(sectorBuffer, 0x1D6);
|
||||
|
||||
if(!_FAT_disc_readSectors (disc, part_lba2, 1, sectorBuffer)) return 0;
|
||||
if(!_FAT_disc_readSectors (disc, part_lba2, 1, sectorBuffer)) {
|
||||
_FAT_mem_free(sectorBuffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG)) ||
|
||||
!memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG)))
|
||||
{
|
||||
!memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) {
|
||||
_FAT_mem_free(sectorBuffer);
|
||||
return part_lba2;
|
||||
}
|
||||
|
||||
if(next_lba2==0) break;
|
||||
}
|
||||
} else {
|
||||
if(!_FAT_disc_readSectors (disc, part_lba, 1, sectorBuffer)) return 0;
|
||||
if(!_FAT_disc_readSectors (disc, part_lba, 1, sectorBuffer)) {
|
||||
_FAT_mem_free(sectorBuffer);
|
||||
return 0;
|
||||
}
|
||||
if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG)) ||
|
||||
!memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) {
|
||||
_FAT_mem_free(sectorBuffer);
|
||||
return part_lba;
|
||||
}
|
||||
}
|
||||
}
|
||||
_FAT_mem_free(sectorBuffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -166,13 +182,20 @@ sec_t FindFirstValidPartition(const DISC_INTERFACE* disc)
|
||||
PARTITION* _FAT_partition_constructor (const DISC_INTERFACE* disc, uint32_t cacheSize, uint32_t sectorsPerPage, sec_t startSector) {
|
||||
PARTITION* partition;
|
||||
|
||||
uint8_t *sectorBuffer = (uint8_t*) _FAT_mem_allocate(MAX_SECTOR_SIZE);
|
||||
if(!sectorBuffer) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Read first sector of disc
|
||||
if (!_FAT_disc_readSectors (disc, startSector, 1, sectorBuffer)) {
|
||||
_FAT_mem_free(sectorBuffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Make sure it is a valid MBR or boot sector
|
||||
if ( (sectorBuffer[BPB_bootSig_55] != 0x55) || (sectorBuffer[BPB_bootSig_AA] != 0xAA)) {
|
||||
_FAT_mem_free(sectorBuffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -187,19 +210,21 @@ PARTITION* _FAT_partition_constructor (const DISC_INTERFACE* disc, uint32_t cach
|
||||
} else {
|
||||
startSector = FindFirstValidPartition(disc);
|
||||
if (!_FAT_disc_readSectors (disc, startSector, 1, sectorBuffer)) {
|
||||
_FAT_mem_free(sectorBuffer);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Now verify that this is indeed a FAT partition
|
||||
if (memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG)) &&
|
||||
memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG)))
|
||||
{
|
||||
memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) {
|
||||
_FAT_mem_free(sectorBuffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
partition = (PARTITION*) _FAT_mem_allocate (sizeof(PARTITION));
|
||||
if (partition == NULL) {
|
||||
_FAT_mem_free(sectorBuffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -226,8 +251,15 @@ PARTITION* _FAT_partition_constructor (const DISC_INTERFACE* disc, uint32_t cach
|
||||
partition->numberOfSectors = u8array_to_u32( sectorBuffer, BPB_numSectors);
|
||||
}
|
||||
|
||||
partition->bytesPerSector = BYTES_PER_READ; // Sector size is redefined to be 512 bytes
|
||||
partition->sectorsPerCluster = sectorBuffer[BPB_sectorsPerCluster] * u8array_to_u16(sectorBuffer, BPB_bytesPerSector) / BYTES_PER_READ;
|
||||
partition->bytesPerSector = u8array_to_u16(sectorBuffer, BPB_bytesPerSector);
|
||||
if(partition->bytesPerSector < MIN_SECTOR_SIZE || partition->bytesPerSector > MAX_SECTOR_SIZE) {
|
||||
// Unsupported sector size
|
||||
_FAT_mem_free(sectorBuffer);
|
||||
_FAT_mem_free(partition);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
partition->sectorsPerCluster = sectorBuffer[BPB_sectorsPerCluster];
|
||||
partition->bytesPerCluster = partition->bytesPerSector * partition->sectorsPerCluster;
|
||||
partition->fat.fatStart = startSector + u8array_to_u16(sectorBuffer, BPB_reservedSectors);
|
||||
|
||||
@ -268,7 +300,7 @@ PARTITION* _FAT_partition_constructor (const DISC_INTERFACE* disc, uint32_t cach
|
||||
}
|
||||
|
||||
// Create a cache to use
|
||||
partition->cache = _FAT_cache_constructor (cacheSize, sectorsPerPage, partition->disc, startSector+partition->numberOfSectors);
|
||||
partition->cache = _FAT_cache_constructor (cacheSize, sectorsPerPage, partition->disc, startSector+partition->numberOfSectors, partition->bytesPerSector);
|
||||
|
||||
// Set current directory to the root
|
||||
partition->cwdCluster = partition->rootDirCluster;
|
||||
@ -282,6 +314,8 @@ PARTITION* _FAT_partition_constructor (const DISC_INTERFACE* disc, uint32_t cach
|
||||
|
||||
_FAT_partition_readFSinfo(partition);
|
||||
|
||||
_FAT_mem_free(sectorBuffer);
|
||||
|
||||
return partition;
|
||||
}
|
||||
|
||||
@ -328,8 +362,11 @@ void _FAT_partition_createFSinfo(PARTITION * partition)
|
||||
if(partition->readOnly || partition->filesysType != FS_FAT32)
|
||||
return;
|
||||
|
||||
uint8_t sectorBuffer[BYTES_PER_READ];
|
||||
memset(sectorBuffer, 0, sizeof(sectorBuffer));
|
||||
uint8_t *sectorBuffer = (uint8_t*) _FAT_mem_allocate(partition->bytesPerSector);
|
||||
if(!sectorBuffer) {
|
||||
return;
|
||||
}
|
||||
memset(sectorBuffer, 0, partition->bytesPerSector);
|
||||
|
||||
int i;
|
||||
for(i = 0; i < 4; ++i)
|
||||
@ -346,6 +383,8 @@ void _FAT_partition_createFSinfo(PARTITION * partition)
|
||||
sectorBuffer[FSIB_bootSig_AA] = 0xAA;
|
||||
|
||||
_FAT_disc_writeSectors (partition->disc, partition->fsInfoSector, 1, sectorBuffer);
|
||||
|
||||
_FAT_mem_free(sectorBuffer);
|
||||
}
|
||||
|
||||
void _FAT_partition_readFSinfo(PARTITION * partition)
|
||||
@ -353,24 +392,29 @@ void _FAT_partition_readFSinfo(PARTITION * partition)
|
||||
if(partition->filesysType != FS_FAT32)
|
||||
return;
|
||||
|
||||
uint8_t sectorBuffer[BYTES_PER_READ] = {0};
|
||||
|
||||
uint8_t *sectorBuffer = (uint8_t*) _FAT_mem_allocate(partition->bytesPerSector);
|
||||
if(!sectorBuffer) {
|
||||
return;
|
||||
}
|
||||
memset(sectorBuffer, 0, partition->bytesPerSector);
|
||||
// Read first sector of disc
|
||||
if (!_FAT_disc_readSectors (partition->disc, partition->fsInfoSector, 1, sectorBuffer)) {
|
||||
_FAT_mem_free(sectorBuffer);
|
||||
return;
|
||||
}
|
||||
|
||||
if(memcmp(sectorBuffer+FSIB_SIG1, FS_INFO_SIG1, 4) != 0 ||
|
||||
memcmp(sectorBuffer+FSIB_SIG2, FS_INFO_SIG2, 4) != 0 ||
|
||||
u8array_to_u32(sectorBuffer, FSIB_numberOfFreeCluster) == 0)
|
||||
{
|
||||
u8array_to_u32(sectorBuffer, FSIB_numberOfFreeCluster) == 0) {
|
||||
//sector does not yet exist, create one!
|
||||
_FAT_partition_createFSinfo(partition);
|
||||
_FAT_mem_free(sectorBuffer);
|
||||
return;
|
||||
}
|
||||
|
||||
partition->fat.numberFreeCluster = u8array_to_u32(sectorBuffer, FSIB_numberOfFreeCluster);
|
||||
partition->fat.numberLastAllocCluster = u8array_to_u32(sectorBuffer, FSIB_numberLastAllocCluster);
|
||||
_FAT_mem_free(sectorBuffer);
|
||||
}
|
||||
|
||||
void _FAT_partition_writeFSinfo(PARTITION * partition)
|
||||
@ -378,21 +422,26 @@ void _FAT_partition_writeFSinfo(PARTITION * partition)
|
||||
if(partition->filesysType != FS_FAT32)
|
||||
return;
|
||||
|
||||
uint8_t sectorBuffer[BYTES_PER_READ] = {0};
|
||||
|
||||
uint8_t *sectorBuffer = (uint8_t*) _FAT_mem_allocate(partition->bytesPerSector);
|
||||
if(!sectorBuffer) {
|
||||
return;
|
||||
}
|
||||
memset(sectorBuffer, 0, partition->bytesPerSector);
|
||||
// Read first sector of disc
|
||||
if (!_FAT_disc_readSectors (partition->disc, partition->fsInfoSector, 1, sectorBuffer)) {
|
||||
_FAT_mem_free(sectorBuffer);
|
||||
return;
|
||||
}
|
||||
|
||||
if(memcmp(sectorBuffer+FSIB_SIG1, FS_INFO_SIG1, 4) || memcmp(sectorBuffer+FSIB_SIG2, FS_INFO_SIG2, 4))
|
||||
if(memcmp(sectorBuffer+FSIB_SIG1, FS_INFO_SIG1, 4) || memcmp(sectorBuffer+FSIB_SIG2, FS_INFO_SIG2, 4)) {
|
||||
_FAT_mem_free(sectorBuffer);
|
||||
return;
|
||||
}
|
||||
|
||||
u32_to_u8array(sectorBuffer, FSIB_numberOfFreeCluster, partition->fat.numberFreeCluster);
|
||||
u32_to_u8array(sectorBuffer, FSIB_numberLastAllocCluster, partition->fat.numberLastAllocCluster);
|
||||
|
||||
// Read first sector of disc
|
||||
if (!_FAT_disc_writeSectors (partition->disc, partition->fsInfoSector, 1, sectorBuffer)) {
|
||||
return;
|
||||
}
|
||||
_FAT_disc_writeSectors (partition->disc, partition->fsInfoSector, 1, sectorBuffer);
|
||||
_FAT_mem_free(sectorBuffer);
|
||||
}
|
||||
|
@ -34,6 +34,9 @@
|
||||
#include "cache.h"
|
||||
#include "lock.h"
|
||||
|
||||
#define MIN_SECTOR_SIZE 512
|
||||
#define MAX_SECTOR_SIZE 4096
|
||||
|
||||
// Filesystem type
|
||||
typedef enum {FS_UNKNOWN, FS_FAT12, FS_FAT16, FS_FAT32} FS_TYPE;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user