Refactored espfs file system

pull/193/head
cskarai 8 years ago committed by Thorsten von Eicken
parent adbea01deb
commit 1dab6e5d84
  1. 106
      espfs/espfs.c
  2. 15
      espfs/espfs.h

@ -80,37 +80,6 @@ Accessing the flash through the mem emulation at 0x40200000 is a bit hairy: All
a memory exception, crashing the program. a memory exception, crashing the program.
*/ */
void espfs_memcpy( EspFsContext * ctx, void * dest, const void * src, int count )
{
if( ctx->source == ESPFS_MEMORY )
os_memcpy( dest, src, count );
else
{
if( spi_flash_read( (int)src, dest, count ) != SPI_FLASH_RESULT_OK )
os_memset( dest, 0, count ); // if read was not successful, reply with zeroes
}
}
EspFsInitResult ICACHE_FLASH_ATTR espFsInit(EspFsContext *ctx, void *flashAddress, EspFsSource source) {
ctx->valid = 0;
ctx->source = source;
// base address must be aligned to 4 bytes
if (((int)flashAddress & 3) != 0) {
return ESPFS_INIT_RESULT_BAD_ALIGN;
}
// check if there is valid header at address
EspFsHeader testHeader;
espfs_memcpy(ctx, &testHeader, flashAddress, sizeof(EspFsHeader));
if (testHeader.magic != ESPFS_MAGIC) {
return ESPFS_INIT_RESULT_NO_IMAGE;
}
ctx->data = (char *)flashAddress;
ctx->valid = 1;
return ESPFS_INIT_RESULT_OK;
}
//Copies len bytes over from dst to src, but does it using *only* //Copies len bytes over from dst to src, but does it using *only*
//aligned 32-bit reads. Yes, it's no too optimized but it's short and sweet and it works. //aligned 32-bit reads. Yes, it's no too optimized but it's short and sweet and it works.
@ -133,12 +102,49 @@ void ICACHE_FLASH_ATTR memcpyAligned(char *dst, const char *src, int len) {
#define memcpyAligned memcpy #define memcpyAligned memcpy
#endif #endif
void ICACHE_FLASH_ATTR memcpyFromFlash(char *dst, const char *src, int len)
{
if( spi_flash_read( (int)src, (void *)dst, len ) != SPI_FLASH_RESULT_OK )
os_memset( dst, 0, len ); // if read was not successful, reply with zeroes
}
// memcpy on MEMORY/FLASH file systems
void espfs_memcpy( EspFsContext * ctx, void * dest, const void * src, int count )
{
if( ctx->source == ESPFS_MEMORY )
os_memcpy( dest, src, count );
else
memcpyFromFlash(dest, src, count);
}
// aligned memcpy on MEMORY/FLASH file systems
void espfs_memcpyAligned( EspFsContext * ctx, void * dest, const void * src, int count ) void espfs_memcpyAligned( EspFsContext * ctx, void * dest, const void * src, int count )
{ {
if( ctx->source == ESPFS_MEMORY ) if( ctx->source == ESPFS_MEMORY )
memcpyAligned(dest, src, count); memcpyAligned(dest, src, count);
else else
espfs_memcpy(ctx, dest, src, count); memcpyFromFlash(dest, src, count);
}
// initializes an EspFs context
EspFsInitResult ICACHE_FLASH_ATTR espFsInit(EspFsContext *ctx, void *flashAddress, EspFsSource source) {
ctx->valid = 0;
ctx->source = source;
// base address must be aligned to 4 bytes
if (((int)flashAddress & 3) != 0) {
return ESPFS_INIT_RESULT_BAD_ALIGN;
}
// check if there is valid header at address
EspFsHeader testHeader;
espfs_memcpy(ctx, &testHeader, flashAddress, sizeof(EspFsHeader));
if (testHeader.magic != ESPFS_MAGIC) {
return ESPFS_INIT_RESULT_NO_IMAGE;
}
ctx->data = (char *)flashAddress;
ctx->valid = 1;
return ESPFS_INIT_RESULT_OK;
} }
// Returns flags of opened file. // Returns flags of opened file.
@ -155,6 +161,7 @@ int ICACHE_FLASH_ATTR espFsFlags(EspFsFile *fh) {
return (int)flags; return (int)flags;
} }
// creates and initializes an iterator over the espfs file system
void ICACHE_FLASH_ATTR espFsIteratorInit(EspFsContext *ctx, EspFsIterator *iterator) void ICACHE_FLASH_ATTR espFsIteratorInit(EspFsContext *ctx, EspFsIterator *iterator)
{ {
if( ctx->data == NULL ) if( ctx->data == NULL )
@ -163,19 +170,31 @@ void ICACHE_FLASH_ATTR espFsIteratorInit(EspFsContext *ctx, EspFsIterator *itera
return; return;
} }
iterator->ctx = ctx; iterator->ctx = ctx;
iterator->p = ctx->data; iterator->position = NULL;
} }
// moves iterator to the next file on espfs
// returns 1 if iterator move was successful, otherwise 0 (last file)
// iterator->header and iterator->name will contain file information
int ICACHE_FLASH_ATTR espFsIteratorNext(EspFsIterator *iterator) int ICACHE_FLASH_ATTR espFsIteratorNext(EspFsIterator *iterator)
{ {
if( iterator->ctx == NULL ) if( iterator->ctx == NULL )
return 0; return 0;
char * p = iterator->p; char * position = iterator->position;
if( position == NULL )
position = iterator->ctx->data; // first node
else
{
// jump the iterator to the next file
position+=sizeof(EspFsHeader) + iterator->header.nameLen+iterator->header.fileLenComp;
if ((int)position&3) position+=4-((int)position&3); //align to next 32bit val
}
iterator->node = p; iterator->position = position;
EspFsHeader * hdr = &iterator->header; EspFsHeader * hdr = &iterator->header;
espfs_memcpy(iterator->ctx, hdr, p, sizeof(EspFsHeader)); espfs_memcpy(iterator->ctx, hdr, position, sizeof(EspFsHeader));
if (hdr->magic!=ESPFS_MAGIC) { if (hdr->magic!=ESPFS_MAGIC) {
#ifdef ESPFS_DBG #ifdef ESPFS_DBG
@ -185,17 +204,15 @@ int ICACHE_FLASH_ATTR espFsIteratorNext(EspFsIterator *iterator)
} }
if (hdr->flags&FLAG_LASTFILE) { if (hdr->flags&FLAG_LASTFILE) {
//os_printf("End of image.\n"); //os_printf("End of image.\n");
iterator->ctx = NULL; // invalidate the iterator
return 0; return 0;
} }
p += sizeof(EspFsHeader); position += sizeof(EspFsHeader);
//Grab the name of the file. //Grab the name of the file.
espfs_memcpy(iterator->ctx, iterator->name, p, sizeof(iterator->name)); espfs_memcpy(iterator->ctx, iterator->name, position, sizeof(iterator->name));
p+=hdr->nameLen+hdr->fileLenComp;
if ((int)p&3) p+=4-((int)p&3); //align to next 32bit val
iterator->p = p;
return 1; return 1;
} }
@ -221,10 +238,10 @@ EspFsFile ICACHE_FLASH_ATTR *espFsOpen(EspFsContext *ctx, char *fileName) {
//os_printf("Alloc %p[%d]\n", r, sizeof(EspFsFile)); //os_printf("Alloc %p[%d]\n", r, sizeof(EspFsFile));
if (r==NULL) return NULL; if (r==NULL) return NULL;
r->ctx = ctx; r->ctx = ctx;
r->header=(EspFsHeader *)it.node; r->header=(EspFsHeader *)it.position;
r->decompressor=it.header.compression; r->decompressor=it.header.compression;
r->posComp=it.node + it.header.nameLen + sizeof(EspFsHeader); r->posComp=it.position + it.header.nameLen + sizeof(EspFsHeader);
r->posStart=it.node + it.header.nameLen + sizeof(EspFsHeader); r->posStart=it.position + it.header.nameLen + sizeof(EspFsHeader);
r->posDecomp=0; r->posDecomp=0;
if (it.header.compression==COMPRESS_NONE) { if (it.header.compression==COMPRESS_NONE) {
r->decompData=NULL; r->decompData=NULL;
@ -269,6 +286,7 @@ void ICACHE_FLASH_ATTR espFsClose(EspFsFile *fh) {
os_free(fh); os_free(fh);
} }
// checks if the file system is valid (detect if the content is an espfs image or random data)
int ICACHE_FLASH_ATTR espFsIsValid(EspFsContext *ctx) { int ICACHE_FLASH_ATTR espFsIsValid(EspFsContext *ctx) {
return ctx->valid; return ctx->valid;
} }

@ -9,20 +9,21 @@ typedef enum {
ESPFS_INIT_RESULT_BAD_ALIGN, ESPFS_INIT_RESULT_BAD_ALIGN,
} EspFsInitResult; } EspFsInitResult;
// Only 1 MByte of the flash can be directly accessed with ESP8266
// If flash size is >1 Mbyte, SDK API is required to retrieve flash content
typedef enum { typedef enum {
ESPFS_MEMORY, ESPFS_MEMORY, // read data directly from memory (fast, max 1 MByte)
ESPFS_FLASH, ESPFS_FLASH, // read data from flash using SDK API (no limit for the size)
} EspFsSource; } EspFsSource;
typedef struct EspFsFile EspFsFile; typedef struct EspFsFile EspFsFile;
typedef struct EspFsContext EspFsContext; typedef struct EspFsContext EspFsContext;
typedef struct { typedef struct {
EspFsHeader header; EspFsHeader header; // the header of the current file
EspFsContext *ctx; EspFsContext *ctx; // pointer to espfs context
char name[256]; char name[256]; // the name of the current file
char *node; char *position; // position of the iterator (pointer on the file system)
char * p;
} EspFsIterator; } EspFsIterator;
extern EspFsContext * espLinkCtx; extern EspFsContext * espLinkCtx;

Loading…
Cancel
Save