mirror of
https://github.com/ADElectronics/RTL00_WEB_VS.git
synced 2024-11-22 08:34:15 +00:00
483 lines
18 KiB
C
483 lines
18 KiB
C
/*********************************************************************
|
||
* WEBFS.c
|
||
* RTL871x Flash WEB File System v1.0
|
||
********************************************************************/
|
||
#include "autoconf.h"
|
||
#include "FreeRTOS.h"
|
||
#include "task.h"
|
||
#include "diag.h"
|
||
#include <osdep_api.h>
|
||
#include <osdep_service.h>
|
||
#include "device_lock.h"
|
||
#include "flash_api.h"
|
||
//#include "flash_eep.h"
|
||
|
||
#include "webfs/webfs.h"
|
||
#include "rtl8195a/rtl_libc.h"
|
||
#include "esp_comp.h"
|
||
|
||
|
||
#define WEBFS_CODE_ATTR
|
||
#define WEBFS_DATA_ATTR
|
||
|
||
#define web_mutex_lock() device_mutex_lock(RT_DEV_LOCK_FLASH)
|
||
#define web_mutex_unlock() device_mutex_unlock(RT_DEV_LOCK_FLASH)
|
||
|
||
// Supports long file names to 64 characters
|
||
#define MAX_FILE_NAME_LEN 64 // VarNameSize
|
||
uint32 disk_base_addr WEBFS_DATA_ATTR;
|
||
#define WEBFS_HEAD_ADDR disk_base_addr
|
||
/*
|
||
*
|
||
* Structure:
|
||
*
|
||
* [F][W][E][B][uint8 Ver Hi][uint8 Ver Lo] // заголовок диска
|
||
* [uint16 Number of Files] // кол-во файлов на диске
|
||
* [Name Hash 0]...[Name Hash N] // uint16 типа хеш на каждое имя файла
|
||
* [File Record 0]...[File Record N] // uint32 указатели на адреса структур файлов, относительно начала диска
|
||
*
|
||
* File Record Structure:
|
||
* [uint32 Len] размер файла с заголовком
|
||
* [uint16 HeadLen] длина заголовка, включая размер, флаг, имя (адрес данных - адрес позиции len)
|
||
* [uint16 Flags] бит 0 =1 - файл сжат GZIP, бит 1 = 1 - парсится - имеет динамические переменные
|
||
* [File Name, 0] Имя файла с "СИ" терминатором
|
||
* [File Data] данные файла
|
||
*
|
||
* Name hash (2 uint8s) is calculated as follows:
|
||
* hash = 0
|
||
* for each(uint8 in name)
|
||
* hash += uint8
|
||
* hash <<= 1
|
||
*
|
||
* Technically this means the hash only includes the
|
||
* final 15 characters of a name.
|
||
*
|
||
* String FileNmae Structure (1 to 64 uint8s):
|
||
* ["path/to/file.ext"][0x00]
|
||
*
|
||
*
|
||
* Current version is 1.0
|
||
*/
|
||
// Lock WEBFS access during the upgrade
|
||
volatile bool isWEBFSLocked WEBFS_DATA_ATTR;
|
||
// Track the WEBFS File Handles
|
||
// WEBFSStubs[0] is reserved for internal use (FAT access)
|
||
WEBFS_STUB WEBFSStubs[MAX_WEBFS_OPENFILES+1] WEBFS_DATA_ATTR; // + HANDLE = 0
|
||
// FAT record cache
|
||
WEBFS_FAT_RECORD fatCache WEBFS_DATA_ATTR;
|
||
// ID of currently loaded fatCache
|
||
static uint32 fatCacheID WEBFS_DATA_ATTR;
|
||
// Number of files in this WEBFS image
|
||
uint16 numFiles WEBFS_DATA_ATTR;
|
||
|
||
static void GetFATRecord(uint16 fatID);
|
||
static void WEBFS_Update(void);
|
||
|
||
/*****************************************************************************
|
||
Function:
|
||
void WEBFSInit(void)
|
||
Description:
|
||
Web Disk Init
|
||
*****************************************************************************/
|
||
void WEBFS_CODE_ATTR WEBFSInit(void)
|
||
{
|
||
disk_base_addr = WEBFS_base_addr();
|
||
os_memset((char *) &WEBFSStubs, 0xff, sizeof(WEBFSStubs));
|
||
// Validate the image and load numFiles
|
||
WEBFS_Update();
|
||
#if DEBUGSOO > 0
|
||
os_printf("\nDisk init: %d files, addr = %p\n", numFiles, disk_base_addr);
|
||
#endif
|
||
// тут надо расчет контрольки тела диска или другой контроль...
|
||
if(numFiles == 0) isWEBFSLocked = true;
|
||
else isWEBFSLocked = false;
|
||
}
|
||
/*****************************************************************************
|
||
Function:
|
||
WEBFS_HANDLE WEBFSOpen(uint8* cFile)
|
||
|
||
Description:
|
||
Opens a file in the WEBFS2 file system.
|
||
|
||
Precondition:
|
||
None
|
||
|
||
Parameters:
|
||
cFile - a null terminated file name to open
|
||
|
||
Returns:
|
||
An WEBFS_HANDLE to the opened file if found, or WEBFS_INVALID_HANDLE
|
||
if the file could not be found or no free handles exist.
|
||
***************************************************************************/
|
||
WEBFS_HANDLE WEBFS_CODE_ATTR WEBFSOpen(uint8* cFile)
|
||
{
|
||
WEBFS_HANDLE hWEBFS;
|
||
uint16 nameHash;
|
||
int i, len = 0;
|
||
uint16 hashCache[16];
|
||
uint8 bufname[MAX_FILE_NAME_LEN];
|
||
uint8 *ptr;
|
||
|
||
// Make sure WEBFS is unlocked and we got a filename
|
||
if(*cFile == '\0' || isWEBFSLocked == true)
|
||
return WEBFS_INVALID_HANDLE;
|
||
|
||
// Calculate the name hash to speed up searching
|
||
for(nameHash = 0, ptr = cFile; *ptr != '\0'; ptr++)
|
||
{
|
||
nameHash += *ptr;
|
||
nameHash <<= 1;
|
||
len++;
|
||
}
|
||
// Find a free file handle to use
|
||
for(hWEBFS = 1; hWEBFS <= MAX_WEBFS_OPENFILES; hWEBFS++)
|
||
if(WEBFSStubs[hWEBFS].addr == WEBFS_INVALID) break;
|
||
if(hWEBFS == MAX_WEBFS_OPENFILES)
|
||
return WEBFS_INVALID_HANDLE;
|
||
// Read in hashes, and check remainder on a match. Store 8 in cache for performance
|
||
for(i = 0; i < numFiles; i++) {
|
||
// For new block of 8, read in data
|
||
if((i & 0x0F) == 0) {
|
||
WEBFSStubs[0].addr = 12 + i*2;
|
||
WEBFSStubs[0].bytesRem = 32;
|
||
WEBFSGetArray(0, (uint8*)hashCache, 32);
|
||
}
|
||
// If the hash matches, compare the full filename
|
||
if(hashCache[i&0x0F] == nameHash)
|
||
{
|
||
GetFATRecord(i);
|
||
// filename comparison
|
||
WEBFSStubs[0].addr = fatCache.string;
|
||
WEBFSStubs[0].bytesRem = MAX_FILE_NAME_LEN;
|
||
WEBFSGetArray(0, bufname, MAX_FILE_NAME_LEN);
|
||
if(os_strncmp(cFile, bufname, len) == 0) { // Filename matches, so return true
|
||
WEBFSStubs[hWEBFS].addr = fatCache.data;
|
||
WEBFSStubs[hWEBFS].bytesRem = fatCache.len;
|
||
WEBFSStubs[hWEBFS].fatID = i;
|
||
return hWEBFS;
|
||
}
|
||
}
|
||
}
|
||
// No file name matched, so return nothing
|
||
return WEBFS_INVALID_HANDLE;
|
||
}
|
||
/*****************************************************************************
|
||
Function: void WEBFSClose(WEBFS_HANDLE hWEBFS)
|
||
Summary: Closes a file.
|
||
Returns: None
|
||
***************************************************************************/
|
||
void WEBFS_CODE_ATTR WEBFSClose(WEBFS_HANDLE hWEBFS)
|
||
{
|
||
if(hWEBFS != 0 && hWEBFS <= MAX_WEBFS_OPENFILES)
|
||
WEBFSStubs[hWEBFS].addr = WEBFS_INVALID;
|
||
}
|
||
/*****************************************************************************
|
||
Function: uint16 WEBFSGetArray(WEBFS_HANDLE hWEBFS, uint8* cData, uint16 wLen)
|
||
Description: Reads a series of uint8s from a file.
|
||
Precondition: The file handle referenced by hWEBFS is already open.
|
||
Parameters:
|
||
hWEBFS - the file handle from which to read
|
||
cData - where to store the uint8s that were read
|
||
wLen - how many uint8s to read
|
||
Returns:
|
||
The number of uint8s successfully read. If this is less than wLen,
|
||
an EOF occurred while attempting to read.
|
||
***************************************************************************/
|
||
uint16 WEBFS_CODE_ATTR WEBFSGetArray(WEBFS_HANDLE hWEBFS, uint8* cData, uint16 wLen)
|
||
{
|
||
// Make sure we're reading a valid address
|
||
if(hWEBFS > MAX_WEBFS_OPENFILES) return 0;
|
||
|
||
// Determine how many we can actually read
|
||
if(wLen > WEBFSStubs[hWEBFS].bytesRem) wLen = WEBFSStubs[hWEBFS].bytesRem;
|
||
// Make sure we're reading a valid address
|
||
if(WEBFSStubs[hWEBFS].addr == WEBFS_INVALID || wLen == 0) return 0;
|
||
|
||
if(cData != NULL) {
|
||
|
||
// Read the data
|
||
web_mutex_lock();
|
||
// if(wLen < 16)
|
||
flash_stream_read(&flashobj, WEBFSStubs[hWEBFS].addr + WEBFS_HEAD_ADDR, wLen, cData);
|
||
// else flash_burst_read(&flashobj, WEBFSStubs[hWEBFS].addr + WEBFS_HEAD_ADDR, wLen, cData);
|
||
web_mutex_unlock();
|
||
|
||
// if(spi_flash_read(WEBFSStubs[hWEBFS].addr+WEBFS_HEAD_ADDR, cData, wLen) != SPI_FLASH_RESULT_OK)
|
||
// return 0;
|
||
};
|
||
WEBFSStubs[hWEBFS].addr += wLen;
|
||
WEBFSStubs[hWEBFS].bytesRem -= wLen;
|
||
return wLen;
|
||
}
|
||
/*****************************************************************************
|
||
Function:
|
||
bool WEBFSSeek(WEBFS_HANDLE hWEBFS, uint32 dwOffset, WEBFS_SEEK_MODE tMode)
|
||
Description: Moves the current read pointer to a new location.
|
||
Precondition: The file handle referenced by hWEBFS is already open.
|
||
Parameters:
|
||
hWEBFS - the file handle to seek with
|
||
dwOffset - offset from the specified position in the specified direction
|
||
tMode - one of the WEBFS_SEEK_MODE constants
|
||
Returns:
|
||
true - the seek was successful
|
||
false - either the new location or the handle itself was invalid
|
||
***************************************************************************/
|
||
bool WEBFS_CODE_ATTR WEBFSSeek(WEBFS_HANDLE hWEBFS, uint32 dwOffset, WEBFS_SEEK_MODE tMode)
|
||
{
|
||
uint32 temp;
|
||
|
||
// Make sure a valid file is open
|
||
if(hWEBFS > MAX_WEBFS_OPENFILES || WEBFSStubs[hWEBFS].addr == WEBFS_INVALID)
|
||
return false;
|
||
|
||
switch(tMode)
|
||
{
|
||
// Seek offset uint8s from start
|
||
case WEBFS_SEEK_START:
|
||
temp = WEBFSGetSize(hWEBFS);
|
||
if(dwOffset > temp)
|
||
return false;
|
||
|
||
WEBFSStubs[hWEBFS].addr = WEBFSGetStartAddr(hWEBFS) + dwOffset;
|
||
WEBFSStubs[hWEBFS].bytesRem = temp - dwOffset;
|
||
return true;
|
||
|
||
// Seek forwards offset uint8s
|
||
case WEBFS_SEEK_FORWARD:
|
||
if(dwOffset > WEBFSStubs[hWEBFS].bytesRem)
|
||
return false;
|
||
|
||
WEBFSStubs[hWEBFS].addr += dwOffset;
|
||
WEBFSStubs[hWEBFS].bytesRem -= dwOffset;
|
||
return true;
|
||
|
||
// Seek backwards offset uint8s
|
||
case WEBFS_SEEK_REWIND:
|
||
temp = WEBFSGetStartAddr(hWEBFS);
|
||
if(WEBFSStubs[hWEBFS].addr < temp + dwOffset)
|
||
return false;
|
||
|
||
WEBFSStubs[hWEBFS].addr -= dwOffset;
|
||
WEBFSStubs[hWEBFS].bytesRem += dwOffset;
|
||
return true;
|
||
|
||
// Seek so that offset uint8s remain in file
|
||
case WEBFS_SEEK_END:
|
||
temp = WEBFSGetSize(hWEBFS);
|
||
if(dwOffset > temp)
|
||
return false;
|
||
|
||
WEBFSStubs[hWEBFS].addr = WEBFSGetEndAddr(hWEBFS) - dwOffset;
|
||
WEBFSStubs[hWEBFS].bytesRem = dwOffset;
|
||
return true;
|
||
|
||
default:
|
||
return false;
|
||
}
|
||
}
|
||
/*****************************************************************************
|
||
Function: static void GetFATRecord(uint16 fatID)
|
||
Description: Loads the FAT record for a specified handle.
|
||
Precondition: None
|
||
Parameters: fatID - the ID of the file whose FAT is to be loaded
|
||
Returns: None
|
||
Remarks: The FAT record will be stored in fatCache.
|
||
***************************************************************************/
|
||
static void WEBFS_CODE_ATTR GetFATRecord(uint16 fatID)
|
||
{
|
||
WEBFS_FHEADER fhead;
|
||
if(fatID == fatCacheID || fatID >= numFiles) return;
|
||
// Read the FAT record to the cache
|
||
WEBFSStubs[0].bytesRem = sizeof(fhead) + 4;
|
||
WEBFSStubs[0].addr = 12 + numFiles*2 + fatID *4;
|
||
WEBFSGetArray(0, (uint8 *)&fatCache.data, 4);
|
||
WEBFSStubs[0].addr = fatCache.data;
|
||
WEBFSGetArray(0, (uint8 *)&fhead, sizeof(fhead));
|
||
fatCache.len = fhead.blksize - fhead.headlen;
|
||
fatCache.string = fatCache.data + 8;
|
||
fatCache.flags = fhead.flags;
|
||
fatCache.data = fatCache.data + fhead.headlen;
|
||
fatCacheID = fatID;
|
||
}
|
||
/*****************************************************************************
|
||
Function: uint16 WEBFSGetFlags(WEBFS_HANDLE hWEBFS)
|
||
Description: Reads a file's flags.
|
||
Precondition: The file handle referenced by hWEBFS is already open.
|
||
Parameters: hWEBFS - the file handle from which to read the metadata
|
||
Returns: The flags that were associated with the file
|
||
***************************************************************************/
|
||
uint16 WEBFS_CODE_ATTR WEBFSGetFlags(WEBFS_HANDLE hWEBFS)
|
||
{
|
||
// Make sure a valid file is open
|
||
if(hWEBFS > MAX_WEBFS_OPENFILES || WEBFSStubs[hWEBFS].addr == WEBFS_INVALID)
|
||
return 0;
|
||
|
||
//move to the point for reading
|
||
GetFATRecord(WEBFSStubs[hWEBFS].fatID);
|
||
return fatCache.flags;
|
||
}
|
||
/*****************************************************************************
|
||
Function: uint32 WEBFSGetSize(WEBFS_HANDLE hWEBFS)
|
||
Description: Reads the size of a file.
|
||
Precondition: The file handle referenced by hWEBFS is already open.
|
||
Parameters: hWEBFS - the file handle from which to read the metadata
|
||
Returns: The size that was read as a uint32
|
||
***************************************************************************/
|
||
uint32 WEBFS_CODE_ATTR WEBFSGetSize(WEBFS_HANDLE hWEBFS)
|
||
{
|
||
// Make sure a valid file is open
|
||
if(hWEBFS > MAX_WEBFS_OPENFILES || WEBFSStubs[hWEBFS].addr == WEBFS_INVALID)
|
||
return 0;
|
||
|
||
// Move to the point for reading
|
||
GetFATRecord(WEBFSStubs[hWEBFS].fatID);
|
||
return fatCache.len;
|
||
}
|
||
/*****************************************************************************
|
||
Function: uint32 WEBFSGetBytesRem(WEBFS_HANDLE hWEBFS)
|
||
Description: Determines how many uint8s remain to be read.
|
||
Precondition: The file handle referenced by hWEBFS is already open.
|
||
Parameters: hWEBFS - the file handle from which to read the metadata
|
||
Returns: The number of uint8s remaining in the file as a uint32
|
||
***************************************************************************/
|
||
uint32 WEBFS_CODE_ATTR WEBFSGetBytesRem(WEBFS_HANDLE hWEBFS)
|
||
{
|
||
// Make sure a valid file is open
|
||
if(hWEBFS > MAX_WEBFS_OPENFILES || WEBFSStubs[hWEBFS].addr == WEBFS_INVALID)
|
||
return 0;
|
||
return WEBFSStubs[hWEBFS].bytesRem;
|
||
}
|
||
/*****************************************************************************
|
||
Function: WEBFS_PTR WEBFSGetStartAddr(WEBFS_HANDLE hWEBFS)
|
||
Description: Reads the starting address of a file.
|
||
Precondition: The file handle referenced by hWEBFS is already open.
|
||
Parameters: hWEBFS - the file handle from which to read the metadata
|
||
Returns: The starting address of the file in the WEBFS image
|
||
***************************************************************************/
|
||
WEBFS_PTR WEBFS_CODE_ATTR WEBFSGetStartAddr(WEBFS_HANDLE hWEBFS)
|
||
{
|
||
// Make sure a valid file is open
|
||
if(hWEBFS > MAX_WEBFS_OPENFILES || WEBFSStubs[hWEBFS].addr == WEBFS_INVALID)
|
||
return 0;
|
||
// Move to the point for reading
|
||
GetFATRecord(WEBFSStubs[hWEBFS].fatID);
|
||
return fatCache.data;
|
||
}
|
||
/*****************************************************************************
|
||
Function: WEBFS_PTR WEBFSGetEndAddr(WEBFS_HANDLE hWEBFS)
|
||
Description: Determines the ending address of a file.
|
||
Precondition: The file handle referenced by hWEBFS is already open.
|
||
Parameters: hWEBFS - the file handle from which to read the metadata
|
||
Returns: The address just after the file ends (start address of next file)
|
||
***************************************************************************/
|
||
WEBFS_PTR WEBFS_CODE_ATTR WEBFSGetEndAddr(WEBFS_HANDLE hWEBFS)
|
||
{
|
||
// Make sure a valid file is open
|
||
if(hWEBFS > MAX_WEBFS_OPENFILES || WEBFSStubs[hWEBFS].addr == WEBFS_INVALID)
|
||
return WEBFS_INVALID;
|
||
// Move to the point for reading
|
||
GetFATRecord(WEBFSStubs[hWEBFS].fatID);
|
||
return fatCache.data + fatCache.len;
|
||
}
|
||
/*****************************************************************************
|
||
Function: bool WEBFSGetFilename(WEBFS_HANDLE hWEBFS, uint8* cName, uint16 wLen)
|
||
Description: Reads the file name of a file that is already open.
|
||
Precondition: The file handle referenced by hWEBFS is already open.
|
||
Parameters:
|
||
hWEBFS - the file handle from which to determine the file name
|
||
cName - where to store the name of the file
|
||
wLen - the maximum length of data to store in cName
|
||
Returns:
|
||
true - the file name was successfully located
|
||
false - the file handle provided is not currently open
|
||
***************************************************************************/
|
||
bool WEBFS_CODE_ATTR WEBFSGetFilename(WEBFS_HANDLE hWEBFS, uint8* cName, uint16 wLen)
|
||
{
|
||
uint32 addr;
|
||
|
||
// Make sure a valid file is open
|
||
if(hWEBFS > MAX_WEBFS_OPENFILES || WEBFSStubs[hWEBFS].addr == WEBFS_INVALID)
|
||
return false;
|
||
|
||
// Move to the point for reading
|
||
GetFATRecord(WEBFSStubs[hWEBFS].fatID);
|
||
addr = fatCache.string;
|
||
WEBFSStubs[0].addr = addr;
|
||
WEBFSStubs[0].bytesRem = 255;
|
||
|
||
// Read the value and return
|
||
WEBFSGetArray(0, cName, wLen);
|
||
return true;
|
||
}
|
||
/*****************************************************************************
|
||
Function: uint32 WEBFSGetPosition(WEBFS_HANDLE hWEBFS)
|
||
Description: Determines the current position in the file
|
||
Precondition: The file handle referenced by hWEBFS is already open.
|
||
Parameters: hWEBFS - the file handle for which to determine position
|
||
Returns: The position in the file as a uint32 (or WEBFS_PTR)
|
||
***************************************************************************/
|
||
uint32 WEBFS_CODE_ATTR WEBFSGetPosition(WEBFS_HANDLE hWEBFS)
|
||
{
|
||
return WEBFSStubs[hWEBFS].addr - WEBFSGetStartAddr(hWEBFS);
|
||
}
|
||
/*****************************************************************************
|
||
Function: void WEBFS_Update(void)
|
||
Summary: Validates the WEBFS Image
|
||
Description: Verifies that the WEBFS image is valid, and reads the number of
|
||
available files from the image header. This function is called on
|
||
boot, and again after any image is written.
|
||
Parameters: None
|
||
Returns: None
|
||
***************************************************************************/
|
||
static void WEBFS_CODE_ATTR WEBFS_Update(void)
|
||
{
|
||
// Update numFiles
|
||
WEBFS_DISK_HEADER dhead;
|
||
WEBFSStubs[0].addr = 0;
|
||
WEBFSStubs[0].bytesRem = sizeof(dhead);
|
||
WEBFSGetArray(0, (uint8*)&dhead, sizeof(dhead));
|
||
if(dhead.id == WEBFS_DISK_ID && dhead.ver == WEBFS_DISK_VER) { //"FWEB"1,0 ?
|
||
numFiles = dhead.numFiles;
|
||
}
|
||
else numFiles = 0;
|
||
fatCacheID = WEBFS_INVALID_FAT;
|
||
}
|
||
/****************************************************************************
|
||
* WEBFS_max_size()
|
||
***************************************************************************/
|
||
uint32 WEBFS_CODE_ATTR WEBFS_max_size(void)
|
||
{
|
||
/*
|
||
uint32 size = spi_flash_real_size();
|
||
if(size > WEBFS_DISK_ADDR_BIGFLASH) size -= WEBFS_DISK_ADDR_BIGFLASH;
|
||
else {
|
||
size = WEBFS_DISK_ADDR_MINFLASH_END - WEBFS_DISK_ADDR_MINFLASH_START;
|
||
}
|
||
return size;
|
||
*/
|
||
return spi_flash_real_size() - WEBFS_DISK_FADDR;
|
||
}
|
||
/****************************************************************************
|
||
* WEBFS_size()
|
||
***************************************************************************/
|
||
uint32 WEBFS_CODE_ATTR WEBFS_curent_size(void)
|
||
{
|
||
uint32 size = 0;
|
||
web_mutex_lock();
|
||
if(numFiles) flash_read_word(&flashobj, disk_base_addr + 8, (uint32_t *) &size);
|
||
web_mutex_unlock();
|
||
return size;
|
||
}
|
||
/****************************************************************************
|
||
* WEBFS_size()
|
||
***************************************************************************/
|
||
uint32 WEBFS_CODE_ATTR WEBFS_base_addr(void)
|
||
{
|
||
/*
|
||
uint32 webfs_faddr;
|
||
if(flash_get_size(&flashobj) <= WEBFS_DISK_ADDR_BIGFLASH) webfs_faddr = WEBFS_DISK_ADDR_MINFLASH_START;
|
||
else webfs_faddr = WEBFS_DISK_ADDR_BIGFLASH;
|
||
return webfs_faddr;
|
||
*/
|
||
return WEBFS_DISK_FADDR;
|
||
}
|