test: Settings-Format längentolerant machen, ota_pending ergänzen

read_rec() akzeptiert jetzt Records mit hdr.length <= sizeof(nl_settings_t):
CRC wird nur über die tatsächlich geschriebenen Bytes geprüft, fehlende Felder
bleiben auf 0 (Default). Ein zu langer (unbekannter) Record wird weiter
abgelehnt. Ein durch massive Kürzung "leer" gelesener Record (fade_in_ms,
fade_out_ms und token allesamt 0) fällt komplett auf die Defaults zurück.
Neues Feld ota_pending (nach fade_out_ms) für den kommenden OTA-Ablauf.
This commit is contained in:
Michael Sauer
2026-09-12 00:55:20 +02:00
parent ed374fc490
commit 6e9fb09455
3 changed files with 81 additions and 4 deletions
+31 -4
View File
@@ -44,14 +44,35 @@ void nl_settings_init(uint32_t addr_a, uint32_t addr_b)
s_addr[1] = addr_b;
}
/* Reads a record and validates it. `r->data` is filled from the on-flash payload,
* zero-extended when an older/shorter layout is found (hdr.length < sizeof(nl_settings_t)):
* the CRC only covers the bytes actually written, so it is checked over the stored length,
* not over the current struct size. A record whose length exceeds the current struct
* (an unknown, newer layout) is rejected outright. */
static bool read_rec(int slot, rec_t *r)
{
if (nl_flash_read(s_addr[slot], r, sizeof *r) != 0)
rec_hdr_t hdr;
uint32_t crc, stored_crc;
if (nl_flash_read(s_addr[slot], &hdr, sizeof hdr) != 0)
return false;
if (r->hdr.magic != NL_SETTINGS_MAGIC || r->hdr.version != NL_SETTINGS_VERSION ||
r->hdr.length != sizeof(nl_settings_t))
if (hdr.magic != NL_SETTINGS_MAGIC || hdr.version != NL_SETTINGS_VERSION ||
hdr.length > sizeof(nl_settings_t))
return false;
return nl_crc32(0, r, offsetof(rec_t, crc)) == r->crc;
memset(r, 0, sizeof *r);
r->hdr = hdr;
if (nl_flash_read(s_addr[slot] + sizeof hdr, &r->data, hdr.length) != 0)
return false;
if (nl_flash_read(s_addr[slot] + sizeof hdr + hdr.length, &stored_crc, sizeof stored_crc) != 0)
return false;
crc = nl_crc32(0, &hdr, sizeof hdr);
crc = nl_crc32(crc, &r->data, hdr.length);
if (crc != stored_crc)
return false;
r->crc = stored_crc;
return true;
}
bool nl_settings_load(nl_settings_t *out)
@@ -71,6 +92,12 @@ bool nl_settings_load(nl_settings_t *out)
out->wifi_pass[NL_PASS_LEN - 1] = '\0';
out->token[NL_TOKEN_LEN - 1] = '\0';
out->name[NL_NAME_LEN - 1] = '\0';
/* A record so severely truncated that fade_in_ms/fade_out_ms/token all read back as
* zero carries no usable data; treat it as if nothing was stored at all. */
if (out->fade_in_ms == 0 && out->fade_out_ms == 0 && out->token[0] == '\0') {
nl_settings_defaults(out);
return false;
}
return true;
}
+1
View File
@@ -18,6 +18,7 @@ typedef struct {
uint8_t power_on_behaviour; /* nl_pob_t */
uint16_t fade_in_ms;
uint16_t fade_out_ms;
uint8_t ota_pending; /* set before an OTA; the next boot restores the last state */
} nl_settings_t;
void nl_settings_defaults(nl_settings_t *s);