Browse Source

httpd: backend for programming board revision

H. Peter Anvin 2 years ago
parent
commit
2533d0ac15

+ 1 - 1
esp32/max80/boardinfo.c

@@ -164,5 +164,5 @@ int board_info_set(const char *board_id_string)
     if (unchanged)
 	return 0;		/* Not modified, so don't reflash */
 
-    board_info_update_flash();
+    return board_info_update_flash();
 }

+ 120 - 5
esp32/max80/httpd.c

@@ -1,9 +1,11 @@
 #define MODULE "httpd"
+#define DEBUG 1
 
 #include "common.h"
 #include "fw.h"
 #include "httpd.h"
 #include "config.h"
+#include "boardinfo_esp.h"
 
 #include <incbin.h>
 #include <unzipLIB.h>
@@ -209,7 +211,7 @@ static esp_err_t httpd_send_plain(httpd_req_t *req,
 
     const char * const refresher = refresher_buf ? refresher_buf : "";
     const char * const uncacher = (flags & HSP_UNCACHE)
-      ? "Clear-Site-Data: \"cache\"\r\n" : "";
+	? "Clear-Site-Data: \"cache\"\r\n" : "";
 
     if (redirect) {
 	/* \0 -> \n so don't include it */
@@ -295,6 +297,17 @@ static esp_err_t httpd_err_enomem(httpd_req_t *req)
     return HTTP_ERR(req, 503, "Out of memory");
 }
 
+static esp_err_t httpd_err_not_post(httpd_req_t *req)
+{
+    return HTTP_ERR(req, 405, "Only POST allowed");
+}
+
+#define HTTPD_ASSERT_POST(req)			\
+    do {					\
+	if ((req)->method != HTTP_POST)		\
+	    return httpd_err_not_post(req);	\
+    } while (0)
+
 static esp_err_t httpd_update_done(httpd_req_t *req, const char *what, int err)
 {
     char *response = NULL;
@@ -328,6 +341,8 @@ static esp_err_t httpd_firmware_update(httpd_req_t *req)
 {
     int rv;
 
+    HTTPD_ASSERT_POST(req);
+
     /* XXX: use httpd_fopen_read() here */
     rv = firmware_update_start((read_func_t)httpd_req_recv, (token_t)req, false);
     if (!rv)
@@ -360,6 +375,103 @@ static esp_err_t httpd_set_config(httpd_req_t *req, const char *query)
     return httpd_update_done(req, "Configuration", rv1 ? rv1 : rv2);
 }
 
+static inline bool is_eol(int c)
+{
+    return c == EOF || c == '\0' || c == '\r' || c == '\n';
+}
+
+static esp_err_t httpd_set_board_rev(httpd_req_t *req)
+{
+    FILE *f = NULL;
+    static const char rev_prefix[] = "max80.hw.ver";
+    static const char rev_valid[] = "MAX80 v";
+    char *rev_str;
+    int err = Z_DATA_ERROR;
+    enum sbr_parse_state {
+	ps_start,
+	ps_prefix,
+	ps_string,
+	ps_skipline
+    };
+    enum sbr_parse_state state;
+    const char *match_ptr = NULL;
+    char *p = NULL;
+    int c;
+
+    HTTPD_ASSERT_POST(req);
+
+    rev_str = malloc(sizeof board_info.version_str);
+    if (!rev_str)
+	return httpd_err_enomem(req);
+
+    f = httpd_fopen_read(req);
+    if (!f) {
+	free(rev_str);
+	return HTTP_ERR(req, 500, "Unable to get request handle");
+    }
+
+    state = ps_start;
+
+    do {
+	bool eol;
+
+	c = getc(f);
+	eol = is_eol(c);
+
+	switch (state) {
+	case ps_start:
+	    match_ptr = rev_prefix;
+	    state = ps_prefix;
+	    /* fall through */
+
+	case ps_prefix:
+	    if (eol) {
+		state = ps_start;
+	    } else if (*match_ptr && c == *match_ptr) {
+		match_ptr++;
+	    } else if (!*match_ptr && c == '=') {
+		p = rev_str;
+		state = ps_string;
+	    } else {
+		state = ps_skipline;
+	    }
+	    break;
+
+	case ps_string:
+	    if (eol) {
+		*p = '\0';
+		if (!memcmp(rev_str, rev_valid, sizeof rev_valid - 1)) {
+		    /* Otherwise input truncated or invalid */
+		    printf("[HTTP] setting board revision: %s\n", rev_str);
+		    if (!board_info_set(rev_str)) {
+			setenv_cond("status.max80.hw.ver",
+				    board_info.version_str);
+			err = Z_OK;
+		    } else {
+			err = FWUPDATE_ERR_CONFIG_SAVE;
+		    }
+		}
+		state = ps_start;
+	    } else if (p - rev_str >= sizeof board_info.version_str - 1) {
+		state = ps_skipline;
+	    } else {
+		*p++ = c;
+	    }
+	    break;
+
+	case ps_skipline:
+	    if (eol)
+		state = ps_start;
+	    break;
+	}
+    } while (c != EOF);
+
+    fclose(f);
+    free(rev_str);
+
+    return httpd_update_done(req, "board revision", err);
+}
+
 #define MIN_STATUS_REF 1	/* Minimum refresh time in s */
 
 static void httpd_get_status_extra(FILE *f, httpd_req_t *req)
@@ -444,9 +556,9 @@ static esp_err_t httpd_lang_redirect(httpd_req_t *req)
     return httpd_send_plain(req, 302, lang_buf, len, 0, 0);
 }
 
-#define STRING_MATCHES(str, len, what) \
+#define STRING_MATCHES(str, len, what)					\
     (((len) == sizeof(what)-1) && !memcmp((str), (what), sizeof(what)-1))
-#define STRING_MATCHES_PREFIX(str, len, what) \
+#define STRING_MATCHES_PREFIX(str, len, what)				\
     (((len) >= sizeof(what)-1) && !memcmp((str), (what), sizeof(what)-1))
 
 static esp_err_t httpd_sys_handler(httpd_req_t *req)
@@ -477,7 +589,7 @@ static esp_err_t httpd_sys_handler(httpd_req_t *req)
     if (STRING_MATCHES(file, filelen, "getconfig"))
 	return httpd_get_config_status(req, false);
 
-    if (req->method == HTTP_POST && STRING_MATCHES(file, filelen, "fwupdate"))
+    if (STRING_MATCHES(file, filelen, "fwupdate"))
 	return httpd_firmware_update(req);
 
     if (STRING_MATCHES(file, filelen, "setconfig"))
@@ -489,6 +601,9 @@ static esp_err_t httpd_sys_handler(httpd_req_t *req)
     if (STRING_MATCHES(file, filelen, "setlang"))
 	return httpd_set_lang(req, query);
 
+    if (STRING_MATCHES(file, filelen, "setboardrev"))
+	return httpd_set_board_rev(req);
+
     return httpd_err_enoent(req);
 }
 
@@ -868,7 +983,7 @@ void my_httpd_start(void)
     config.uri_match_fn = httpd_uri_match_prefix;
 
     if (httpd_start(&server, &config) != ESP_OK)
-      return;
+	return;
 
     esp_register_shutdown_handler(my_httpd_stop);
 

+ 1 - 1
esp32/max80/max80.ino

@@ -122,7 +122,7 @@ void setup() {
 
     printf("[FW]   MAX80 firmware compiled on %s\n", fwdate);
     printf("[PCB]  MAX80 board version: %s\n", board_info.version_str);
-    setenv_cond("status.max80.hw.ver", board_info.version_str + 7);
+    setenv_cond("status.max80.hw.ver", board_info.version_str);
     Serial.println("MAX80 start");
 
     init_config();

BIN
esp32/output/max80.ino.bin


+ 3 - 2
esp32/www/update.html

@@ -8,7 +8,7 @@
   <body>
     <x-inc src="head.html"></x-inc>
     <h1 class="update">Update</h1>
-    <form id="boardid" action="sys/boardrev" method="post"
+    <form id="boardid" action="sys/setboardrev" method="post"
 	  onsubmit="uploadform()" data-ref="1" data-ref-url="update.html">
       <fieldset>
 	<legend>Board Revision</legend>
@@ -24,7 +24,8 @@
 	    <option value="MAX80 v2.0.1">v2.0.1</option>
 	    <option class="other" value="MAX80 v">other...</option>
 	  </select>
-	  <input type="text" name="ver" id="ver" oninput="brt()" disabled />
+	  <input type="text" name="max80.hw.ver" id="ver"
+		 oninput="brt()" disabled />
 	</label>
 	<p id="warnrev" class="warnrev hidden">Be careful: the board
 	might fail to boot if the board revision is programmed

BIN
fpga/output/max80.fw


BIN
fpga/output/v1.fw


BIN
fpga/output/v2.fw