summaryrefslogtreecommitdiff
path: root/src/lisp
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2016-11-11 23:34:54 -0800
committerKeith Packard <keithp@keithp.com>2016-11-17 22:18:39 -0800
commitd70a79fece4077c263a5773c8849ec60c6b649bc (patch)
tree19bf3359194d276fdec1d5f3c8c1006f52bcd632 /src/lisp
parent6187afea14c2dbaae98b595963104c527a3a45c8 (diff)
altos/lisp: Append a CRC to the saved image to validate on restore
The CRC is actually of the ROM bits, so we can tell if the restored image relates to the currently running code. Signed-off-by: Keith Packard <keithp@keithp.com>
Diffstat (limited to 'src/lisp')
-rw-r--r--src/lisp/ao_lisp.h18
-rw-r--r--src/lisp/ao_lisp_make_const.c28
-rw-r--r--src/lisp/ao_lisp_mem.c2
-rw-r--r--src/lisp/ao_lisp_save.c27
4 files changed, 65 insertions, 10 deletions
diff --git a/src/lisp/ao_lisp.h b/src/lisp/ao_lisp.h
index 44838a34..ea3d2a09 100644
--- a/src/lisp/ao_lisp.h
+++ b/src/lisp/ao_lisp.h
@@ -26,16 +26,22 @@ typedef int16_t ao_signed_poly;
#ifdef AO_LISP_SAVE
struct ao_lisp_os_save {
- ao_poly ao_lisp_atoms;
- ao_poly ao_lisp_globals;
+ ao_poly atoms;
+ ao_poly globals;
+ uint16_t const_checksum;
+ uint16_t const_checksum_inv;
};
-#define AO_LISP_POOL (AO_LISP_POOL_TOTAL - sizeof (struct ao_lisp_os_save))
+#define AO_LISP_POOL_EXTRA (sizeof(struct ao_lisp_os_save))
+#define AO_LISP_POOL ((int) (AO_LISP_POOL_TOTAL - AO_LISP_POOL_EXTRA))
int
ao_lisp_os_save(void);
int
+ao_lisp_os_restore_save(struct ao_lisp_os_save *save, int offset);
+
+int
ao_lisp_os_restore(void);
#endif
@@ -67,12 +73,14 @@ extern uint8_t ao_lisp_const[AO_LISP_POOL_CONST];
#define _ao_lisp_atom_eval _atom("eval")
#define _ao_lisp_atom_read _atom("read")
#define _ao_lisp_atom_eof _atom("eof")
+#define _ao_lisp_atom_save _atom("save")
+#define _ao_lisp_atom_restore _atom("restore")
#else
#include "ao_lisp_const.h"
#ifndef AO_LISP_POOL
-#define AO_LISP_POOL 16384
+#define AO_LISP_POOL 3072
#endif
-extern uint8_t ao_lisp_pool[AO_LISP_POOL];
+extern uint8_t ao_lisp_pool[AO_LISP_POOL + AO_LISP_POOL_EXTRA];
#endif
/* Primitive types */
diff --git a/src/lisp/ao_lisp_make_const.c b/src/lisp/ao_lisp_make_const.c
index 0a8c9d07..6a29f402 100644
--- a/src/lisp/ao_lisp_make_const.c
+++ b/src/lisp/ao_lisp_make_const.c
@@ -86,6 +86,33 @@ is_atom(int offset)
return 0;
}
+#define AO_FEC_CRC_INIT 0xffff
+
+static inline uint16_t
+ao_fec_crc_byte(uint8_t byte, uint16_t crc)
+{
+ uint8_t bit;
+
+ for (bit = 0; bit < 8; bit++) {
+ if (((crc & 0x8000) >> 8) ^ (byte & 0x80))
+ crc = (crc << 1) ^ 0x8005;
+ else
+ crc = (crc << 1);
+ byte <<= 1;
+ }
+ return crc;
+}
+
+uint16_t
+ao_fec_crc(const uint8_t *bytes, uint8_t len)
+{
+ uint16_t crc = AO_FEC_CRC_INIT;
+
+ while (len--)
+ crc = ao_fec_crc_byte(*bytes++, crc);
+ return crc;
+}
+
int
main(int argc, char **argv)
{
@@ -126,6 +153,7 @@ main(int argc, char **argv)
printf("extern const uint8_t ao_lisp_const[AO_LISP_POOL_CONST] __attribute__((aligned(4)));\n");
printf("#define ao_builtin_atoms 0x%04x\n", ao_lisp_atom_poly(ao_lisp_atoms));
printf("#define ao_builtin_frame 0x%04x\n", ao_lisp_frame_poly(ao_lisp_frame_global));
+ printf("#define ao_lisp_const_checksum ((uint16_t) 0x%04x)\n", ao_fec_crc(ao_lisp_const, ao_lisp_top));
for (a = ao_lisp_atoms; a; a = ao_lisp_poly_atom(a->next)) {
char *n = a->name, c;
diff --git a/src/lisp/ao_lisp_mem.c b/src/lisp/ao_lisp_mem.c
index 31ee9e1e..0373f015 100644
--- a/src/lisp/ao_lisp_mem.c
+++ b/src/lisp/ao_lisp_mem.c
@@ -24,7 +24,7 @@ uint8_t ao_lisp_const[AO_LISP_POOL_CONST] __attribute__((aligned(4)));
#undef AO_LISP_POOL
#define AO_LISP_POOL AO_LISP_POOL_CONST
#else
-uint8_t ao_lisp_pool[AO_LISP_POOL] __attribute__((aligned(4)));
+uint8_t ao_lisp_pool[AO_LISP_POOL + AO_LISP_POOL_EXTRA] __attribute__((aligned(4)));
#endif
#if 0
diff --git a/src/lisp/ao_lisp_save.c b/src/lisp/ao_lisp_save.c
index 2b19fdcb..030846b7 100644
--- a/src/lisp/ao_lisp_save.c
+++ b/src/lisp/ao_lisp_save.c
@@ -17,12 +17,18 @@
ao_poly
ao_lisp_save(struct ao_lisp_cons *cons)
{
+ if (!ao_lisp_check_argc(_ao_lisp_atom_save, cons, 0, 0))
+ return AO_LISP_NIL;
+
#ifdef AO_LISP_SAVE
struct ao_lisp_os_save *os = (struct ao_lisp_os_save *) &ao_lisp_pool[AO_LISP_POOL];
ao_lisp_collect();
- os->ao_lisp_atoms = ao_lisp_atom_poly(ao_lisp_atoms);
- os->ao_lisp_globals = ao_lisp_frame_poly(ao_lisp_frame_global);
+ os->atoms = ao_lisp_atom_poly(ao_lisp_atoms);
+ os->globals = ao_lisp_frame_poly(ao_lisp_frame_global);
+ os->const_checksum = ao_lisp_const_checksum;
+ os->const_checksum_inv = ~ao_lisp_const_checksum;
+
if (ao_lisp_os_save())
return _ao_lisp_atom_t;
#endif
@@ -32,13 +38,26 @@ ao_lisp_save(struct ao_lisp_cons *cons)
ao_poly
ao_lisp_restore(struct ao_lisp_cons *cons)
{
+ if (!ao_lisp_check_argc(_ao_lisp_atom_save, cons, 0, 0))
+ return AO_LISP_NIL;
+
#ifdef AO_LISP_SAVE
+ struct ao_lisp_os_save save;
struct ao_lisp_os_save *os = (struct ao_lisp_os_save *) &ao_lisp_pool[AO_LISP_POOL];
+ if (!ao_lisp_os_restore_save(&save, AO_LISP_POOL))
+ return ao_lisp_error(AO_LISP_INVALID, "header restore failed");
+
+ if (save.const_checksum != ao_lisp_const_checksum ||
+ save.const_checksum_inv != (uint16_t) ~ao_lisp_const_checksum)
+ {
+ return ao_lisp_error(AO_LISP_INVALID, "image is corrupted or stale");
+ }
+
if (ao_lisp_os_restore()) {
- ao_lisp_atoms = ao_lisp_poly_atom(os->ao_lisp_atoms);
- ao_lisp_frame_global = ao_lisp_poly_frame(os->ao_lisp_globals);
+ ao_lisp_atoms = ao_lisp_poly_atom(os->atoms);
+ ao_lisp_frame_global = ao_lisp_poly_frame(os->globals);
/* Clear the eval global variabls */
ao_lisp_eval_clear_globals();