566 lines
16 KiB
C
566 lines
16 KiB
C
|
// Filesystem implementation
|
||
|
#include "romfs.h"
|
||
|
#include "c_string.h"
|
||
|
// #include "c_errno.h"
|
||
|
#include "romfiles.h"
|
||
|
#include "c_stdio.h"
|
||
|
// #include "c_stdlib.h"
|
||
|
#include "c_fcntl.h"
|
||
|
|
||
|
#include "platform.h"
|
||
|
|
||
|
#if defined( BUILD_ROMFS ) || defined( BUILD_WOFS )
|
||
|
|
||
|
#define TOTAL_MAX_FDS 8
|
||
|
// DO NOT CHANGE THE ROMFS ALIGNMENT.
|
||
|
// UNLESS YOU _LIKE_ TO WATCH THE WORLD BURN.
|
||
|
#define ROMFS_ALIGN 4
|
||
|
|
||
|
#define fsmin( x , y ) ( ( x ) < ( y ) ? ( x ) : ( y ) )
|
||
|
|
||
|
static FD fd_table[ TOTAL_MAX_FDS ];
|
||
|
static int romfs_num_fd;
|
||
|
|
||
|
#define WOFS_END_MARKER_CHAR 0xFF
|
||
|
#define WOFS_DEL_FIELD_SIZE ( ROMFS_ALIGN )
|
||
|
#define WOFS_FILE_DELETED 0xAA
|
||
|
|
||
|
// Length of the 'file size' field for both ROMFS/WOFS
|
||
|
#define ROMFS_SIZE_LEN 4
|
||
|
|
||
|
static int ICACHE_FLASH_ATTR romfs_find_empty_fd(void)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
for( i = 0; i < TOTAL_MAX_FDS; i ++ )
|
||
|
if( fd_table[ i ].baseaddr == 0xFFFFFFFF &&
|
||
|
fd_table[ i ].offset == 0xFFFFFFFF &&
|
||
|
fd_table[ i ].size == 0xFFFFFFFF )
|
||
|
return i;
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
static void ICACHE_FLASH_ATTR romfs_close_fd( int fd )
|
||
|
{
|
||
|
if(fd<0 || fd>=TOTAL_MAX_FDS)
|
||
|
return;
|
||
|
c_memset( fd_table + fd, 0xFF, sizeof( FD ) );
|
||
|
fd_table[ fd ].flags = 0;
|
||
|
}
|
||
|
|
||
|
// Helper function: read a byte from the FS
|
||
|
static uint8_t ICACHE_FLASH_ATTR romfsh_read8( uint32_t addr, const FSDATA *pfs )
|
||
|
{
|
||
|
uint8_t temp;
|
||
|
if( pfs->flags & ROMFS_FS_FLAG_DIRECT )
|
||
|
return pfs->pbase[ addr ];
|
||
|
pfs->readf( &temp, addr, 1, pfs );
|
||
|
return temp;
|
||
|
}
|
||
|
|
||
|
// Helper function: return 1 if PFS reffers to a WOFS, 0 otherwise
|
||
|
static int ICACHE_FLASH_ATTR romfsh_is_wofs( const FSDATA* pfs )
|
||
|
{
|
||
|
return ( pfs->flags & ROMFS_FS_FLAG_WO ) != 0;
|
||
|
}
|
||
|
|
||
|
// Find the next file, returning FS_FILE_OK or FS_FILE_NOT_FOUND if there no file left.
|
||
|
static uint8_t ICACHE_FLASH_ATTR romfs_next_file( uint32_t *start, char* fname, size_t len, size_t *act_len, FSDATA *pfs )
|
||
|
{
|
||
|
uint32_t i, j, n;
|
||
|
uint32_t fsize;
|
||
|
int is_deleted;
|
||
|
|
||
|
// Look for the file
|
||
|
i = *start;
|
||
|
*act_len = 0;
|
||
|
if( (i >= INTERNAL_FLASH_SIZE) || (romfsh_read8( i, pfs ) == WOFS_END_MARKER_CHAR )) // end of file system
|
||
|
{
|
||
|
*start = (i >= INTERNAL_FLASH_SIZE)?(INTERNAL_FLASH_SIZE-1):i;
|
||
|
return FS_FILE_NOT_FOUND;
|
||
|
}
|
||
|
// Read file name
|
||
|
len = len>MAX_FNAME_LENGTH?MAX_FNAME_LENGTH:len;
|
||
|
for( j = 0; j < len; j ++ )
|
||
|
{
|
||
|
fname[ j ] = romfsh_read8( i + j, pfs );
|
||
|
if( fname[ j ] == 0 )
|
||
|
break;
|
||
|
}
|
||
|
n = j; // save the file name length to n
|
||
|
// ' i + j' now points at the '0' byte
|
||
|
j = i + j + 1;
|
||
|
// Round to a multiple of ROMFS_ALIGN
|
||
|
j = ( j + ROMFS_ALIGN - 1 ) & ~( ROMFS_ALIGN - 1 );
|
||
|
// WOFS has an additional WOFS_DEL_FIELD_SIZE bytes before the size as an indication for "file deleted"
|
||
|
if( romfsh_is_wofs( pfs ) )
|
||
|
{
|
||
|
is_deleted = romfsh_read8( j, pfs ) == WOFS_FILE_DELETED;
|
||
|
j += WOFS_DEL_FIELD_SIZE;
|
||
|
}
|
||
|
else
|
||
|
is_deleted = 0;
|
||
|
// And read the size
|
||
|
fsize = romfsh_read8( j, pfs ) + ( romfsh_read8( j + 1, pfs ) << 8 );
|
||
|
fsize += ( romfsh_read8( j + 2, pfs ) << 16 ) + ( romfsh_read8( j + 3, pfs ) << 24 );
|
||
|
j += ROMFS_SIZE_LEN;
|
||
|
if( !is_deleted )
|
||
|
{
|
||
|
// Found the valid file
|
||
|
*act_len = n;
|
||
|
}
|
||
|
// Move to next file
|
||
|
i = j + fsize;
|
||
|
// On WOFS, all file names must begin at a multiple of ROMFS_ALIGN
|
||
|
if( romfsh_is_wofs( pfs ) )
|
||
|
i = ( i + ROMFS_ALIGN - 1 ) & ~( ROMFS_ALIGN - 1 );
|
||
|
*start = i; // modify the start address
|
||
|
return FS_FILE_OK;
|
||
|
}
|
||
|
|
||
|
// Open the given file, returning one of FS_FILE_NOT_FOUND, FS_FILE_ALREADY_OPENED
|
||
|
// or FS_FILE_OK
|
||
|
static uint8_t ICACHE_FLASH_ATTR romfs_open_file( const char* fname, FD* pfd, FSDATA *pfs, uint32_t *plast, uint32_t *pnameaddr )
|
||
|
{
|
||
|
uint32_t i, j, n;
|
||
|
char fsname[ MAX_FNAME_LENGTH + 1 ];
|
||
|
uint32_t fsize;
|
||
|
int is_deleted;
|
||
|
|
||
|
// Look for the file
|
||
|
i = 0;
|
||
|
while( 1 )
|
||
|
{
|
||
|
if( i >= INTERNAL_FLASH_SIZE ){
|
||
|
*plast = INTERNAL_FLASH_SIZE - 1; // point to last one
|
||
|
return FS_FILE_NOT_FOUND;
|
||
|
}
|
||
|
if( romfsh_read8( i, pfs ) == WOFS_END_MARKER_CHAR )
|
||
|
{
|
||
|
*plast = i;
|
||
|
return FS_FILE_NOT_FOUND;
|
||
|
}
|
||
|
// Read file name
|
||
|
n = i;
|
||
|
for( j = 0; j < MAX_FNAME_LENGTH; j ++ )
|
||
|
{
|
||
|
fsname[ j ] = romfsh_read8( i + j, pfs );
|
||
|
if( fsname[ j ] == 0 )
|
||
|
break;
|
||
|
}
|
||
|
// ' i + j' now points at the '0' byte
|
||
|
j = i + j + 1;
|
||
|
// Round to a multiple of ROMFS_ALIGN
|
||
|
j = ( j + ROMFS_ALIGN - 1 ) & ~( ROMFS_ALIGN - 1 );
|
||
|
// WOFS has an additional WOFS_DEL_FIELD_SIZE bytes before the size as an indication for "file deleted"
|
||
|
if( romfsh_is_wofs( pfs ) )
|
||
|
{
|
||
|
is_deleted = romfsh_read8( j, pfs ) == WOFS_FILE_DELETED;
|
||
|
j += WOFS_DEL_FIELD_SIZE;
|
||
|
}
|
||
|
else
|
||
|
is_deleted = 0;
|
||
|
// And read the size
|
||
|
fsize = romfsh_read8( j, pfs ) + ( romfsh_read8( j + 1, pfs ) << 8 );
|
||
|
fsize += ( romfsh_read8( j + 2, pfs ) << 16 ) + ( romfsh_read8( j + 3, pfs ) << 24 );
|
||
|
j += ROMFS_SIZE_LEN;
|
||
|
if( !c_strncasecmp( fname, fsname, MAX_FNAME_LENGTH ) && !is_deleted )
|
||
|
{
|
||
|
// Found the file
|
||
|
pfd->baseaddr = j;
|
||
|
pfd->offset = 0;
|
||
|
pfd->size = fsize;
|
||
|
if( pnameaddr )
|
||
|
*pnameaddr = n;
|
||
|
return FS_FILE_OK;
|
||
|
}
|
||
|
// Move to next file
|
||
|
i = j + fsize;
|
||
|
// On WOFS, all file names must begin at a multiple of ROMFS_ALIGN
|
||
|
if( romfsh_is_wofs( pfs ) )
|
||
|
i = ( i + ROMFS_ALIGN - 1 ) & ~( ROMFS_ALIGN - 1 );
|
||
|
}
|
||
|
*plast = 0;
|
||
|
return FS_FILE_NOT_FOUND;
|
||
|
}
|
||
|
|
||
|
static int ICACHE_FLASH_ATTR romfs_open( const char *path, int flags, int mode, void *pdata )
|
||
|
{
|
||
|
FD tempfs;
|
||
|
int i;
|
||
|
FSDATA *pfsdata = ( FSDATA* )pdata;
|
||
|
int must_create = 0;
|
||
|
int exists;
|
||
|
uint8_t lflags = ROMFS_FILE_FLAG_READ;
|
||
|
uint32_t firstfree, nameaddr;
|
||
|
|
||
|
if( romfs_num_fd == TOTAL_MAX_FDS )
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
// Does the file exist?
|
||
|
exists = romfs_open_file( path, &tempfs, pfsdata, &firstfree, &nameaddr ) == FS_FILE_OK;
|
||
|
// Now interpret "flags" to set file flags and to check if we should create the file
|
||
|
if( flags & O_CREAT )
|
||
|
{
|
||
|
// If O_CREAT is specified with O_EXCL and the file already exists, return with error
|
||
|
if( ( flags & O_EXCL ) && exists )
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
// Otherwise create the file if it does not exist
|
||
|
must_create = !exists;
|
||
|
}
|
||
|
if( ( flags & O_TRUNC ) && ( flags & ( O_WRONLY | O_RDWR ) ) && exists )
|
||
|
{
|
||
|
// The file exists, but it must be truncated
|
||
|
// In the case of WOFS, this effectively means "create a new file"
|
||
|
must_create = 1;
|
||
|
}
|
||
|
// ROMFS can't create files
|
||
|
if( must_create && ( ( pfsdata->flags & ROMFS_FS_FLAG_WO ) == 0 ) )
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
// Decode access mode
|
||
|
if( flags & O_WRONLY )
|
||
|
lflags = ROMFS_FILE_FLAG_WRITE;
|
||
|
else if( flags & O_RDWR )
|
||
|
lflags = ROMFS_FILE_FLAG_READ | ROMFS_FILE_FLAG_WRITE;
|
||
|
if( flags & O_APPEND )
|
||
|
lflags |= ROMFS_FILE_FLAG_APPEND;
|
||
|
// If a write access is requested when the file must NOT be created, this
|
||
|
// is an error
|
||
|
if( ( lflags & ( ROMFS_FILE_FLAG_WRITE | ROMFS_FILE_FLAG_APPEND ) ) && !must_create )
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
if( ( lflags & ( ROMFS_FILE_FLAG_WRITE | ROMFS_FILE_FLAG_APPEND ) ) && romfs_fs_is_flag_set( pfsdata, ROMFS_FS_FLAG_WRITING ) )
|
||
|
{
|
||
|
// At most one file can be opened in write mode at any given time on WOFS
|
||
|
return -1;
|
||
|
}
|
||
|
// Do we need to create the file ?
|
||
|
if( must_create )
|
||
|
{
|
||
|
if( exists )
|
||
|
{
|
||
|
// Invalidate the file first by changing WOFS_DEL_FIELD_SIZE bytes before
|
||
|
// the file length to WOFS_FILE_DELETED
|
||
|
uint8_t tempb[] = { WOFS_FILE_DELETED, 0xFF, 0xFF, 0xFF };
|
||
|
pfsdata->writef( tempb, tempfs.baseaddr - ROMFS_SIZE_LEN - WOFS_DEL_FIELD_SIZE, WOFS_DEL_FIELD_SIZE, pfsdata );
|
||
|
}
|
||
|
// Find the last available position by asking romfs_open_file to look for a file
|
||
|
// with an invalid name
|
||
|
romfs_open_file( "\1", &tempfs, pfsdata, &firstfree, NULL );
|
||
|
// Is there enough space on the FS for another file?
|
||
|
if( pfsdata->max_size - firstfree + 1 < c_strlen( path ) + 1 + WOFS_MIN_NEEDED_SIZE + WOFS_DEL_FIELD_SIZE )
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
// Make sure we can get a file descriptor before writing
|
||
|
if( ( i = romfs_find_empty_fd() ) < 0 )
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
// Write the name of the file
|
||
|
pfsdata->writef( path, firstfree, c_strlen( path ) + 1, pfsdata );
|
||
|
firstfree += c_strlen( path ) + 1; // skip over the name
|
||
|
// Align to a multiple of ROMFS_ALIGN
|
||
|
firstfree = ( firstfree + ROMFS_ALIGN - 1 ) & ~( ROMFS_ALIGN - 1 );
|
||
|
firstfree += ROMFS_SIZE_LEN + WOFS_DEL_FIELD_SIZE; // skip over the size and the deleted flags area
|
||
|
tempfs.baseaddr = firstfree;
|
||
|
tempfs.offset = tempfs.size = 0;
|
||
|
// Set the "writing" flag on the FS to indicate that there is a file opened in write mode
|
||
|
romfs_fs_set_flag( pfsdata, ROMFS_FS_FLAG_WRITING );
|
||
|
}
|
||
|
else // File must exist (and was found in the previous 'romfs_open_file' call)
|
||
|
{
|
||
|
if( !exists )
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if( ( i = romfs_find_empty_fd() ) < 0 )
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
}
|
||
|
// Copy the descriptor information
|
||
|
tempfs.flags = lflags;
|
||
|
c_memcpy( fd_table + i, &tempfs, sizeof( FD ) );
|
||
|
romfs_num_fd ++;
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
static int ICACHE_FLASH_ATTR romfs_close( int fd, void *pdata )
|
||
|
{
|
||
|
if(fd<0 || fd>=TOTAL_MAX_FDS)
|
||
|
return 0;
|
||
|
FD* pfd = fd_table + fd;
|
||
|
FSDATA *pfsdata = ( FSDATA* )pdata;
|
||
|
uint8_t temp[ ROMFS_SIZE_LEN ];
|
||
|
|
||
|
if( pfd->flags & ( ROMFS_FILE_FLAG_WRITE | ROMFS_FILE_FLAG_APPEND ) )
|
||
|
{
|
||
|
// Write back the size
|
||
|
temp[ 0 ] = pfd->size & 0xFF;
|
||
|
temp[ 1 ] = ( pfd->size >> 8 ) & 0xFF;
|
||
|
temp[ 2 ] = ( pfd->size >> 16 ) & 0xFF;
|
||
|
temp[ 3 ] = ( pfd->size >> 24 ) & 0xFF;
|
||
|
pfsdata->writef( temp, pfd->baseaddr - ROMFS_SIZE_LEN, ROMFS_SIZE_LEN, pfsdata );
|
||
|
// Clear the "writing" flag on the FS instance to allow other files to be opened
|
||
|
// in write mode
|
||
|
romfs_fs_clear_flag( pfsdata, ROMFS_FS_FLAG_WRITING );
|
||
|
}
|
||
|
romfs_close_fd( fd );
|
||
|
romfs_num_fd --;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static _ssize_t ICACHE_FLASH_ATTR romfs_write( int fd, const void* ptr, size_t len, void *pdata )
|
||
|
{
|
||
|
if(fd<0 || fd>=TOTAL_MAX_FDS)
|
||
|
return -1;
|
||
|
if(len == 0)
|
||
|
return 0;
|
||
|
FD* pfd = fd_table + fd;
|
||
|
FSDATA *pfsdata = ( FSDATA* )pdata;
|
||
|
|
||
|
if( ( pfd->flags & ( ROMFS_FILE_FLAG_WRITE | ROMFS_FILE_FLAG_APPEND ) ) == 0 )
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
// Append mode: set the file pointer to the end
|
||
|
if( pfd->flags & ROMFS_FILE_FLAG_APPEND )
|
||
|
pfd->offset = pfd->size;
|
||
|
// Only write at the end of the file!
|
||
|
if( pfd->offset != pfd->size )
|
||
|
return 0;
|
||
|
// Check if we have enough space left on the device. Always keep 1 byte for the final 0xFF
|
||
|
// and ROMFS_ALIGN - 1 bytes for aligning the contents of the file data in the worst case
|
||
|
// scenario (so ROMFS_ALIGN bytes in total)
|
||
|
if( pfd->baseaddr + pfd->size + len > pfsdata->max_size - ROMFS_ALIGN )
|
||
|
len = pfsdata->max_size - ( pfd->baseaddr + pfd->size ) - ROMFS_ALIGN;
|
||
|
pfsdata->writef( ptr, pfd->offset + pfd->baseaddr, len, pfsdata );
|
||
|
pfd->offset += len;
|
||
|
pfd->size += len;
|
||
|
return len;
|
||
|
}
|
||
|
|
||
|
static _ssize_t ICACHE_FLASH_ATTR romfs_read( int fd, void* ptr, size_t len, void *pdata )
|
||
|
{
|
||
|
if(fd<0 || fd>=TOTAL_MAX_FDS)
|
||
|
return -1;
|
||
|
if(len == 0)
|
||
|
return 0;
|
||
|
|
||
|
FD* pfd = fd_table + fd;
|
||
|
long actlen = fsmin( len, pfd->size - pfd->offset );
|
||
|
FSDATA *pfsdata = ( FSDATA* )pdata;
|
||
|
|
||
|
if( ( pfd->flags & ROMFS_FILE_FLAG_READ ) == 0 )
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
if( pfsdata->flags & ROMFS_FS_FLAG_DIRECT )
|
||
|
c_memcpy( ptr, pfsdata->pbase + pfd->offset + pfd->baseaddr, actlen );
|
||
|
else
|
||
|
actlen = pfsdata->readf( ptr, pfd->offset + pfd->baseaddr, actlen, pfsdata );
|
||
|
pfd->offset += actlen;
|
||
|
return actlen;
|
||
|
}
|
||
|
|
||
|
// lseek
|
||
|
static int ICACHE_FLASH_ATTR romfs_lseek( int fd, int off, int whence, void *pdata )
|
||
|
{
|
||
|
if(fd<0 || fd>=TOTAL_MAX_FDS)
|
||
|
return -1;
|
||
|
|
||
|
FD* pfd = fd_table + fd;
|
||
|
uint32_t newpos = 0;
|
||
|
|
||
|
switch( whence )
|
||
|
{
|
||
|
case SEEK_SET:
|
||
|
newpos = off;
|
||
|
break;
|
||
|
|
||
|
case SEEK_CUR:
|
||
|
newpos = pfd->offset + off;
|
||
|
break;
|
||
|
|
||
|
case SEEK_END:
|
||
|
newpos = pfd->size + off;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
return -1;
|
||
|
}
|
||
|
if( newpos > pfd->size )
|
||
|
return -1;
|
||
|
pfd->offset = newpos;
|
||
|
return newpos;
|
||
|
}
|
||
|
|
||
|
// ****************************************************************************
|
||
|
// WOFS functions and instance descriptor for real hardware
|
||
|
|
||
|
#if defined( BUILD_WOFS )
|
||
|
static uint32_t ICACHE_FLASH_ATTR sim_wofs_write( const void *from, uint32_t toaddr, uint32_t size, const void *pdata )
|
||
|
{
|
||
|
const FSDATA *pfsdata = ( const FSDATA* )pdata;
|
||
|
if(toaddr>=INTERNAL_FLASH_SIZE)
|
||
|
{
|
||
|
NODE_ERR("ERROR in flash op: wrong addr.\n");
|
||
|
return 0;
|
||
|
}
|
||
|
toaddr += ( uint32_t )pfsdata->pbase;
|
||
|
return platform_flash_write( from, toaddr, size );
|
||
|
}
|
||
|
|
||
|
static uint32_t ICACHE_FLASH_ATTR sim_wofs_read( void *to, uint32_t fromaddr, uint32_t size, const void *pdata )
|
||
|
{
|
||
|
const FSDATA *pfsdata = ( const FSDATA* )pdata;
|
||
|
if(fromaddr>=INTERNAL_FLASH_SIZE)
|
||
|
{
|
||
|
NODE_ERR("ERROR in flash op: wrong addr.\n");
|
||
|
return 0;
|
||
|
}
|
||
|
fromaddr += ( uint32_t )pfsdata->pbase;
|
||
|
return platform_flash_read( to, fromaddr, size );
|
||
|
}
|
||
|
|
||
|
// This must NOT be a const!
|
||
|
static FSDATA wofs_fsdata =
|
||
|
{
|
||
|
NULL,
|
||
|
ROMFS_FS_FLAG_WO,
|
||
|
sim_wofs_read,
|
||
|
sim_wofs_write,
|
||
|
0
|
||
|
};
|
||
|
|
||
|
// WOFS formatting function
|
||
|
// Returns 1 if OK, 0 for error
|
||
|
int ICACHE_FLASH_ATTR wofs_format( void )
|
||
|
{
|
||
|
uint32_t sect_first, sect_last;
|
||
|
FD tempfd;
|
||
|
platform_flash_get_first_free_block_address( §_first );
|
||
|
// Get the first free address in WOFS. We use this address to compute the last block that we need to
|
||
|
// erase, instead of simply erasing everything from sect_first to the last Flash page.
|
||
|
romfs_open_file( "\1", &tempfd, &wofs_fsdata, §_last, NULL );
|
||
|
sect_last = platform_flash_get_sector_of_address( sect_last + ( uint32_t )wofs_fsdata.pbase );
|
||
|
while( sect_first <= sect_last )
|
||
|
if( platform_flash_erase_sector( sect_first ++ ) == PLATFORM_ERR )
|
||
|
return 0;
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
int ICACHE_FLASH_ATTR wofs_open(const char *_name, int flags){
|
||
|
return romfs_open( _name, flags, 0, &wofs_fsdata );
|
||
|
}
|
||
|
|
||
|
int ICACHE_FLASH_ATTR wofs_close( int fd ){
|
||
|
return romfs_close( fd, &wofs_fsdata );
|
||
|
}
|
||
|
|
||
|
size_t ICACHE_FLASH_ATTR wofs_write( int fd, const void* ptr, size_t len ){
|
||
|
return romfs_write( fd, ptr, len, &wofs_fsdata );
|
||
|
}
|
||
|
|
||
|
size_t ICACHE_FLASH_ATTR wofs_read( int fd, void* ptr, size_t len){
|
||
|
return romfs_read( fd, ptr, len, &wofs_fsdata );
|
||
|
}
|
||
|
|
||
|
int ICACHE_FLASH_ATTR wofs_lseek( int fd, int off, int whence ){
|
||
|
return romfs_lseek( fd, off, whence, &wofs_fsdata );
|
||
|
}
|
||
|
|
||
|
int ICACHE_FLASH_ATTR wofs_eof( int fd ){
|
||
|
if(fd<0 || fd>=TOTAL_MAX_FDS)
|
||
|
return -1;
|
||
|
FD* pfd = fd_table + fd;
|
||
|
// NODE_DBG("off:%d, sz:%d\n",pfd->offset, pfd->size);
|
||
|
return pfd->offset == pfd->size;
|
||
|
}
|
||
|
|
||
|
int ICACHE_FLASH_ATTR wofs_getc( int fd ){
|
||
|
char c = EOF;
|
||
|
if(!wofs_eof(fd)){
|
||
|
romfs_read( fd, &c, 1, &wofs_fsdata );
|
||
|
}
|
||
|
// NODE_DBG("c: %d\n", c);
|
||
|
return (int)c;
|
||
|
}
|
||
|
|
||
|
int ICACHE_FLASH_ATTR wofs_ungetc( int c, int fd ){
|
||
|
return romfs_lseek( fd, -1, SEEK_CUR, &wofs_fsdata );
|
||
|
}
|
||
|
|
||
|
// Find the next file, returning FS_FILE_OK or FS_FILE_NOT_FOUND if there no file left.
|
||
|
uint8_t ICACHE_FLASH_ATTR wofs_next( uint32_t *start, char* fname, size_t len, size_t *act_len ){
|
||
|
return romfs_next_file( start, fname, len, act_len, &wofs_fsdata );
|
||
|
}
|
||
|
|
||
|
#endif // #ifdef BUILD_WOFS
|
||
|
|
||
|
// Initialize both ROMFS and WOFS as needed
|
||
|
int ICACHE_FLASH_ATTR romfs_init( void )
|
||
|
{
|
||
|
unsigned i;
|
||
|
|
||
|
for( i = 0; i < TOTAL_MAX_FDS; i ++ )
|
||
|
{
|
||
|
c_memset( fd_table + i, 0xFF, sizeof( FD ) );
|
||
|
fd_table[ i ].flags = 0;
|
||
|
}
|
||
|
#if defined( BUILD_WOFS )
|
||
|
// Get the start address and size of WOFS and register it
|
||
|
wofs_fsdata.pbase = ( uint8_t* )platform_flash_get_first_free_block_address( NULL );
|
||
|
wofs_fsdata.max_size = INTERNAL_FLASH_SIZE - ( ( uint32_t )wofs_fsdata.pbase - INTERNAL_FLASH_START_ADDRESS );
|
||
|
NODE_DBG("wofs.pbase:%x,max:%x\n",wofs_fsdata.pbase,wofs_fsdata.max_size);
|
||
|
#endif // ifdef BUILD_WOFS
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
#else // #if defined( BUILD_ROMFS ) || defined( BUILD_WOFS )
|
||
|
|
||
|
int ICACHE_FLASH_ATTR romfs_init( void )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
#endif // #if defined( BUILD_ROMFS ) || defined( BUILD_WOFS )
|
||
|
|
||
|
int ICACHE_FLASH_ATTR test_romfs()
|
||
|
{
|
||
|
int fd;
|
||
|
int i, size;
|
||
|
|
||
|
fd = wofs_open("init.lua",O_RDONLY);
|
||
|
NODE_DBG("open file fd:%d\n", fd);
|
||
|
char r[128];
|
||
|
NODE_DBG("read from file:\n");
|
||
|
c_memset(r,0,128);
|
||
|
size = wofs_read(fd,r,128);
|
||
|
r[size]=0;
|
||
|
NODE_DBG(r);
|
||
|
NODE_DBG("\n");
|
||
|
wofs_close(fd);
|
||
|
|
||
|
fd = wofs_open("testm.lua",O_RDONLY);
|
||
|
NODE_DBG("open file fd:%d\n", fd);
|
||
|
NODE_DBG("read from file:\n");
|
||
|
c_memset(r,0,128);
|
||
|
size = wofs_read(fd,r,128);
|
||
|
r[size]=0;
|
||
|
NODE_DBG(r);
|
||
|
NODE_DBG("\n");
|
||
|
wofs_close(fd);
|
||
|
|
||
|
return 0;
|
||
|
}
|