diff --git a/src/httpserver/rest_interface.c b/src/httpserver/rest_interface.c index 307ee414c..97d298afb 100644 --- a/src/httpserver/rest_interface.c +++ b/src/httpserver/rest_interface.c @@ -55,7 +55,7 @@ static int http_rest_post_lfs_file(http_request_t* request); static int http_favicon(http_request_t* request); static int http_rest_post_reboot(http_request_t* request); -static int http_rest_post_flash(http_request_t* request, int startaddr); +static int http_rest_post_flash(http_request_t* request, int startaddr, int maxaddr); static int http_rest_get_flash(http_request_t* request, int startaddr, int len); static int http_rest_get_flash_advanced(http_request_t* request); static int http_rest_post_flash_advanced(http_request_t* request); @@ -166,7 +166,22 @@ static int http_rest_get(http_request_t* request) { #ifdef BK_LITTLEFS if (!strcmp(request->url, "api/fsblock")) { - return http_rest_get_flash(request, LFS_BLOCKS_START, LFS_BLOCKS_LEN); + uint32_t newsize = CFG_GetLFS_Size(); + uint32_t newstart = (LFS_BLOCKS_END - newsize); + + newsize = (newsize/LFS_BLOCK_SIZE)*LFS_BLOCK_SIZE; + + // double check again that we're within bounds - don't want + // boot overwrite or anything nasty.... + if (newstart < LFS_BLOCKS_START_MIN){ + return http_rest_error(request, -20, "LFS Size mismatch"); + } + if ((newstart + newsize > LFS_BLOCKS_END) || + (newstart + newsize < LFS_BLOCKS_START_MIN)){ + return http_rest_error(request, -20, "LFS Size mismatch"); + } + + return http_rest_get_flash(request, newstart, newsize); } #endif @@ -225,9 +240,9 @@ static int http_rest_post(http_request_t* request) { } if (!strcmp(request->url, "api/ota")) { #if PLATFORM_BK7231T - return http_rest_post_flash(request, START_ADR_OF_BK_PARTITION_OTA); + return http_rest_post_flash(request, START_ADR_OF_BK_PARTITION_OTA, LFS_BLOCKS_END); #elif PLATFORM_BK7231N - return http_rest_post_flash(request, START_ADR_OF_BK_PARTITION_OTA); + return http_rest_post_flash(request, START_ADR_OF_BK_PARTITION_OTA, LFS_BLOCKS_END); #else // TODO #endif @@ -246,8 +261,23 @@ static int http_rest_post(http_request_t* request) { if (lfs_present()) { release_lfs(); } + uint32_t newsize = CFG_GetLFS_Size(); + uint32_t newstart = (LFS_BLOCKS_END - newsize); + + newsize = (newsize/LFS_BLOCK_SIZE)*LFS_BLOCK_SIZE; + + // double check again that we're within bounds - don't want + // boot overwrite or anything nasty.... + if (newstart < LFS_BLOCKS_START_MIN){ + return http_rest_error(request, -20, "LFS Size mismatch"); + } + if ((newstart + newsize > LFS_BLOCKS_END) || + (newstart + newsize < LFS_BLOCKS_START_MIN)){ + return http_rest_error(request, -20, "LFS Size mismatch"); + } + // we are writing the lfs block - int res = http_rest_post_flash(request, LFS_BLOCKS_START); + int res = http_rest_post_flash(request, newstart, LFS_BLOCKS_END); // initialise the filesystem, it should be there now. // don't create if it does not mount init_lfs(0); @@ -866,7 +896,7 @@ static int http_rest_error(http_request_t* request, int code, char* msg) { } -static int http_rest_post_flash(http_request_t* request, int startaddr) { +static int http_rest_post_flash(http_request_t* request, int startaddr, int maxaddr) { #if PLATFORM_XR809 #elif PLATFORM_BL602 @@ -890,7 +920,7 @@ static int http_rest_post_flash(http_request_t* request, int startaddr) { towrite = request->contentLength; } - if (writelen < 0 || (startaddr + writelen > 0x200000)) { + if (writelen < 0 || (startaddr + writelen > maxaddr)) { ADDLOG_DEBUG(LOG_FEATURE_API, "ABORTED: %d bytes to write", writelen); return http_rest_error(request, -20, "writelen < 0 or end > 0x200000"); } @@ -899,6 +929,7 @@ static int http_rest_post_flash(http_request_t* request, int startaddr) { //ADDLOG_DEBUG(LOG_FEATURE_API, "%d bytes to write", writelen); add_otadata((unsigned char*)writebuf, writelen); total += writelen; + startaddr += writelen; towrite -= writelen; if (towrite > 0) { writebuf = request->received; @@ -945,7 +976,8 @@ static int http_rest_post_flash_advanced(http_request_t* request) { int sres; sres = sscanf(params, "%x", &startaddr); if (sres == 1 && startaddr >= START_ADR_OF_BK_PARTITION_OTA) { - return http_rest_post_flash(request, startaddr); + // allow up to end of flash + return http_rest_post_flash(request, startaddr, 0x200000); } return http_rest_error(request, -1, "invalid url"); } diff --git a/src/littlefs/our_lfs.c b/src/littlefs/our_lfs.c index 2684a06cf..5b80bcbec 100644 --- a/src/littlefs/our_lfs.c +++ b/src/littlefs/our_lfs.c @@ -12,6 +12,10 @@ #include "our_lfs.h" #include "../logging/logging.h" #include "flash_pub.h" +#include "../new_cfg.h" +#include "../new_cfg.h" +#include "../cmnds/cmd_public.h" + //https://github.com/littlefs-project/littlefs @@ -56,8 +60,12 @@ static int lfs_erase(const struct lfs_config *c, lfs_block_t block); // are propogated to the user. static int lfs_sync(const struct lfs_config *c); + +uint32_t LFS_Start = LFS_BLOCKS_END - LFS_BLOCKS_DEFAULT_LEN; +uint32_t LFS_Size = LFS_BLOCKS_DEFAULT_LEN; + // configuration of the filesystem is provided by this struct -const struct lfs_config cfg = { +struct lfs_config cfg = { // block device operations .read = lfs_read, .prog = lfs_write, @@ -68,7 +76,7 @@ const struct lfs_config cfg = { .read_size = 1, .prog_size = 1, .block_size = LFS_BLOCK_SIZE, - .block_count = (LFS_BLOCKS_LEN/LFS_BLOCK_SIZE), + .block_count = (LFS_BLOCKS_DEFAULT_LEN/LFS_BLOCK_SIZE), .cache_size = 16, .lookahead_size = 16, .block_cycles = 500, @@ -78,9 +86,158 @@ int lfs_present(){ return lfs_initialised; } +static int CMD_LFS_Size(const void *context, const char *cmd, const char *args, int cmdFlags){ + if (!args || !args[0]){ + ADDLOG_INFO(LOG_FEATURE_CMD, "unchanged LFS size 0x%X configured 0x%X", LFS_Size, CFG_GetLFS_Size()); + return 1; + } + + const char *p = args; + + uint32_t newsize = strtol(args, (char **)&p, 0); + uint32_t newstart = (LFS_BLOCKS_END - newsize); + + newsize = (newsize/LFS_BLOCK_SIZE)*LFS_BLOCK_SIZE; + + if ((newsize < LFS_BLOCKS_MIN_LEN) || (newsize > LFS_BLOCKS_MAX_LEN)) { + ADDLOG_ERROR(LOG_FEATURE_CMD, "LFSSize OUT OF BOUNDS 0x%X (range 0x%X-0x%X)", + newsize, + LFS_BLOCKS_MIN_LEN, + LFS_BLOCKS_MAX_LEN + ); + return 1; + } + + // double check again that we're within bounds - don't want + // boot overwrite or anything nasty.... + if ((newstart < LFS_BLOCKS_START_MIN) || (newstart >= LFS_BLOCKS_END)){ + ADDLOG_ERROR(LOG_FEATURE_CMD, "LFSSize OUT OF BOUNDS start 0x%X ", newstart); + return 1; + } + if ((newstart + newsize > LFS_BLOCKS_END) || + (newstart + newsize < LFS_BLOCKS_START_MIN)){ + ADDLOG_ERROR(LOG_FEATURE_CMD, "LFSSize OUT OF BOUNDS end 0x%X", newstart + newsize); + return 1; + } + + + CFG_SetLFS_Size(newsize); + ADDLOG_INFO(LOG_FEATURE_CMD, "LFS size 0x%X new configured 0x%X", LFS_Size, CFG_GetLFS_Size()); + return 1; +} + +static int CMD_LFS_Unmount(const void *context, const char *cmd, const char *args, int cmdFlags){ + if (lfs_initialised){ + release_lfs(); + ADDLOG_INFO(LOG_FEATURE_CMD, "unmounted LFS size 0x%X", LFS_Size); + } else { + ADDLOG_INFO(LOG_FEATURE_CMD, "LFS was not mounted - size 0x%X", LFS_Size); + } + return 1; +} + +static int CMD_LFS_Mount(const void *context, const char *cmd, const char *args, int cmdFlags){ + if (lfs_initialised){ + ADDLOG_INFO(LOG_FEATURE_CMD, "LFS already mounted size 0x%X", LFS_Size); + } else { + init_lfs(1); + ADDLOG_INFO(LOG_FEATURE_CMD, "LFS mounted size 0x%X", LFS_Size); + } + return 1; +} + +static int CMD_LFS_Format(const void *context, const char *cmd, const char *args, int cmdFlags){ + if (lfs_initialised){ + release_lfs(); + ADDLOG_INFO(LOG_FEATURE_CMD, "LFS released size 0x%X", LFS_Size); + } + + if (args && args[0]){ + // if we have a size, set the size first + CMD_LFS_Size(context, cmd, args, cmdFlags); + } + + uint32_t newsize = CFG_GetLFS_Size(); + + newsize = (newsize/LFS_BLOCK_SIZE)*LFS_BLOCK_SIZE; + if ((newsize < LFS_BLOCKS_MIN_LEN) || (newsize > LFS_BLOCKS_MAX_LEN)) { + ADDLOGF_ERROR("LFSSize OUT OF BOUNDS 0x%X (range 0x%X-0x%X) - defaulting to 0x%X", + newsize, + LFS_BLOCKS_MIN_LEN, + LFS_BLOCKS_MAX_LEN, + LFS_BLOCKS_DEFAULT_LEN + ); + newsize = LFS_BLOCKS_DEFAULT_LEN; + } + uint32_t newstart = (LFS_BLOCKS_END - newsize); + + // double check again that we're within bounds - don't want + // boot overwrite or anything nasty.... + if (newstart < LFS_BLOCKS_START_MIN){ + ADDLOG_ERROR(LOG_FEATURE_CMD, "LFS OUT OF BOUNDS start 0x%X too small", newstart); + return 1; + } + if ((newstart + newsize > LFS_BLOCKS_END) || + (newstart + newsize < LFS_BLOCKS_START_MIN)){ + ADDLOG_ERROR(LOG_FEATURE_CMD, "LFS OUT OF BOUNDS end 0x%X too big", newstart + newsize); + return 1; + } + + LFS_Start = newstart; + LFS_Size = newsize; + cfg.block_count = (newsize/LFS_BLOCK_SIZE); + + int err = lfs_format(&lfs, &cfg); + ADDLOG_INFO(LOG_FEATURE_CMD, "LFS formatted size 0x%X (err %d)", LFS_Size, err); + init_lfs(1); + if (!lfs_initialised){ + ADDLOG_ERROR(LOG_FEATURE_CMD, "LFS error"); + } else { + ADDLOG_INFO(LOG_FEATURE_CMD, "LFS mounted"); + } + return 1; +} + +void LFSAddCmds(){ + CMD_RegisterCommand("lfssize", NULL, CMD_LFS_Size, "Log or Set LFS size - will apply and re-format next boot, usage setlfssize 0x10000", NULL); + CMD_RegisterCommand("lfsunmount", NULL, CMD_LFS_Unmount, "Un-mount LFS", NULL); + CMD_RegisterCommand("lfsmount", NULL, CMD_LFS_Mount, "Mount LFS", NULL); + CMD_RegisterCommand("lfsformat", NULL, CMD_LFS_Format, "Unmount and format LFS. Optionally add new size as argument", NULL); +} + void init_lfs(int create){ if (!lfs_initialised){ + uint32_t newsize = CFG_GetLFS_Size(); + + // double check again that we're within bounds - don't want + // boot overwrite or anything nasty.... + newsize = (newsize/LFS_BLOCK_SIZE)*LFS_BLOCK_SIZE; + if ((newsize < LFS_BLOCKS_MIN_LEN) || (newsize > LFS_BLOCKS_MAX_LEN)) { + ADDLOGF_ERROR("LFSSize OUT OF BOUNDS 0x%X (range 0x%X-0x%X) - defaulting to 0x%X", + newsize, + LFS_BLOCKS_MIN_LEN, + LFS_BLOCKS_MAX_LEN, + LFS_BLOCKS_DEFAULT_LEN + ); + newsize = LFS_BLOCKS_DEFAULT_LEN; + } + uint32_t newstart = (LFS_BLOCKS_END - newsize); + + if (newstart < LFS_BLOCKS_START_MIN){ + ADDLOGF_ERROR("LFS OUT OF BOUNDS start 0x%X too small", newstart); + return; + } + if ((newstart + newsize > LFS_BLOCKS_END) || + (newstart + newsize < LFS_BLOCKS_START_MIN)){ + ADDLOGF_ERROR("LFS OUT OF BOUNDS end 0x%X too big", newstart + newsize); + return; + } + + LFS_Start = newstart; + LFS_Size = newsize; + cfg.block_count = (newsize/LFS_BLOCK_SIZE); + int err = lfs_mount(&lfs, &cfg); // reformat if we can't mount the filesystem @@ -136,7 +293,7 @@ void release_lfs(){ static int lfs_read(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size){ int res; - unsigned int startAddr = LFS_BLOCKS_START; + unsigned int startAddr = LFS_Start; startAddr += block*LFS_BLOCK_SIZE; startAddr += off; GLOBAL_INT_DECLARATION(); @@ -153,7 +310,7 @@ static int lfs_write(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size){ int res; int protect = FLASH_PROTECT_NONE; - unsigned int startAddr = LFS_BLOCKS_START; + unsigned int startAddr = LFS_Start; GLOBAL_INT_DECLARATION(); startAddr += block*LFS_BLOCK_SIZE; @@ -177,7 +334,7 @@ static int lfs_write(const struct lfs_config *c, lfs_block_t block, static int lfs_erase(const struct lfs_config *c, lfs_block_t block){ int res; int protect = FLASH_PROTECT_NONE; - unsigned int startAddr = LFS_BLOCKS_START; + unsigned int startAddr = LFS_Start; GLOBAL_INT_DECLARATION(); startAddr += block*LFS_BLOCK_SIZE; diff --git a/src/littlefs/our_lfs.h b/src/littlefs/our_lfs.h index 3a9e7bb03..3bda7ad8a 100644 --- a/src/littlefs/our_lfs.h +++ b/src/littlefs/our_lfs.h @@ -15,15 +15,25 @@ // start 0x1000 after OTA addr #define LFS_BLOCKS_START 0x133000 -// 512k -#define LFS_BLOCKS_LEN 0x80000 +#define LFS_BLOCKS_START_MIN 0x133000 + +// end of OTA flash +#define LFS_BLOCKS_END 0x1B3000 +// 512k MAX - i.e. no more that 0x80000 +// 0x8000 = 32k +#define LFS_BLOCKS_MIN_LEN 0x4000 +#define LFS_BLOCKS_MAX_LEN 0x80000 +#define LFS_BLOCKS_DEFAULT_LEN 0x8000 + #define LFS_BLOCK_SIZE 0x1000 extern int boot_count; extern lfs_t lfs; extern lfs_file_t file; +extern uint32_t LFS_Start; +void LFSAddCmds(); void init_lfs(); void release_lfs(); int lfs_present(); diff --git a/src/new_cfg.c b/src/new_cfg.c index 25f9d8117..381bdf3b5 100644 --- a/src/new_cfg.c +++ b/src/new_cfg.c @@ -7,6 +7,10 @@ #include "hal/hal_wifi.h" #include "hal/hal_flashConfig.h" #include "cmnds/cmd_public.h" +#ifdef BK_LITTLEFS +#include "littlefs/our_lfs.h" +#endif + #define DEFAULT_BOOT_SUCCESS_TIME 30 @@ -509,6 +513,24 @@ void CFG_SetButtonRepeatPressTime(int value) { g_cfg_pendingChanges++; } } + +#ifdef BK_LITTLEFS +void CFG_SetLFS_Size(uint32_t value) { + if(g_cfg.LFS_Size != value) { + g_cfg.LFS_Size = value; + g_cfg_pendingChanges++; + } +} + +uint32_t CFG_GetLFS_Size() { + uint32_t size = g_cfg.LFS_Size; + if (size == 0){ + size = LFS_BLOCKS_DEFAULT_LEN; + } + return size; +} +#endif + void CFG_InitAndLoad() { byte chkSum; diff --git a/src/new_cfg.h b/src/new_cfg.h index 89c1a23c2..df14da872 100644 --- a/src/new_cfg.h +++ b/src/new_cfg.h @@ -74,6 +74,11 @@ void CFG_SetButtonLongPressTime(int value); void CFG_SetButtonShortPressTime(int value); void CFG_SetButtonRepeatPressTime(int value); +#ifdef BK_LITTLEFS + void CFG_SetLFS_Size(uint32_t value); + uint32_t CFG_GetLFS_Size(); +#endif + #endif diff --git a/src/new_pins.h b/src/new_pins.h index 0e5976d05..75b9c1e0b 100644 --- a/src/new_pins.h +++ b/src/new_pins.h @@ -238,8 +238,8 @@ typedef struct mainConfig_s { byte buttonHoldRepeat; byte unused_fill1; - //unsigned long LFS_Size; will be here, and next reduced by one - unsigned long unusedSectorA[54]; + unsigned long LFS_Size; // szie of LFS volume. it's aligned against the end of OTA + unsigned long unusedSectorA[53]; // offs 0x00000594 byte unused_bytefill[3]; byte timeRequiredToMarkBootSuccessfull; diff --git a/src/user_main.c b/src/user_main.c index b5518a361..cacc692cc 100644 --- a/src/user_main.c +++ b/src/user_main.c @@ -318,10 +318,11 @@ void Main_OnEverySecond() //int mqtt_max, mqtt_cur, mqtt_mem; //MQTT_GetStats(&mqtt_cur, &mqtt_max, &mqtt_mem); //ADDLOGF_INFO("mqtt req %i/%i, free mem %i\n", mqtt_cur,mqtt_max,mqtt_mem); - ADDLOGF_INFO("%sTime %i, idle %i, free %d, MQTT %i(%i), bWifi %i, secondsWithNoPing %i, socks %i/%i\n", + ADDLOGF_INFO("%sTime %i, idle %i/s, free %d, MQTT %i(%i), bWifi %i, secondsWithNoPing %i, socks %i/%i\n", safe, g_secondsElapsed, idleCount, xPortGetFreeHeapSize(),bMQTTconnected, MQTT_GetConnectEvents(), g_bHasWiFiConnected, g_timeSinceLastPingReply, LWIP_GetActiveSockets(), LWIP_GetMaxSockets()); - + // reset so it's a per-second counter. + idleCount = 0; } // print network info @@ -527,6 +528,11 @@ void Main_Init() HTTPServer_Start(); ADDLOGF_DEBUG("Started http tcp server\r\n"); + +#ifdef BK_LITTLEFS + LFSAddCmds(); // setlfssize +#endif + // only initialise certain things if we are not in AP mode if (!bSafeMode) {