introduce new feature for the updater: UPDATECRC32
authorStephan Baerwolf <stephan.baerwolf@tu-ilmenau.de>
Fri, 14 Mar 2014 10:55:21 +0000 (11:55 +0100)
committerStephan Baerwolf <stephan.baerwolf@tu-ilmenau.de>
Sat, 15 Mar 2014 01:39:26 +0000 (01:39 +0000)
In the head of Makefile.inc you now can configure "UPDATECRC32"
to enable the updater to check integrity of the new firmware image.
The CRC32 of polynomial 0xEDB88320 is used. This CRC is the same,
the non-volatile-memory controller of ATxmega series is using.

Enabling this feature will only increase the update by a few
bytes (~180bytes) , but will offer more safety against bogus images.

By default the CRC is NOT used, but it can be enabled to a
fix value or calculated automatically during compile.

Signed-off-by: Stephan Baerwolf <stephan.baerwolf@tu-ilmenau.de>
Makefile.inc
updater/Makefile
updater/crccheck.c [new file with mode: 0644]
updater/updater.c

index dd9526a..34225c3 100644 (file)
@@ -11,6 +11,9 @@ DEVICE = atmega8
 # where the updating firmware should be located (starting address)
 FLASHADDRESS = 0x0000
 
 # where the updating firmware should be located (starting address)
 FLASHADDRESS = 0x0000
 
+# use any fix (ATxmega compatible) crc32, uncomment to disable feature or set automatically with value "0"
+;UPDATECRC32  = 0
+
 # some MCU independent defines...
 #...will be extended within MCU dependend configuration below...
 DEFINES += -DCONFIG_NO__CHIP_ERASE -DCONFIG_NO__ONDEMAND_PAGEERASE
 # some MCU independent defines...
 #...will be extended within MCU dependend configuration below...
 DEFINES += -DCONFIG_NO__CHIP_ERASE -DCONFIG_NO__ONDEMAND_PAGEERASE
index a1bc14d..db0cd8c 100644 (file)
@@ -57,7 +57,15 @@ usbasploader.o: usbasploader.raw $(DEPENDS)
 
 
 updater.o: updater.c usbasploader.h usbasploader.raw usbasploader.o $(DEPENDS)
 
 
 updater.o: updater.c usbasploader.h usbasploader.raw usbasploader.o $(DEPENDS)
+ifndef UPDATECRC32
        $(CC) updater.c -c -o updater.o -DSIZEOF_new_firmware=$(shell stat -c %s usbasploader.raw) $(CFLAGS)
        $(CC) updater.c -c -o updater.o -DSIZEOF_new_firmware=$(shell stat -c %s usbasploader.raw) $(CFLAGS)
+else
+ifeq ($(UPDATECRC32), 0)
+       $(CC) updater.c -c -o updater.o -DSIZEOF_new_firmware=$(shell stat -c %s usbasploader.raw) -DUPDATECRC32=0x$(shell crc32 usbasploader.raw) $(CFLAGS)
+else
+       $(CC) updater.c -c -o updater.o -DSIZEOF_new_firmware=$(shell stat -c %s usbasploader.raw) -DUPDATECRC32=$(UPDATECRC32) $(CFLAGS)
+endif
+endif
 #      $(CC) updater.c -c -o updater.o $(CFLAGS)
 
 updater.elf: updater.o usbasploader.o $(DEPENDS)
 #      $(CC) updater.c -c -o updater.o $(CFLAGS)
 
 updater.elf: updater.o usbasploader.o $(DEPENDS)
diff --git a/updater/crccheck.c b/updater/crccheck.c
new file mode 100644 (file)
index 0000000..798c37a
--- /dev/null
@@ -0,0 +1,36 @@
+/****************************************************************************/
+/* CRC32 stuff taken and adapted from lib_crc version 1.16 :                */
+/*   Library         : lib_crc                                              */
+/*   File            : lib_crc.c                                            */
+/*   Author          : Lammert Bies  1999-2008                              */
+/*   E-mail          : info@lammertbies.nl                                  */
+/****************************************************************************/
+
+/* the ATxmega series NVM CRC compatible polynom */
+/* on ATxmega you can do this much faster in hardware */
+#define                 P_32        0xEDB88320L
+#define                 D_32        0xFFFFFFFFL
+
+uint32_t crc_tab32_value(uint8_t address) {
+  uint32_t result;
+  uint8_t  j;
+
+  result = (uint32_t)address & 0xffL;
+  for (j=0; j<8; j++) {
+      if (result & 0x00000001L)        result = (result >> 1) ^ P_32;
+      else                     result = result >> 1;
+  }
+
+  return result;
+}
+
+uint32_t update_crc_32(uint32_t crc, uint8_t c) {
+  uint32_t tmp, long_c;
+
+  long_c = (uint32_t)c & 0xffL;
+
+  tmp = crc ^ long_c;
+  crc = (crc >> 8) ^ crc_tab32_value(tmp & 0xffL);
+
+  return crc;
+}
index f61b345..479df80 100644 (file)
@@ -271,15 +271,38 @@ size_t mypgm_WRITEpage(const mypgm_addr_t byteaddress,const void* buffer, const
 }
 #endif
 
 }
 #endif
 
+#if defined(UPDATECRC32)
+#include "crccheck.c"
+#endif
+
 // #pragma GCC diagnostic ignored "-Wno-pointer-to-int-cast"
 int main(void)
 {
 // #pragma GCC diagnostic ignored "-Wno-pointer-to-int-cast"
 int main(void)
 {
+#if defined(UPDATECRC32)
+    uint32_t crcval;
+#endif
     size_t  i;
     uint8_t buffer[SPM_PAGESIZE];
     
     wdt_disable();
     cli();
 
     size_t  i;
     uint8_t buffer[SPM_PAGESIZE];
     
     wdt_disable();
     cli();
 
+#if defined(UPDATECRC32)
+    // check if new firmware-image is corrupted
+    crcval = D_32;
+    for (i=0;i<SIZEOF_new_firmware;i+=1) {
+#if (FLASHEND > 65535)
+      crcval = update_crc_32(crcval, pgm_read_byte_far(FULLCORRECTFLASHADDRESS(&new_firmware[i])));
+#else
+      crcval = update_crc_32(crcval, pgm_read_byte(FULLCORRECTFLASHADDRESS(&new_firmware[i])));
+#endif
+    }
+    crcval ^= D_32;
+
+    // allow to change the firmware
+    if (crcval == ((uint32_t)UPDATECRC32)) {
+#endif
+
     // check if firmware would change...
     buffer[0]=0;
     for (i=0;i<SIZEOF_new_firmware;i+=2) {
     // check if firmware would change...
     buffer[0]=0;
     for (i=0;i<SIZEOF_new_firmware;i+=2) {
@@ -338,5 +361,9 @@ int main(void)
 
     }
 
 
     }
 
+#if defined(UPDATECRC32)
+    }
+#endif
+
     return 0;
 }
     return 0;
 }