+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+/* EEPROM data size, not including checksum */
+#define EEP_DATA_SIZE 494
+/* FIXME: actually we should either find a way to include the declaration of
+ struct storage_t here or at least make this a command line parameter */
+
+/* code from http://www.nongnu.org/avr-libc/user-manual/group__util__crc.html */
+uint16_t crc16_update(uint16_t crc, uint8_t a)
+{
+ int i;
+
+ crc ^= a;
+ for (i = 0; i < 8; ++i)
+ {
+ if (crc & 1)
+ crc = (crc >> 1) ^ 0xA001;
+ else
+ crc = (crc >> 1);
+ }
+
+ return crc;
+}
+
+/* oh, this is soooo ugly... :-( */
+int main(int argc, char ** argv)
+{
+ int i, c, id;
+ uint16_t checksum = 0;
+
+ if ((argc < 2) || ((id = atoi(argv[1])) > 15) || (id <= 0))
+ {
+ fputs("usage: patcheeprom id < eeprom-template > eeprom-binary\n\n", stderr);
+ return 127;
+ }
+ /* print out magic byte and add it to checksum */
+ putchar(0x23);
+ checksum = crc16_update(checksum, 0x23);
+
+ /* print out id and add it to checksum */
+ putchar(id);
+ checksum = crc16_update(checksum, id);
+
+ /* ignore first two bytes of input */
+ getchar();
+ getchar();
+
+ /* now copy template and adapt checksum */
+ for (i = 2; i < EEP_DATA_SIZE; i++) {
+
+ if ((c = getchar()) == EOF) {
+ return 1;
+ }
+
+ checksum = crc16_update(checksum, c);
+
+ if (putchar(c) == EOF) {
+ return 2;
+ }
+ }
+ /* print out checksum, and we're done */
+ putchar(checksum & 0xff);
+ putchar(checksum >> 8);
+
+ return 0;
+}
+