fix: Fix-Runde 1 für Task 4 - Reset nur bei akzeptiertem OTA-Image, hängende Downloads/Sessions begrenzen

This commit is contained in:
Michael Sauer
2026-09-12 01:56:58 +02:00
parent aa8151c3d6
commit 37c05d2f90
7 changed files with 122 additions and 27 deletions
+3 -1
View File
@@ -165,7 +165,9 @@ static void app_task(void *arg)
have_last = nl_state_log_load(&last);
store_unlock();
if (s_settings.ota_pending) {
/* We came back from an update attempt: restore the light the user had on. */
/* We came back from an update attempt (accepted or rejected). Just clear the flag so it
* doesn't stick in flash forever; nl_boot_state() below restores the light from `last`/
* power_on_behaviour as on any other boot, no special-casing needed here. */
s_settings.ota_pending = 0;
printf("boot after ota attempt\r\n");
store_lock();
+7 -3
View File
@@ -336,9 +336,13 @@ static void handle_command(const nl_api_ctx_t *ctx, const nl_http_request_t *req
} else if (strcmp(type, "fw_update") == 0) {
if (get_string(cmd, "url", 8, 255, &url) != 1 || strncmp(url, "http://", 7) != 0)
reply_error(resp, 400, "invalid url");
else if (ctx->fw_update(url) != 0)
reply_error(resp, 501, "fw_update not available");
else
else if (ctx->fw_update(url) != 0) {
/* fw_update() itself can genuinely fail now (busy, or a rejected URL) - 409 with the
* reason, not a blanket "not implemented". */
nl_sys_info_t in;
ctx->get_info(&in);
reply_error(resp, 409, in.last_ota_error ? in.last_ota_error : "fw_update busy or invalid url");
} else
reply(resp, 202, "{\"status\":\"updating\"}");
} else if (strcmp(type, "reboot") == 0) {
reply(resp, 200, "{\"ok\":true}");
+29 -13
View File
@@ -34,22 +34,30 @@ void nl_ota_set_error(const char *e) { s_error = e; }
/* Called by the SDK firmware-update path once the image has been written and hashed.
sha256 covers the whole payload (T_BOOTER header + compressed image), tail is the
512 byte end block that used to carry the QConnex RSA signature. */
512 byte end block that used to carry the QConnex RSA signature.
NB: this runs on the SDK's own fwup_scheduler task (tls_fwup_init(), stack
FWUP_TASK_STK_SIZE*4, ~2 KB) - NOT on the 8 KB nl_ota task stack. Keep this hook minimal:
one short printf, no extra locals (a version buffer used to sit here and was removed). */
bool nl_fwup_verify_tail(const uint8_t sha256[32], const uint8_t *tail, uint32_t tail_len)
{
nl_trailer_err_t e = nl_trailer_verify(tail, tail_len, NINLIGHT_DEVICE_ID, sha256);
if (e != NL_TRAILER_OK) {
if (e != NL_TRAILER_OK)
s_error = nl_trailer_err_name(e);
printf("ota: trailer rejected (%s)\r\n", s_error);
return false;
}
{
char v[NL_TRAILER_VERSION_LEN];
nl_trailer_version(tail, v);
printf("ota: trailer ok, incoming version %s\r\n", v);
}
return true;
printf("ota: trailer %s\r\n", e == NL_TRAILER_OK ? "ok" : s_error);
return e == NL_TRAILER_OK;
}
/* Logs the URL without any "user:pass@" userinfo, so credentials embedded in the URL never
reach the console. s_url is validated by nl_ota_start() to start with "http://". */
static void log_url(const char *url)
{
const char *at = strchr(url + 7, '@');
if (at != NULL)
printf("ota: downloading http://%s\r\n", at + 1);
else
printf("ota: downloading %s\r\n", url);
}
static void ota_task(void *arg)
@@ -57,7 +65,7 @@ static void ota_task(void *arg)
int rc;
(void)arg;
printf("ota: downloading %s\r\n", s_url);
log_url(s_url);
rc = t_http_fwup(s_url);
/* Only reached on failure - the SDK resets the chip itself after a good image. */
if (s_error == NULL)
@@ -82,7 +90,7 @@ int nl_ota_start(const char *url)
if (url == NULL || strncmp(url, "http://", 7) != 0)
return -1;
n = strlen(url);
if (n == 0 || n >= sizeof s_url)
if (n <= 7 || n >= sizeof s_url) /* n == 7 is bare "http://" with no host */
return -1;
if (s_busy) {
s_error = "busy";
@@ -105,6 +113,14 @@ int nl_ota_start(const char *url)
if (tls_os_task_create(NULL, "nl_ota", ota_task, NULL, (u8 *)s_stack, sizeof(s_stack),
NL_OTA_PRIO, 0) != TLS_OS_SUCCESS) {
/* The task never ran, so clear the ota_pending flag we just persisted above - otherwise
* the next boot wrongly logs "boot after ota attempt" for an update that never started. */
nl_settings_t *s;
nl_app_lock();
s = nl_app_settings();
s->ota_pending = 0;
nl_app_unlock();
(void)nl_app_save_settings();
s_busy = false;
s_error = "busy";
return -1;