altos/lisp: Append a CRC to the saved image to validate on restore
authorKeith Packard <keithp@keithp.com>
Sat, 12 Nov 2016 07:34:54 +0000 (23:34 -0800)
committerKeith Packard <keithp@keithp.com>
Fri, 18 Nov 2016 06:18:39 +0000 (22:18 -0800)
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>
src/lambdakey-v1.0/ao_lisp_os_save.c [new file with mode: 0644]
src/lisp/ao_lisp.h
src/lisp/ao_lisp_make_const.c
src/lisp/ao_lisp_mem.c
src/lisp/ao_lisp_save.c
src/test/ao_lisp_test.c
src/test/hanoi.lisp

diff --git a/src/lambdakey-v1.0/ao_lisp_os_save.c b/src/lambdakey-v1.0/ao_lisp_os_save.c
new file mode 100644 (file)
index 0000000..4413839
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <ao.h>
+#include <ao_lisp.h>
+#include <ao_flash.h>
+
+extern uint8_t __flash__[];
+
+/* saved variables to rebuild the heap
+
+   ao_lisp_atoms
+   ao_lisp_frame_global
+ */
+
+int
+ao_lisp_os_save(void)
+{
+       int i;
+
+       for (i = 0; i < AO_LISP_POOL_TOTAL; i += 256) {
+               uint32_t        *dst = (uint32_t *) &__flash__[i];
+               uint32_t        *src = (uint32_t *) &ao_lisp_pool[i];
+
+               ao_flash_page(dst, src);
+       }
+       return 1;
+}
+
+int
+ao_lisp_os_restore_save(struct ao_lisp_os_save *save, int offset)
+{
+       memcpy(save, &__flash__[offset], sizeof (struct ao_lisp_os_save));
+       return 1;
+}
+
+int
+ao_lisp_os_restore(void)
+{
+       memcpy(ao_lisp_pool, __flash__, AO_LISP_POOL_TOTAL);
+       return 1;
+}
index 44838a3419b814c81450efe3aae78520a9f12bcf..ea3d2a0905f8d5e8e9deab93523404f3bd0ecb61 100644 (file)
@@ -26,15 +26,21 @@ 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);
 
@@ -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 */
index 0a8c9d0752ce6603a40695b56d68406416819077..6a29f402d263cfbe5e11ae478089cb8440c1b9ce 100644 (file)
@@ -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;
index 31ee9e1e339739ff4965b0469e13f8575727abe6..0373f0151448f87144b961a622c094799eae0f44 100644 (file)
@@ -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
index 2b19fdcba3520ba182b85799e1c1ea72d9e5cb6b..030846b7234b22197d0340512690cbede9282996 100644 (file)
 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();
index 41dae07aabf3d9155d331c63125d40e8961f245e..648d1abe061a021ef5cc4964c934d2bf08e923b1 100644 (file)
@@ -34,6 +34,24 @@ ao_lisp_os_save(void)
        return 1;
 }
 
+int
+ao_lisp_os_restore_save(struct ao_lisp_os_save *save, int offset)
+{
+       FILE    *restore = fopen(save_file, "r");
+       size_t  ret;
+
+       if (!restore) {
+               perror(save_file);
+               return 0;
+       }
+       fseek(restore, offset, SEEK_SET);
+       ret = fread(save, sizeof (struct ao_lisp_os_save), 1, restore);
+       fclose(restore);
+       if (ret != 1)
+               return 0;
+       return 1;
+}
+
 int
 ao_lisp_os_restore(void)
 {
index 01398d9121029dba270802d9362e687bb3e9c888..2b614829a8f85ec6ce3e844b022fccc76b4dd11e 100644 (file)
@@ -6,19 +6,11 @@
   (patom "\033[2J" nil)
   )
 
-(defun test ()
-  (clear)
-  (move-to 30 12)
-  (patom "hello, world")
-  (move-to 0 19)
-  )
-
 (setq stack '("*" "**" "***" "****" "*****" "******" "*******"))
 
 (setq stacks nil)
 
 (defun display-string (x y str)
-  (move-to x y)
   (move-to x y)
   (patom str)
   )