From f8c60b06686ce6ed023812d57d8ed9adf60ead20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Sun, 6 Aug 2017 11:22:45 +0200 Subject: [PATCH] parser timeout, better checksum checking and struct stuffing, shaved some bytes off RAM --- Makefile | 2 +- html_orig/_pages.php | 6 ++-- html_orig/lang/en.php | 10 +++--- html_orig/pages/cfg_term.php | 6 ++++ html_orig/pages/term.php | 2 +- user/ansi_parser.c | 70 ++++++++++++++++++++++-------------- user/ansi_parser.rl | 22 ++++++++++-- user/cgi_network.c | 6 ++-- user/cgi_persist.c | 2 +- user/cgi_sockets.c | 2 +- user/cgi_system.c | 2 +- user/cgi_term_cfg.c | 41 ++++++++++++++------- user/cgi_wifi.c | 4 +-- user/persist.c | 45 +++++++++++++++++------ user/persist.h | 17 +++++---- user/screen.c | 15 ++++++-- user/screen.h | 13 +------ user/syscfg.h | 7 ---- user/wifimgr.h | 27 ++------------ 19 files changed, 177 insertions(+), 122 deletions(-) diff --git a/Makefile b/Makefile index edde199..afc9439 100644 --- a/Makefile +++ b/Makefile @@ -65,7 +65,7 @@ LIBS += esphttpd # compiler flags using during compilation of source files CFLAGS = -Os -ggdb -std=gnu99 -Werror -Wpointer-arith -Wundef -Wall -Wl,-EL -fno-inline-functions \ -nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH \ - -Wno-address -Wno-unused -DHTTPD_MAX_BACKLOG_SIZE=8192 -DADMIN_PASSWORD=$(ADMIN_PASSWORD) + -Wno-address -Wno-unused -DHTTPD_MAX_BACKLOG_SIZE=4096 -DADMIN_PASSWORD=$(ADMIN_PASSWORD) # linker flags used to generate the main object file LDFLAGS = -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static diff --git a/html_orig/_pages.php b/html_orig/_pages.php index 8d99c1e..129cfd2 100644 --- a/html_orig/_pages.php +++ b/html_orig/_pages.php @@ -18,6 +18,9 @@ if (! function_exists('pg')) { } } +pg('cfg_term', 'cfg', 'terminal', '/cfg/term'); +pg('term_set', 'api', '', '/cfg/term/set'); + pg('cfg_wifi', 'cfg', 'wifi', '/cfg/wifi'); pg('cfg_wifi_conn', '', '', '/cfg/wifi/connecting'); pg('wifi_connstatus', 'api', '', '/cfg/wifi/connstatus'); @@ -27,9 +30,6 @@ pg('wifi_scan', 'api', '', '/cfg/wifi/scan'); pg('cfg_network', 'cfg', 'network', '/cfg/network'); pg('network_set', 'api', '', '/cfg/network/set'); -pg('cfg_term', 'cfg', 'terminal', '/cfg/term'); -pg('term_set', 'api', '', '/cfg/term/set'); - pg('cfg_system', 'cfg', 'configure', '/cfg/system'); pg('system_set', 'api', '', '/cfg/system/set'); diff --git a/html_orig/lang/en.php b/html_orig/lang/en.php index 679a72b..11d7030 100644 --- a/html_orig/lang/en.php +++ b/html_orig/lang/en.php @@ -36,6 +36,7 @@ return [ 'term.default_fg_bg' => 'Text / background', 'term.buttons' => 'Button labels', 'term.theme' => 'Color scheme', + 'term.parser_tout_ms' => 'Parser timeout', // terminal color labels 'color.0' => 'Black', @@ -115,14 +116,13 @@ return [ 'system.confirm_store_defaults' => 'Enter admin password to confirm you want to store the current settings as defaults.', 'system.password' => 'Admin password:', - 'system.restore_defaults' => 'Reset to default settings', - 'system.write_defaults' => 'Save current settings as default', - 'system.restore_hard' => 'Reset to firmware default settings', + 'system.restore_defaults' => 'Reset active settings to defaults', + 'system.write_defaults' => 'Save active settings as defaults', + 'system.restore_hard' => 'Reset active settings to firmware defaults', 'system.explain_persist' => ' ESPTerm contains two persistent memory banks, one for default and one for active settings. Active settings can be stored as defaults - by the administrator. Use the following button to revert all - active settings to their stored default values. + by the administrator (password required). ', 'system.uart' => 'Serial Port', 'system.explain_uart' => ' diff --git a/html_orig/pages/cfg_term.php b/html_orig/pages/cfg_term.php index e40863e..1a93ade 100644 --- a/html_orig/pages/cfg_term.php +++ b/html_orig/pages/cfg_term.php @@ -104,6 +104,12 @@ +
+ + +  ms +
+
diff --git a/html_orig/pages/term.php b/html_orig/pages/term.php index 3677c2e..f723cd6 100644 --- a/html_orig/pages/term.php +++ b/html_orig/pages/term.php @@ -26,7 +26,7 @@ diff --git a/user/ansi_parser.c b/user/ansi_parser.c index 7785042..feb687b 100644 --- a/user/ansi_parser.c +++ b/user/ansi_parser.c @@ -2,10 +2,11 @@ /* #line 1 "user/ansi_parser.rl" */ #include #include "ansi_parser.h" +#include "screen.h" /* Ragel constants block */ -/* #line 9 "user/ansi_parser.c" */ +/* #line 10 "user/ansi_parser.c" */ static const char _ansi_actions[] = { 0, 1, 0, 1, 1, 1, 2, 1, 3, 1, 4, 1, 5, 1, 6, 1, @@ -30,9 +31,21 @@ static const int ansi_en_OSC_body = 5; static const int ansi_en_main = 1; -/* #line 8 "user/ansi_parser.rl" */ +/* #line 9 "user/ansi_parser.rl" */ +static volatile int cs = -1; + +static ETSTimer resetTim; + +static void ICACHE_FLASH_ATTR +resetParserCb(void *arg) { + if (cs != ansi_start) { + cs = ansi_start; + warn("Parser timeout, state reset"); + } +} + /** * \brief Linear ANSI chars stream parser * @@ -49,8 +62,6 @@ static const int ansi_en_main = 1; void ICACHE_FLASH_ATTR ansi_parser(const char *newdata, size_t len) { - static int cs = -1; - // The CSI code is built here static char csi_leading; //!< Leading char, 0 if none static int csi_ni; //!< Number of the active digit @@ -69,17 +80,24 @@ ansi_parser(const char *newdata, size_t len) // Init Ragel on the first run if (cs == -1) { -/* #line 73 "user/ansi_parser.c" */ +/* #line 84 "user/ansi_parser.c" */ { cs = ansi_start; } -/* #line 46 "user/ansi_parser.rl" */ +/* #line 57 "user/ansi_parser.rl" */ + } + + // schedule state reset + if (termconf->parser_tout_ms > 0) { + os_timer_disarm(&resetTim); + os_timer_setfn(&resetTim, resetParserCb, NULL); + os_timer_arm(&resetTim, termconf->parser_tout_ms, 0); } // The parser -/* #line 83 "user/ansi_parser.c" */ +/* #line 101 "user/ansi_parser.c" */ { const char *_acts; unsigned int _nacts; @@ -315,13 +333,13 @@ execFuncs: while ( _nacts-- > 0 ) { switch ( *_acts++ ) { case 0: -/* #line 58 "user/ansi_parser.rl" */ +/* #line 76 "user/ansi_parser.rl" */ { apars_handle_plainchar((*p)); } break; case 1: -/* #line 65 "user/ansi_parser.rl" */ +/* #line 83 "user/ansi_parser.rl" */ { // Reset the CSI builder csi_leading = csi_char = 0; @@ -336,13 +354,13 @@ execFuncs: } break; case 2: -/* #line 78 "user/ansi_parser.rl" */ +/* #line 96 "user/ansi_parser.rl" */ { csi_leading = (*p); } break; case 3: -/* #line 82 "user/ansi_parser.rl" */ +/* #line 100 "user/ansi_parser.rl" */ { // x10 + digit if (csi_ni < CSI_N_MAX) { @@ -351,13 +369,13 @@ execFuncs: } break; case 4: -/* #line 89 "user/ansi_parser.rl" */ +/* #line 107 "user/ansi_parser.rl" */ { csi_ni++; } break; case 5: -/* #line 93 "user/ansi_parser.rl" */ +/* #line 111 "user/ansi_parser.rl" */ { csi_char = (*p); @@ -367,14 +385,14 @@ execFuncs: } break; case 6: -/* #line 101 "user/ansi_parser.rl" */ +/* #line 119 "user/ansi_parser.rl" */ { apars_handle_badseq(); {cs = 1;goto _again;} } break; case 7: -/* #line 118 "user/ansi_parser.rl" */ +/* #line 136 "user/ansi_parser.rl" */ { csi_ni = 0; @@ -390,20 +408,20 @@ execFuncs: } break; case 8: -/* #line 132 "user/ansi_parser.rl" */ +/* #line 150 "user/ansi_parser.rl" */ { apars_handle_OSC_SetScreenSize(csi_n[0], csi_n[1]); {cs = 1;goto _again;} } break; case 9: -/* #line 137 "user/ansi_parser.rl" */ +/* #line 155 "user/ansi_parser.rl" */ { osc_buffer[osc_bi++] = (*p); } break; case 10: -/* #line 141 "user/ansi_parser.rl" */ +/* #line 159 "user/ansi_parser.rl" */ { osc_buffer[osc_bi++] = '\0'; apars_handle_OSC_SetTitle(osc_buffer); @@ -411,7 +429,7 @@ execFuncs: } break; case 11: -/* #line 147 "user/ansi_parser.rl" */ +/* #line 165 "user/ansi_parser.rl" */ { osc_buffer[osc_bi++] = '\0'; apars_handle_OSC_SetButton(csi_n[0], osc_buffer); @@ -419,7 +437,7 @@ execFuncs: } break; case 12: -/* #line 159 "user/ansi_parser.rl" */ +/* #line 177 "user/ansi_parser.rl" */ { // Reset screen apars_handle_RESET_cmd(); @@ -427,20 +445,20 @@ execFuncs: } break; case 13: -/* #line 165 "user/ansi_parser.rl" */ +/* #line 183 "user/ansi_parser.rl" */ { apars_handle_saveCursorAttrs(); {cs = 1;goto _again;} } break; case 14: -/* #line 170 "user/ansi_parser.rl" */ +/* #line 188 "user/ansi_parser.rl" */ { apars_handle_restoreCursorAttrs(); {cs = 1;goto _again;} } break; -/* #line 444 "user/ansi_parser.c" */ +/* #line 462 "user/ansi_parser.c" */ } } goto _again; @@ -458,7 +476,7 @@ _again: while ( __nacts-- > 0 ) { switch ( *__acts++ ) { case 6: -/* #line 101 "user/ansi_parser.rl" */ +/* #line 119 "user/ansi_parser.rl" */ { apars_handle_badseq(); {cs = 1; if ( p == pe ) @@ -466,7 +484,7 @@ _again: goto _again;} } break; -/* #line 470 "user/ansi_parser.c" */ +/* #line 488 "user/ansi_parser.c" */ } } } @@ -474,6 +492,6 @@ goto _again;} _out: {} } -/* #line 190 "user/ansi_parser.rl" */ +/* #line 208 "user/ansi_parser.rl" */ } diff --git a/user/ansi_parser.rl b/user/ansi_parser.rl index 37c33bc..7c3f35d 100644 --- a/user/ansi_parser.rl +++ b/user/ansi_parser.rl @@ -1,5 +1,6 @@ #include #include "ansi_parser.h" +#include "screen.h" /* Ragel constants block */ %%{ @@ -7,6 +8,18 @@ write data; }%% +static volatile int cs = -1; + +static ETSTimer resetTim; + +static void ICACHE_FLASH_ATTR +resetParserCb(void *arg) { + if (cs != ansi_start) { + cs = ansi_start; + warn("Parser timeout, state reset"); + } +} + /** * \brief Linear ANSI chars stream parser * @@ -23,8 +36,6 @@ void ICACHE_FLASH_ATTR ansi_parser(const char *newdata, size_t len) { - static int cs = -1; - // The CSI code is built here static char csi_leading; //!< Leading char, 0 if none static int csi_ni; //!< Number of the active digit @@ -45,6 +56,13 @@ ansi_parser(const char *newdata, size_t len) %% write init; } + // schedule state reset + if (termconf->parser_tout_ms > 0) { + os_timer_disarm(&resetTim); + os_timer_setfn(&resetTim, resetParserCb, NULL); + os_timer_arm(&resetTim, termconf->parser_tout_ms, 0); + } + // The parser %%{ #/* diff --git a/user/cgi_network.c b/user/cgi_network.c index 9b451de..66bed17 100644 --- a/user/cgi_network.c +++ b/user/cgi_network.c @@ -28,9 +28,9 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiNetworkSetParams(HttpdConnData *connData) { static ETSTimer timer; - char buff[50]; + char buff[20]; + char redir_url_buf[100]; - char redir_url_buf[300]; char *redir_url = redir_url_buf; redir_url += sprintf(redir_url, SET_REDIR_ERR); // we'll test if anything was printed by looking for \0 in failed_keys_buf @@ -201,7 +201,7 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiNetworkSetParams(HttpdConnData *connData) //Template code for the WLAN page. httpd_cgi_state ICACHE_FLASH_ATTR tplNetwork(HttpdConnData *connData, char *token, void **arg) { - char buff[100]; + char buff[20]; u8 mac[6]; if (token == NULL) { diff --git a/user/cgi_persist.c b/user/cgi_persist.c index 3a18c5d..92bfefd 100644 --- a/user/cgi_persist.c +++ b/user/cgi_persist.c @@ -20,7 +20,7 @@ verify_admin_pw(const char *pw) httpd_cgi_state ICACHE_FLASH_ATTR cgiPersistWriteDefaults(HttpdConnData *connData) { - char buff[50]; + char buff[PASSWORD_LEN]; if (connData->conn == NULL) { //Connection aborted. Clean up. diff --git a/user/cgi_sockets.c b/user/cgi_sockets.c index 45fc5c1..1b9283d 100644 --- a/user/cgi_sockets.c +++ b/user/cgi_sockets.c @@ -6,7 +6,7 @@ #include "uart_driver.h" #include "screen.h" -#define SOCK_BUF_LEN 2048 +#define SOCK_BUF_LEN 1024 static char sock_buff[SOCK_BUF_LEN]; volatile bool notify_available = true; diff --git a/user/cgi_system.c b/user/cgi_system.c index a834be1..f1c044c 100755 --- a/user/cgi_system.c +++ b/user/cgi_system.c @@ -61,8 +61,8 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiSystemCfgSetParams(HttpdConnData *connData) { char buff[50]; + char redir_url_buf[100]; - char redir_url_buf[300]; char *redir_url = redir_url_buf; redir_url += sprintf(redir_url, SET_REDIR_ERR); // we'll test if anything was printed by looking for \0 in failed_keys_buf diff --git a/user/cgi_term_cfg.c b/user/cgi_term_cfg.c index ccdb260..7026818 100644 --- a/user/cgi_term_cfg.c +++ b/user/cgi_term_cfg.c @@ -19,8 +19,9 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiTermCfgSetParams(HttpdConnData *connData) { char buff[50]; + char redir_url_buf[100]; + int n, w, h; - char redir_url_buf[300]; char *redir_url = redir_url_buf; redir_url += sprintf(redir_url, SET_REDIR_ERR); // we'll test if anything was printed by looking for \0 in failed_keys_buf @@ -33,11 +34,11 @@ cgiTermCfgSetParams(HttpdConnData *connData) // width and height must always go together so we can do max size validation if (GET_ARG("term_width")) { dbg("Default screen width: %s", buff); - int w = atoi(buff); + w = atoi(buff); if (w > 1) { if (GET_ARG("term_height")) { dbg("Default screen height: %s", buff); - int h = atoi(buff); + h = atoi(buff); if (h > 1) { if (w * h <= MAX_SCREEN_SIZE) { termconf->width = w; @@ -63,20 +64,31 @@ cgiTermCfgSetParams(HttpdConnData *connData) if (GET_ARG("default_bg")) { dbg("Screen default BG: %s", buff); - int color = atoi(buff); - if (color >= 0 && color < 16) { - termconf->default_bg = (u8) color; + n = atoi(buff); + if (n >= 0 && n < 16) { + termconf->default_bg = (u8) n; } else { warn("Bad color %s", buff); redir_url += sprintf(redir_url, "default_bg,"); } } + if (GET_ARG("parser_tout_ms")) { + dbg("Parser timeout: %s ms", buff); + n = atoi(buff); + if (n >= 0) { + termconf->parser_tout_ms = (u8) n; + } else { + warn("Bad timeout %s", buff); + redir_url += sprintf(redir_url, "parser_tout_ms,"); + } + } + if (GET_ARG("default_fg")) { dbg("Screen default FG: %s", buff); - int color = atoi(buff); - if (color >= 0 && color < 16) { - termconf->default_fg = (u8) color; + n = atoi(buff); + if (n >= 0 && n < 16) { + termconf->default_fg = (u8) n; } else { warn("Bad color %s", buff); redir_url += sprintf(redir_url, "default_fg,"); @@ -85,9 +97,9 @@ cgiTermCfgSetParams(HttpdConnData *connData) if (GET_ARG("theme")) { dbg("Screen color theme: %s", buff); - int theme = atoi(buff); - if (theme >= 0 && theme <= 5) { // ALWAYS ADJUST WHEN ADDING NEW THEME! - termconf->theme = (u8) theme; + n = atoi(buff); + if (n >= 0 && n <= 5) { // ALWAYS ADJUST WHEN ADDING NEW THEME! + termconf->theme = (u8) n; } else { warn("Bad theme num: %s", buff); redir_url += sprintf(redir_url, "theme,"); @@ -127,7 +139,7 @@ cgiTermCfgSetParams(HttpdConnData *connData) httpd_cgi_state ICACHE_FLASH_ATTR tplTermCfg(HttpdConnData *connData, char *token, void **arg) { -#define BUFLEN 100 +#define BUFLEN TERM_TITLE_LEN char buff[BUFLEN]; char buff2[10]; @@ -144,6 +156,9 @@ tplTermCfg(HttpdConnData *connData, char *token, void **arg) else if (streq(token, "term_height")) { sprintf(buff, "%d", termconf->height); } + else if (streq(token, "parser_tout_ms")) { + sprintf(buff, "%d", termconf->parser_tout_ms); + } else if (streq(token, "theme")) { sprintf(buff, "%d", termconf->theme); } diff --git a/user/cgi_wifi.c b/user/cgi_wifi.c index 78c7720..67fb0c6 100644 --- a/user/cgi_wifi.c +++ b/user/cgi_wifi.c @@ -325,8 +325,8 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiWiFiSetParams(HttpdConnData *connData) static ETSTimer timer; char buff[50]; + char redir_url_buf[100]; // this is just barely enough - but it's split into two forms, so we never have error in all fields - char redir_url_buf[300]; char *redir_url = redir_url_buf; redir_url += sprintf(redir_url, SET_REDIR_ERR); // we'll test if anything was printed by looking for \0 in failed_keys_buf @@ -507,7 +507,7 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiWiFiSetParams(HttpdConnData *connData) //Template code for the WLAN page. httpd_cgi_state ICACHE_FLASH_ATTR tplWlan(HttpdConnData *connData, char *token, void **arg) { - char buff[100]; + char buff[PASSWORD_LEN]; int x; int connectStatus; diff --git a/user/persist.c b/user/persist.c index 14d9573..dd89036 100644 --- a/user/persist.c +++ b/user/persist.c @@ -17,23 +17,45 @@ static void ICACHE_FLASH_ATTR apply_live_settings(void) { dbg("[Persist] Applying live settings..."); - terminal_apply_settings(); - wifimgr_apply_settings(); + + dbg("[Persist] > system"); sysconf_apply_settings(); + + dbg("[Persist] > wifi"); + wifimgr_apply_settings(); + + dbg("[Persist] > terminal"); + terminal_apply_settings(); + + dbg("[Persist] Live settings applied."); // ... } static void ICACHE_FLASH_ATTR restore_live_settings_to_hard_defaults(void) { + dbg("[Persist] Restore to hard defaults..."); + + dbg("[Persist] > system"); + sysconf_restore_defaults(); + + dbg("[Persist] > wifi"); wifimgr_restore_defaults(); + + dbg("[Persist] > terminal"); terminal_restore_defaults(); - sysconf_restore_defaults(); + + dbg("[Persist] Restored to hard defaults."); // ... } //endregion +const u32 wconf_at = (u32)&persist.defaults.wificonf - (u32)&persist.defaults; +const u32 tconf_at = (u32)&persist.defaults.termconf - (u32)&persist.defaults; +const u32 sconf_at = (u32)&persist.defaults.sysconf - (u32)&persist.defaults; +const u32 cksum_at = (u32)&persist.defaults.checksum - (u32)&persist.defaults; + /** * Compute CRC32. Adapted from https://github.com/esp8266/Arduino * @param data @@ -43,7 +65,9 @@ restore_live_settings_to_hard_defaults(void) static uint32_t ICACHE_FLASH_ATTR calculateCRC32(const uint8_t *data, size_t length) { - uint32_t crc = 0xffffffff + CHECKSUM_SALT; + // the salt here should ensure settings are wiped when the structure changes + // CHECKSUM_SALT can be adjusted manually to force a reset. + uint32_t crc = 0xffffffff + CHECKSUM_SALT + ((wconf_at << 16) ^ (tconf_at << 10) ^ (sconf_at << 5)); while (length--) { uint8_t c = *data++; for (uint32_t i = 0x80; i > 0; i >>= 1) { @@ -81,13 +105,12 @@ persist_load(void) { info("[Persist] Loading stored settings from FLASH..."); - dbg("sizeof(AppConfigBundle) = %d bytes", sizeof(AppConfigBundle)); - dbg("> sizeof(WiFiConfigBundle) = %d bytes", sizeof(WiFiConfigBundle)); - dbg("> sizeof(TerminalConfigBundle) = %d bytes", sizeof(TerminalConfigBundle)); - dbg("> sizeof(SystemConfigBundle) = %d bytes", sizeof(SystemConfigBundle)); - dbg("> sizeof(checksum) = %d bytes", sizeof(uint32_t)); - dbg("> filler = %d bytes", - sizeof(AppConfigBundle) - (sizeof(WiFiConfigBundle) + sizeof(TerminalConfigBundle) + sizeof(SystemConfigBundle))); + dbg("AppConfigBundle memory map:"); + dbg("> WiFiConfigBundle at %4d (error %2d)", wconf_at, wconf_at - 0); + dbg("> SystemConfigBundle at %4d (error %2d)", sconf_at, sconf_at - WIFICONF_SIZE); + dbg("> TerminalConfigBundle at %4d (error %2d)", tconf_at, tconf_at - WIFICONF_SIZE - SYSCONF_SIZE); + dbg("> Checksum at %4d (error %2d)", cksum_at, cksum_at - (APPCONF_SIZE - 4)); + dbg("> Total size = %d bytes (error %d)", sizeof(AppConfigBundle), APPCONF_SIZE - sizeof(AppConfigBundle)); bool hard_reset = false; diff --git a/user/persist.h b/user/persist.h index aa05e52..aba195b 100644 --- a/user/persist.h +++ b/user/persist.h @@ -16,15 +16,20 @@ // Changing this could be used to force-erase the config area // after a firmware upgrade -#define CHECKSUM_SALT 2 +#define CHECKSUM_SALT 3 #define APPCONF_SIZE 2048 /** Struct for current or default settings */ typedef struct { // the entire block should be 1024 bytes long (for compatibility across upgrades) WiFiConfigBundle wificonf; - TerminalConfigBundle termconf; + uint8_t _filler1[WIFICONF_SIZE - sizeof(WiFiConfigBundle)]; + SystemConfigBundle sysconf; + uint8_t _filler3[SYSCONF_SIZE - sizeof(SystemConfigBundle)]; + + TerminalConfigBundle termconf; + uint8_t _filler2[TERMCONF_SIZE - sizeof(TerminalConfigBundle)]; // --- Space for future settings --- // The size must be appropriately reduced each time something is added, @@ -34,12 +39,12 @@ typedef struct { // the entire block should be 1024 bytes long (for compatibilit // This ensures user settings are not lost each time they upgrade the firmware, // which would lead to a checksum mismatch if the structure was changed and // it grew to a different memory area. - uint8_t filler[ + uint8_t _filler_end[ APPCONF_SIZE - sizeof(uint32_t) // checksum - - sizeof(WiFiConfigBundle) - - sizeof(TerminalConfigBundle) - - sizeof(SystemConfigBundle) + - WIFICONF_SIZE + - SYSCONF_SIZE + - TERMCONF_SIZE ]; uint32_t checksum; // computed before write and tested on load. If it doesn't match, values are reset to hard defaults. diff --git a/user/screen.c b/user/screen.c index 88e023e..a7132c1 100644 --- a/user/screen.c +++ b/user/screen.c @@ -8,6 +8,9 @@ TerminalConfigBundle * const termconf = &persist.current.termconf; TerminalConfigBundle termconf_scratch; +#define W termconf_scratch.width +#define H termconf_scratch.height + /** * Restore hard defaults */ @@ -17,6 +20,7 @@ void terminal_restore_defaults(void) termconf->default_fg = 7; termconf->width = 26; termconf->height = 10; + termconf->parser_tout_ms = 10; sprintf(termconf->title, "ESPTerm"); for(int i=1; i <= 5; i++) { sprintf(termconf->btn[i-1], "%d", i); @@ -29,12 +33,16 @@ void terminal_restore_defaults(void) void terminal_apply_settings(void) { memcpy(&termconf_scratch, termconf, sizeof(TerminalConfigBundle)); + if (W*H >= MAX_SCREEN_SIZE) { + error("BAD SCREEN SIZE: %d rows x %d cols", H, W); + error("reverting terminal settings to default"); + terminal_restore_defaults(); + persist_store(); + memcpy(&termconf_scratch, termconf, sizeof(TerminalConfigBundle)); + } screen_init(); } -#define W termconf_scratch.width -#define H termconf_scratch.height - /** * Highest permissible value of the color attribute */ @@ -105,6 +113,7 @@ static volatile int notifyLock = 0; static inline void clear_range(unsigned int from, unsigned int to) { + if (to >= W*H) to = W*H-1; Color fg = cursor.inverse ? cursor.bg : cursor.fg; Color bg = cursor.inverse ? cursor.fg : cursor.bg; for (unsigned int i = from; i <= to; i++) { diff --git a/user/screen.h b/user/screen.h index a1d17fc..0e21fbf 100644 --- a/user/screen.h +++ b/user/screen.h @@ -56,18 +56,7 @@ typedef struct { char title[TERM_TITLE_LEN]; char btn[5][TERM_BTN_LEN]; u8 theme; - - u8 _filler[ - TERMCONF_SIZE - - 4 - - 4 - - 1 - - 1 - - 1 - - TERM_TITLE_LEN - - TERM_BTN_LEN * 5 - ]; - + u32 parser_tout_ms; } TerminalConfigBundle; // Live config diff --git a/user/syscfg.h b/user/syscfg.h index 3fe65ed..6b9f607 100644 --- a/user/syscfg.h +++ b/user/syscfg.h @@ -15,13 +15,6 @@ typedef struct { u32 uart_baudrate; u8 uart_parity; u8 uart_stopbits; - - u8 _filler[ - SYSCONF_SIZE - - 4 - - 1 - - 1 - ]; } SystemConfigBundle; extern SystemConfigBundle * const sysconf; diff --git a/user/wifimgr.h b/user/wifimgr.h index 165067d..060fb90 100644 --- a/user/wifimgr.h +++ b/user/wifimgr.h @@ -27,42 +27,21 @@ typedef struct { WIFI_MODE opmode : 8; u8 tpw; - // --- AP config --- + // AP config u8 ap_channel; u8 ap_ssid[SSID_LEN]; u8 ap_password[PASSWORD_LEN]; bool ap_hidden; + // u16 ap_dhcp_time; // in minutes struct dhcps_lease ap_dhcp_range; - struct ip_info ap_addr; - // --- Client config --- + // Client config u8 sta_ssid[SSID_LEN]; u8 sta_password[PASSWORD_LEN]; bool sta_dhcp_enable; struct ip_info sta_addr; - - u8 _filler[ - WIFICONF_SIZE - - 1 - - 1 - - - 1 - - SSID_LEN - - PASSWORD_LEN - - 1 - - 2 - - sizeof(struct dhcps_lease) - - - sizeof(struct ip_info) - - - SSID_LEN - - PASSWORD_LEN - - 1 - - sizeof(struct ip_info) - - 8 // padding? - ]; } WiFiConfigBundle; typedef struct {