|
|
@ -30,6 +30,7 @@ It's written for use with httpd, but doesn't need to be used as such. |
|
|
|
#define os_malloc malloc |
|
|
|
#define os_malloc malloc |
|
|
|
#define os_free free |
|
|
|
#define os_free free |
|
|
|
#define os_memcpy memcpy |
|
|
|
#define os_memcpy memcpy |
|
|
|
|
|
|
|
#define os_memset memset |
|
|
|
#define os_strncmp strncmp |
|
|
|
#define os_strncmp strncmp |
|
|
|
#define os_strcmp strcmp |
|
|
|
#define os_strcmp strcmp |
|
|
|
#define os_strcpy strcpy |
|
|
|
#define os_strcpy strcpy |
|
|
@ -40,9 +41,21 @@ It's written for use with httpd, but doesn't need to be used as such. |
|
|
|
#include "espfsformat.h" |
|
|
|
#include "espfsformat.h" |
|
|
|
#include "espfs.h" |
|
|
|
#include "espfs.h" |
|
|
|
|
|
|
|
|
|
|
|
static char* espFsData = NULL; |
|
|
|
EspFsContext espLinkCtxDef; |
|
|
|
|
|
|
|
EspFsContext userCtxDef; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
EspFsContext * espLinkCtx = &espLinkCtxDef; |
|
|
|
|
|
|
|
EspFsContext * userCtx = &userCtxDef; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct EspFsContext |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
char* data; |
|
|
|
|
|
|
|
EspFsSource source; |
|
|
|
|
|
|
|
uint8_t valid; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
struct EspFsFile { |
|
|
|
struct EspFsFile { |
|
|
|
|
|
|
|
EspFsContext *ctx; |
|
|
|
EspFsHeader *header; |
|
|
|
EspFsHeader *header; |
|
|
|
char decompressor; |
|
|
|
char decompressor; |
|
|
|
int32_t posDecomp; |
|
|
|
int32_t posDecomp; |
|
|
@ -67,7 +80,20 @@ 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. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
EspFsInitResult ICACHE_FLASH_ATTR espFsInit(void *flashAddress) { |
|
|
|
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
|
|
|
|
// base address must be aligned to 4 bytes
|
|
|
|
if (((int)flashAddress & 3) != 0) { |
|
|
|
if (((int)flashAddress & 3) != 0) { |
|
|
|
return ESPFS_INIT_RESULT_BAD_ALIGN; |
|
|
|
return ESPFS_INIT_RESULT_BAD_ALIGN; |
|
|
@ -75,12 +101,13 @@ EspFsInitResult ICACHE_FLASH_ATTR espFsInit(void *flashAddress) { |
|
|
|
|
|
|
|
|
|
|
|
// check if there is valid header at address
|
|
|
|
// check if there is valid header at address
|
|
|
|
EspFsHeader testHeader; |
|
|
|
EspFsHeader testHeader; |
|
|
|
os_memcpy(&testHeader, flashAddress, sizeof(EspFsHeader)); |
|
|
|
espfs_memcpy(ctx, &testHeader, flashAddress, sizeof(EspFsHeader)); |
|
|
|
if (testHeader.magic != ESPFS_MAGIC) { |
|
|
|
if (testHeader.magic != ESPFS_MAGIC) { |
|
|
|
return ESPFS_INIT_RESULT_NO_IMAGE; |
|
|
|
return ESPFS_INIT_RESULT_NO_IMAGE; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
espFsData = (char *)flashAddress; |
|
|
|
ctx->data = (char *)flashAddress; |
|
|
|
|
|
|
|
ctx->valid = 1; |
|
|
|
return ESPFS_INIT_RESULT_OK; |
|
|
|
return ESPFS_INIT_RESULT_OK; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -89,7 +116,7 @@ EspFsInitResult ICACHE_FLASH_ATTR espFsInit(void *flashAddress) { |
|
|
|
|
|
|
|
|
|
|
|
//ToDo: perhaps os_memcpy also does unaligned accesses?
|
|
|
|
//ToDo: perhaps os_memcpy also does unaligned accesses?
|
|
|
|
#ifdef __ets__ |
|
|
|
#ifdef __ets__ |
|
|
|
void ICACHE_FLASH_ATTR memcpyAligned(char *dst, char *src, int len) { |
|
|
|
void ICACHE_FLASH_ATTR memcpyAligned(char *dst, const char *src, int len) { |
|
|
|
int x; |
|
|
|
int x; |
|
|
|
int w, b; |
|
|
|
int w, b; |
|
|
|
for (x=0; x<len; x++) { |
|
|
|
for (x=0; x<len; x++) { |
|
|
@ -106,6 +133,14 @@ void ICACHE_FLASH_ATTR memcpyAligned(char *dst, char *src, int len) { |
|
|
|
#define memcpyAligned memcpy |
|
|
|
#define memcpyAligned memcpy |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void espfs_memcpyAligned( EspFsContext * ctx, void * dest, const void * src, int count ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if( ctx->source == ESPFS_MEMORY ) |
|
|
|
|
|
|
|
memcpyAligned(dest, src, count); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
espfs_memcpy(ctx, dest, src, count); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Returns flags of opened file.
|
|
|
|
// Returns flags of opened file.
|
|
|
|
int ICACHE_FLASH_ATTR espFsFlags(EspFsFile *fh) { |
|
|
|
int ICACHE_FLASH_ATTR espFsFlags(EspFsFile *fh) { |
|
|
|
if (fh == NULL) { |
|
|
|
if (fh == NULL) { |
|
|
@ -116,19 +151,19 @@ int ICACHE_FLASH_ATTR espFsFlags(EspFsFile *fh) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int8_t flags; |
|
|
|
int8_t flags; |
|
|
|
memcpyAligned((char*)&flags, (char*)&fh->header->flags, 1); |
|
|
|
espfs_memcpyAligned(fh->ctx, (char*)&flags, (char*)&fh->header->flags, 1); |
|
|
|
return (int)flags; |
|
|
|
return (int)flags; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//Open a file and return a pointer to the file desc struct.
|
|
|
|
//Open a file and return a pointer to the file desc struct.
|
|
|
|
EspFsFile ICACHE_FLASH_ATTR *espFsOpen(char *fileName) { |
|
|
|
EspFsFile ICACHE_FLASH_ATTR *espFsOpen(EspFsContext *ctx, char *fileName) { |
|
|
|
if (espFsData == NULL) { |
|
|
|
if (ctx->data == NULL) { |
|
|
|
#ifdef ESPFS_DBG |
|
|
|
#ifdef ESPFS_DBG |
|
|
|
os_printf("Call espFsInit first!\n"); |
|
|
|
os_printf("Call espFsInit first!\n"); |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
return NULL; |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
} |
|
|
|
char *p=espFsData; |
|
|
|
char *p=ctx->data; |
|
|
|
char *hpos; |
|
|
|
char *hpos; |
|
|
|
char namebuf[256]; |
|
|
|
char namebuf[256]; |
|
|
|
EspFsHeader h; |
|
|
|
EspFsHeader h; |
|
|
@ -139,7 +174,7 @@ EspFsFile ICACHE_FLASH_ATTR *espFsOpen(char *fileName) { |
|
|
|
while(1) { |
|
|
|
while(1) { |
|
|
|
hpos=p; |
|
|
|
hpos=p; |
|
|
|
//Grab the next file header.
|
|
|
|
//Grab the next file header.
|
|
|
|
os_memcpy(&h, p, sizeof(EspFsHeader)); |
|
|
|
espfs_memcpy(ctx, &h, p, sizeof(EspFsHeader)); |
|
|
|
if (h.magic!=ESPFS_MAGIC) { |
|
|
|
if (h.magic!=ESPFS_MAGIC) { |
|
|
|
#ifdef ESPFS_DBG |
|
|
|
#ifdef ESPFS_DBG |
|
|
|
os_printf("Magic mismatch. EspFS image broken.\n"); |
|
|
|
os_printf("Magic mismatch. EspFS image broken.\n"); |
|
|
@ -152,7 +187,7 @@ EspFsFile ICACHE_FLASH_ATTR *espFsOpen(char *fileName) { |
|
|
|
} |
|
|
|
} |
|
|
|
//Grab the name of the file.
|
|
|
|
//Grab the name of the file.
|
|
|
|
p+=sizeof(EspFsHeader); |
|
|
|
p+=sizeof(EspFsHeader); |
|
|
|
os_memcpy(namebuf, p, sizeof(namebuf)); |
|
|
|
espfs_memcpy(ctx, namebuf, p, sizeof(namebuf)); |
|
|
|
// os_printf("Found file '%s'. Namelen=%x fileLenComp=%x, compr=%d flags=%d\n",
|
|
|
|
// os_printf("Found file '%s'. Namelen=%x fileLenComp=%x, compr=%d flags=%d\n",
|
|
|
|
// namebuf, (unsigned int)h.nameLen, (unsigned int)h.fileLenComp, h.compression, h.flags);
|
|
|
|
// namebuf, (unsigned int)h.nameLen, (unsigned int)h.fileLenComp, h.compression, h.flags);
|
|
|
|
if (os_strcmp(namebuf, fileName)==0) { |
|
|
|
if (os_strcmp(namebuf, fileName)==0) { |
|
|
@ -161,6 +196,7 @@ EspFsFile ICACHE_FLASH_ATTR *espFsOpen(char *fileName) { |
|
|
|
r=(EspFsFile *)os_malloc(sizeof(EspFsFile)); //Alloc file desc mem
|
|
|
|
r=(EspFsFile *)os_malloc(sizeof(EspFsFile)); //Alloc file desc mem
|
|
|
|
//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->header=(EspFsHeader *)hpos; |
|
|
|
r->header=(EspFsHeader *)hpos; |
|
|
|
r->decompressor=h.compression; |
|
|
|
r->decompressor=h.compression; |
|
|
|
r->posComp=p; |
|
|
|
r->posComp=p; |
|
|
@ -187,15 +223,15 @@ int ICACHE_FLASH_ATTR espFsRead(EspFsFile *fh, char *buff, int len) { |
|
|
|
int flen, fdlen; |
|
|
|
int flen, fdlen; |
|
|
|
if (fh==NULL) return 0; |
|
|
|
if (fh==NULL) return 0; |
|
|
|
//Cache file length.
|
|
|
|
//Cache file length.
|
|
|
|
memcpyAligned((char*)&flen, (char*)&fh->header->fileLenComp, 4); |
|
|
|
espfs_memcpyAligned(fh->ctx, (char*)&flen, (char*)&fh->header->fileLenComp, 4); |
|
|
|
memcpyAligned((char*)&fdlen, (char*)&fh->header->fileLenDecomp, 4); |
|
|
|
espfs_memcpyAligned(fh->ctx, (char*)&fdlen, (char*)&fh->header->fileLenDecomp, 4); |
|
|
|
//Do stuff depending on the way the file is compressed.
|
|
|
|
//Do stuff depending on the way the file is compressed.
|
|
|
|
if (fh->decompressor==COMPRESS_NONE) { |
|
|
|
if (fh->decompressor==COMPRESS_NONE) { |
|
|
|
int toRead; |
|
|
|
int toRead; |
|
|
|
toRead=flen-(fh->posComp-fh->posStart); |
|
|
|
toRead=flen-(fh->posComp-fh->posStart); |
|
|
|
if (len>toRead) len=toRead; |
|
|
|
if (len>toRead) len=toRead; |
|
|
|
// os_printf("Reading %d bytes from %x\n", len, (unsigned int)fh->posComp);
|
|
|
|
// os_printf("Reading %d bytes from %x\n", len, (unsigned int)fh->posComp);
|
|
|
|
memcpyAligned(buff, fh->posComp, len); |
|
|
|
espfs_memcpyAligned(fh->ctx, buff, fh->posComp, len); |
|
|
|
fh->posDecomp+=len; |
|
|
|
fh->posDecomp+=len; |
|
|
|
fh->posComp+=len; |
|
|
|
fh->posComp+=len; |
|
|
|
// os_printf("Done reading %d bytes, pos=%x\n", len, fh->posComp);
|
|
|
|
// os_printf("Done reading %d bytes, pos=%x\n", len, fh->posComp);
|
|
|
|