RTL00_WEB_VS/RTLGDB/Project/webfs/webfs.c
ADElectronics 764b020238 update
2017-11-28 22:31:40 +03:00

483 lines
18 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*********************************************************************
* 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;
}