From 03b7473d4faddcb87a5e82205a42028768e7c177 Mon Sep 17 00:00:00 2001 From: Gediminas Jakutis Date: Sat, 19 May 2018 12:02:08 +0300 Subject: add support for "live"-flashing new settings. --- src/server/util.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) (limited to 'src/server/util.c') diff --git a/src/server/util.c b/src/server/util.c index bb494c8..4aee886 100644 --- a/src/server/util.c +++ b/src/server/util.c @@ -18,12 +18,32 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include #include "util.h" #include "net.h" +#include "gtk.h" + +struct child_data { + char **argv; + int fd; + char *buf; +}; static float digest_temp(const short int rawtemp); static float digest_volt(const short int rawvolt); +static int find_settings_region(char *start, char *end, char *buf, size_t n); +static int flash(char *buf, size_t address, size_t size, char* port); +void reap_dead_children(int pid, int status, void *data); /* * raw data is in 0.1°K per 1. Subtract 2730 to get Celsius. @@ -57,3 +77,125 @@ int refresh_data(int nd, struct tempmodule_state *state) return ret; } + + +int write_settings(char *imagename, const struct configuration * const conf) +{ + /* the largest flash size supported by ESP-8266 is 16MiB, so let's just use that. */ + static const size_t flash_size = 16 * 1024 * 1024; + char pattern_a[4] = PADDING_START; + char pattern_b[4] = PADDING_END; + ssize_t buf_used; + ssize_t offset; + char *buf = NULL; + int fd; + int ret = ERROR; + + fd = open(imagename, O_RDONLY); + if (fd < 0) { + goto fail; + } + buf = malloc(flash_size); + buf_used = read(fd, buf, flash_size); + close(fd); + if (buf_used < sizeof(struct configuration)) { + goto fail; + } + + offset = find_settings_region(pattern_a, pattern_b, buf, buf_used); + if (offset == ERROR) { + goto fail; + }; + + memcpy(buf + offset, conf, sizeof(struct configuration)); + /* make sure the block written is aligned on 4k boundry + * and is 4k of size. + * + * see: + * https://github.com/espressif/esptool/issues/306 + */ + offset &= ~(0xfff); + ret = flash(buf + offset, offset, 4 * 1024, NULL); + +fail: + free(buf); + return ret; +} + +static int find_settings_region(char *start, char *end, char *buf, size_t n) +{ + int ret = ERROR; + char *a; + + if (!(a = memmem(buf, n, start, 4))) { + goto fail; + } + + if ((a - buf + sizeof(struct configuration)) > n) { + goto fail; + } + + if (memcmp(a + sizeof(struct configuration) - 4, end, 4)) { + goto fail; + } + + ret = a - buf; +fail: + return ret; +} + +static int flash(char *buf, size_t address, size_t size, char* port) +{ + static const char esptool[] = "esptool.py"; + static const char command[] = "write_flash"; + struct child_data *cdata; + char tmpfn[] = "espXXXXXX"; /* temporary file name template */ + char *fifn; /* flash image file name */ + char textbuf[32]; + char *argv[7] = {0}; + int ret = ERROR; + pid_t pid; + int fd; + size_t i = 1; + + fd = mkstemp(tmpfn); + write(fd, buf, size); + fifn = malloc(0x100); + memset(fifn, '\0', 0x100); + sprintf(textbuf, "/proc/self/fd/%d", fd); + if (readlink(textbuf, fifn, 0x100) == -1) { + exit(TMPFILE); + } + + argv[0] = strdup(esptool); + if (port) { + argv[i++] = strdup("--port"); + argv[i++] = strdup(port); + } + argv[i++] = strdup(command); + sprintf(textbuf, "%#.4lx", address); + argv[i++] = strdup(textbuf); + argv[i++] = strdup(fifn); + argv[i] = NULL; + + cdata = malloc(sizeof(*cdata)); + cdata->argv = argv; + cdata->fd = fd; + cdata->buf = fifn; + + g_spawn_async_with_pipes(NULL, argv, NULL, G_SPAWN_SEARCH_PATH | G_SPAWN_LEAVE_DESCRIPTORS_OPEN | G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &pid, NULL, NULL, NULL, NULL); + g_child_watch_add(pid, reap_dead_children, cdata); + return ret; +} + +void reap_dead_children(int pid, int status, void *data) +{ + struct child_data *a; + + a = data; + free(a->buf); + close(a->fd); + free(data); + g_spawn_close_pid(pid); + gtkui_dialog_done(status); +} -- cgit v1.2.3