mirror of
git://projects.qi-hardware.com/antorcha.git
synced 2024-11-22 07:36:17 +02:00
fw/: addition of boot loader (WIP) and assorted cleanup and improvements
The boot loader currently uses the protocol switch intended for the application. This makes it too big to fit in the very limiting constraints the ATmega168 poses - and there's not even cryptographic authentication yet. We'll have to dumb it down quite a bit.
This commit is contained in:
parent
df6ceb8394
commit
56476539cf
4
NOTES
4
NOTES
@ -90,6 +90,6 @@ electrical, LEDs:
|
|||||||
even less demanding
|
even less demanding
|
||||||
|
|
||||||
authentication:
|
authentication:
|
||||||
- shared secret (128 bit, MD5-hashed text with 128 bit salt)
|
- shared secret (128 bit, SHA1-hashed text with 128 bit salt)
|
||||||
- salt (128 bit)
|
- salt (128 bit)
|
||||||
- MD5
|
- SHA1 from avrcryptolib
|
||||||
|
67
fw/Makefile
67
fw/Makefile
@ -1,8 +1,8 @@
|
|||||||
#
|
#
|
||||||
# Makefile - Makefile of the ATUSB firmware
|
# Makefile - Makefile of the Antorcha firmware
|
||||||
#
|
#
|
||||||
# Written 2010-2011 by Werner Almesberger
|
# Written 2012 by Werner Almesberger
|
||||||
# Copyright 2010-2011 by Werner Almesberger
|
# Copyright 2012 by Werner Almesberger
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
@ -14,13 +14,16 @@ SHELL = /bin/bash
|
|||||||
|
|
||||||
NAME = antorcha
|
NAME = antorcha
|
||||||
|
|
||||||
CFLAGS = -g -mmcu=$(CHIP) -DBOOT_ADDR=$(BOOT_ADDR) \
|
CFLAGS = -g -mmcu=$(CHIP) \
|
||||||
|
-DBOOT_ADDR=$(BOOT_ADDR) -DAPP_ADDR=$(APP_ADDR) -DAPP_END=$(APP_END) \
|
||||||
-Wall -Wextra -Wshadow -Werror -Wno-unused-parameter \
|
-Wall -Wextra -Wshadow -Werror -Wno-unused-parameter \
|
||||||
-Wmissing-prototypes -Wmissing-declarations -Wstrict-prototypes
|
-Wmissing-prototypes -Wmissing-declarations -Wstrict-prototypes
|
||||||
|
|
||||||
CHIP=atmega168
|
CHIP = atmega168
|
||||||
HOST=jlime
|
HOST = jlime
|
||||||
BOOT_ADDR=0x7000
|
BOOT_ADDR = 0
|
||||||
|
APP_ADDR = 0x1000
|
||||||
|
APP_END = 0x4000
|
||||||
|
|
||||||
AVR_PREFIX = $(BIN_PATH) avr-
|
AVR_PREFIX = $(BIN_PATH) avr-
|
||||||
CC = $(AVR_PREFIX)gcc
|
CC = $(AVR_PREFIX)gcc
|
||||||
@ -28,11 +31,9 @@ OBJCOPY = $(AVR_PREFIX)objcopy
|
|||||||
#OBJDUMP = $(AVR_PREFIX)objdump
|
#OBJDUMP = $(AVR_PREFIX)objdump
|
||||||
SIZE = $(AVR_PREFIX)size
|
SIZE = $(AVR_PREFIX)size
|
||||||
|
|
||||||
USB_ID = 20b7:1540
|
OBJS = $(NAME).o $(COMMON_OBJS)
|
||||||
|
BOOT_OBJS = boot.o flash.o fw.o $(COMMON_OBJS)
|
||||||
OBJS = $(NAME).o rf.o spi.o
|
COMMON_OBJS = dispatch.o hash.o rf.o spi.o
|
||||||
|
|
||||||
CFLAGS += -Iinclude
|
|
||||||
|
|
||||||
# ----- Verbosity control -----------------------------------------------------
|
# ----- Verbosity control -----------------------------------------------------
|
||||||
|
|
||||||
@ -56,18 +57,19 @@ endif
|
|||||||
|
|
||||||
# ----- Rules -----------------------------------------------------------------
|
# ----- Rules -----------------------------------------------------------------
|
||||||
|
|
||||||
.PHONY: all clean upload prog update version.c bindist
|
.PHONY: all clean upload prog update version.c
|
||||||
.PHONY: prog-app prog-read on off reset
|
.PHONY: prog-app prog-read on off reset
|
||||||
|
|
||||||
all: $(NAME).bin
|
all: $(NAME).bin boot.bin
|
||||||
|
|
||||||
$(NAME).elf: $(OBJS)
|
$(NAME).elf: $(OBJS)
|
||||||
$(MAKE) version.o
|
$(MAKE) version.o
|
||||||
$(CC) $(CFLAGS) -o $@ $(OBJS) version.o
|
$(CC) $(CFLAGS) -o $@ $(OBJS) version.o \
|
||||||
|
-Wl,--section-start=.text=$(APP_ADDR)
|
||||||
|
|
||||||
#boot.elf: $(BOOT_OBJS)
|
boot.elf: $(BOOT_OBJS)
|
||||||
# $(CC) $(CFLAGS) -o $@ $(BOOT_OBJS) \
|
$(CC) $(CFLAGS) -o $@ $(BOOT_OBJS) \
|
||||||
# -Wl,--section-start=.text=$(BOOT_ADDR)
|
-Wl,--section-start=.text=$(BOOT_ADDR)
|
||||||
|
|
||||||
%.bin: %.elf
|
%.bin: %.elf
|
||||||
$(BUILD) $(OBJCOPY) -j .text -j .data -O binary $< $@
|
$(BUILD) $(OBJCOPY) -j .text -j .data -O binary $< $@
|
||||||
@ -120,25 +122,10 @@ MKDEP = \
|
|||||||
|
|
||||||
-include $(OBJS:.o=.d)
|
-include $(OBJS:.o=.d)
|
||||||
|
|
||||||
# ----- Distribution ----------------------------------------------------------
|
|
||||||
|
|
||||||
BINDIST_BASE=http://downloads.qi-hardware.com/people/werner/wpan/bindist
|
|
||||||
ATUSB_BIN_NAME=atusb-`git rev-parse HEAD | cut -c 1-7`.bin
|
|
||||||
|
|
||||||
bindist:
|
|
||||||
qippl atusb.bin wpan/bindist/$(ATUSB_BIN_NAME)
|
|
||||||
@echo $(BINDIST_BASE)/$(ATUSB_BIN_NAME)
|
|
||||||
@echo md5sum: `md5sum atusb.bin | sed 's/ .*//'`
|
|
||||||
@echo atrf-id: \
|
|
||||||
`sed '/.*number = \(.*\);/s//#\1/p;d' version.c` \
|
|
||||||
`sed '/.*date = "\(.*\)";/s//\1/p;d' version.c`
|
|
||||||
|
|
||||||
# ----- Programming and device control ----------------------------------------
|
# ----- Programming and device control ----------------------------------------
|
||||||
|
|
||||||
#upload: $(NAME).bin boot.hex
|
upload: $(NAME).bin boot.hex
|
||||||
# scp $(NAME).bin boot.hex $(HOST):
|
scp $(NAME).bin boot.hex $(HOST):
|
||||||
upload: $(NAME).bin
|
|
||||||
scp $(NAME).bin $(HOST):
|
|
||||||
|
|
||||||
# lfuse: external clock, slow start-up
|
# lfuse: external clock, slow start-up
|
||||||
# hfuse: 4 kB boot loader, reset into boot loader
|
# hfuse: 4 kB boot loader, reset into boot loader
|
||||||
@ -146,20 +133,20 @@ upload: $(NAME).bin
|
|||||||
# Note: when trying to program 0xef, we get back 0x2f, failing
|
# Note: when trying to program 0xef, we get back 0x2f, failing
|
||||||
# verification. So we just program 0x2f.
|
# verification. So we just program 0x2f.
|
||||||
|
|
||||||
prog:
|
prog-app:
|
||||||
ssh $(HOST) avrdude -F -p $(CHIP) -c nanonote_antorcha -e \
|
ssh $(HOST) avrdude -F -p $(CHIP) -c nanonote_antorcha -e \
|
||||||
-U flash:w:antorcha.bin:r
|
-U flash:w:antorcha.bin:r
|
||||||
# -U lfuse:w:0x60:m
|
# -U lfuse:w:0x60:m
|
||||||
|
|
||||||
#prog:
|
prog:
|
||||||
# ssh $(HOST) avrdude -F -p $(CHIP) -c nanonote_atusb -e \
|
ssh $(HOST) avrdude -F -p $(CHIP) -c nanonote_antorcha -e \
|
||||||
# -U flash:w:boot.hex:i \
|
-U flash:w:boot.hex:i
|
||||||
# -U lfuse:w:0x60:m \
|
# -U lfuse:w:0x60:m \
|
||||||
# -U hfuse:w:0xd8:m \
|
# -U hfuse:w:0xd8:m \
|
||||||
# -U lock:w:0x2f:m
|
# -U lock:w:0x2f:m
|
||||||
|
|
||||||
prog-read:
|
prog-read:
|
||||||
ssh $(HOST) avrdude -F -p $(CHIP) -c nanonote_atusb \
|
ssh $(HOST) avrdude -F -p $(CHIP) -c nanonote_antorcha \
|
||||||
-U flash:r:mcu.bin:r
|
-U flash:r:mcu.bin:r
|
||||||
|
|
||||||
on:
|
on:
|
||||||
|
81
fw/boot.c
Normal file
81
fw/boot.c
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* fw/boot.c - Antorcha boot loader
|
||||||
|
*
|
||||||
|
* Written 2012 by Werner Almesberger
|
||||||
|
* Copyright 2012 Werner Almesberger
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
|
||||||
|
#include "io.h"
|
||||||
|
#include "rf.h"
|
||||||
|
#include "proto.h"
|
||||||
|
#include "dispatch.h"
|
||||||
|
#include "fw.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define MS_TO_LOOP(ms) ((uint32_t) (ms)*335)
|
||||||
|
|
||||||
|
|
||||||
|
static void wait_upload(void)
|
||||||
|
{
|
||||||
|
uint8_t buf[PAYLOAD+5];
|
||||||
|
uint32_t i;
|
||||||
|
uint8_t got;
|
||||||
|
|
||||||
|
restart:
|
||||||
|
for (i = 0; i != MS_TO_LOOP(2000); i++) {
|
||||||
|
got = rf_recv(buf, sizeof(buf));
|
||||||
|
if (got && dispatch(buf, got, fw_protos))
|
||||||
|
goto restart;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
volatile int zero = 0;
|
||||||
|
|
||||||
|
/* Port B has two LEDs and the rest is SPI */
|
||||||
|
PORTB = MASK(B, RF_nSS) | MASK(B, RF_nRST);
|
||||||
|
DDRB = MASK(B, RF_SCLK) | MASK(B, RF_MOSI) | MASK(B, RF_nSS) |
|
||||||
|
MASK(B, RF_nRST) | 0xc0;
|
||||||
|
|
||||||
|
/* All port C pins drive LEDs */
|
||||||
|
PORTC = 0;
|
||||||
|
DDRC = 0x3f;
|
||||||
|
|
||||||
|
/* All port D pins drive LEDs */
|
||||||
|
PORTD = 0;
|
||||||
|
DDRD = 0xff;
|
||||||
|
|
||||||
|
/* disable pull-ups */
|
||||||
|
MCUCR |= 1 << PUD;
|
||||||
|
|
||||||
|
rf_init();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Switch the LED inside the loop so that we get a short pulse one can
|
||||||
|
* observe on a scope.
|
||||||
|
*/
|
||||||
|
do {
|
||||||
|
SET(LED_B8);
|
||||||
|
wait_upload();
|
||||||
|
CLR(LED_B8);
|
||||||
|
while (1);
|
||||||
|
} while (pgm_read_byte(zero) != 0xff);
|
||||||
|
|
||||||
|
|
||||||
|
((void (*)(void)) 0)();
|
||||||
|
|
||||||
|
/* not reached */
|
||||||
|
return 0;
|
||||||
|
}
|
104
fw/dispatch.c
Normal file
104
fw/dispatch.c
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
* fw/dispatch.c - Wireless protocol dispatcher
|
||||||
|
*
|
||||||
|
* Written 2012 by Werner Almesberger
|
||||||
|
* Copyright 2012 Werner Almesberger
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define F_CPU 8000000UL
|
||||||
|
#include <util/delay.h>
|
||||||
|
|
||||||
|
#include "rf.h"
|
||||||
|
#include "proto.h"
|
||||||
|
#include "dispatch.h"
|
||||||
|
#include "io.h"
|
||||||
|
|
||||||
|
|
||||||
|
static uint8_t seq; /* last sequence number seen */
|
||||||
|
static uint8_t type; /* type currently being processed */
|
||||||
|
static uint8_t limit; /* last limit seen */
|
||||||
|
static const struct handler *curr_proto = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
static void send_ack(const uint8_t *buf)
|
||||||
|
{
|
||||||
|
uint8_t ack[3] = { buf[0]+1, buf[1], 0 };
|
||||||
|
|
||||||
|
SET(LED_B6);
|
||||||
|
_delay_ms(1);
|
||||||
|
rf_send(ack, sizeof(ack));
|
||||||
|
CLR(LED_B6);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool answer_ping(const uint8_t *buf)
|
||||||
|
{
|
||||||
|
uint8_t pong[] = { PONG, 0, 0 };
|
||||||
|
|
||||||
|
if (buf[1])
|
||||||
|
return 0;
|
||||||
|
rf_send(pong, sizeof(pong));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool dispatch(const uint8_t *buf, uint8_t len, const struct handler **protos)
|
||||||
|
{
|
||||||
|
SET(LED_B7);
|
||||||
|
CLR(LED_B7);
|
||||||
|
if (len == 3 && buf[0] == PING)
|
||||||
|
return answer_ping(buf);
|
||||||
|
|
||||||
|
if (len != 64+3)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!buf[1]) {
|
||||||
|
while (*protos) {
|
||||||
|
if ((*protos)->type == buf[0])
|
||||||
|
break;
|
||||||
|
protos++;
|
||||||
|
}
|
||||||
|
if (!*protos)
|
||||||
|
return 0;
|
||||||
|
if (!(*protos)->first(buf+3))
|
||||||
|
return 0;
|
||||||
|
curr_proto = *protos;
|
||||||
|
type = buf[0];
|
||||||
|
seq = 0;
|
||||||
|
limit = buf[2];
|
||||||
|
send_ack(buf);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!curr_proto)
|
||||||
|
return 0;
|
||||||
|
if (buf[0] != type)
|
||||||
|
return 0;
|
||||||
|
if (buf[1] > limit)
|
||||||
|
return 0;
|
||||||
|
if (buf[2] != limit)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (buf[1] == seq) {
|
||||||
|
send_ack(buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (buf[1] != seq+1)
|
||||||
|
return 0;
|
||||||
|
if (!curr_proto->more(buf[1], limit, buf+3))
|
||||||
|
return 0;
|
||||||
|
seq++;
|
||||||
|
send_ack(buf);
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
}
|
29
fw/dispatch.h
Normal file
29
fw/dispatch.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* fw/dispatch.h - Wireless protocol dispatcher
|
||||||
|
*
|
||||||
|
* Written 2012 by Werner Almesberger
|
||||||
|
* Copyright 2012 Werner Almesberger
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DISPATCH_H
|
||||||
|
#define DISPATCH_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct handler {
|
||||||
|
enum pck_type type;
|
||||||
|
bool (*first)(const uint8_t *payload);
|
||||||
|
bool (*more)(uint8_t seq, uint8_t limit, const uint8_t *payload);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
bool dispatch(const uint8_t *buf, uint8_t len, const struct handler **protos);
|
||||||
|
|
||||||
|
#endif /* !PROTO_H */
|
73
fw/flash.c
Normal file
73
fw/flash.c
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* fw/flash.c - Flash interface
|
||||||
|
*
|
||||||
|
* Written 2011, 2012 by Werner Almesberger
|
||||||
|
* Copyright 2011, 2012 Werner Almesberger
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Adapted from ben-wpan/atusb/fw/flash.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <avr/boot.h>
|
||||||
|
//#include <avr/pgmspace.h>
|
||||||
|
|
||||||
|
#include "flash.h"
|
||||||
|
|
||||||
|
|
||||||
|
static uint32_t payload;
|
||||||
|
|
||||||
|
|
||||||
|
void flash_start(uint32_t addr)
|
||||||
|
{
|
||||||
|
payload = addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int flash_can_write(uint16_t size)
|
||||||
|
{
|
||||||
|
return payload <= APP_END-size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void flash_write(const uint8_t *buf, uint16_t size)
|
||||||
|
{
|
||||||
|
static uint8_t last;
|
||||||
|
const uint8_t *p;
|
||||||
|
|
||||||
|
for (p = buf; p != buf+size; p++) {
|
||||||
|
if (!(payload & (SPM_PAGESIZE-1))) {
|
||||||
|
boot_page_erase(payload);
|
||||||
|
boot_spm_busy_wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payload & 1)
|
||||||
|
boot_page_fill(payload, last | (*p << 8));
|
||||||
|
else
|
||||||
|
last = *p;
|
||||||
|
payload++;
|
||||||
|
|
||||||
|
if (!(payload & (SPM_PAGESIZE-1))) {
|
||||||
|
boot_page_write(payload-SPM_PAGESIZE);
|
||||||
|
boot_spm_busy_wait();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void flash_end_write(void)
|
||||||
|
{
|
||||||
|
if (payload & (SPM_PAGESIZE-1)) {
|
||||||
|
boot_page_write(payload & ~(SPM_PAGESIZE-1));
|
||||||
|
boot_spm_busy_wait();
|
||||||
|
}
|
||||||
|
boot_rww_enable();
|
||||||
|
}
|
24
fw/flash.h
Normal file
24
fw/flash.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* fw/flash.h - Flash interface
|
||||||
|
*
|
||||||
|
* Written 2012 by Werner Almesberger
|
||||||
|
* Copyright 2012 Werner Almesberger
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FLASH_H
|
||||||
|
#define FLASH_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
void flash_start(uint32_t addr);
|
||||||
|
int flash_can_write(uint16_t size);
|
||||||
|
void flash_write(const uint8_t *buf, uint16_t size);
|
||||||
|
void flash_end_write(void);
|
||||||
|
|
||||||
|
#endif /* !FLASH_H */
|
133
fw/fw.c
Normal file
133
fw/fw.c
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
/*
|
||||||
|
* fw/fw.h - Firmware upload protocols
|
||||||
|
*
|
||||||
|
* Written 2012 by Werner Almesberger
|
||||||
|
* Copyright 2012 Werner Almesberger
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "hash.h"
|
||||||
|
#include "flash.h"
|
||||||
|
#include "proto.h"
|
||||||
|
#include "dispatch.h"
|
||||||
|
#include "fw.h"
|
||||||
|
|
||||||
|
|
||||||
|
static const uint8_t unlock_secret[] = {
|
||||||
|
#include "unlock-secret.inc"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void panic(void)
|
||||||
|
{
|
||||||
|
/* ??? */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ----- Unlocking --------------------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
static bool unlocked = 0;
|
||||||
|
static bool unlock_failed;
|
||||||
|
|
||||||
|
|
||||||
|
static bool unlock_first(const uint8_t *payload)
|
||||||
|
{
|
||||||
|
hash_init();
|
||||||
|
hash_merge(unlock_secret, sizeof(unlock_secret));
|
||||||
|
hash_merge(payload, PAYLOAD);
|
||||||
|
unlocked = 0;
|
||||||
|
unlock_failed = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool unlock_more(uint8_t seq, uint8_t limit, const uint8_t *payload)
|
||||||
|
{
|
||||||
|
switch (seq) {
|
||||||
|
case 1:
|
||||||
|
hash_merge(payload, PAYLOAD);
|
||||||
|
hash_end();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (!hash_eq(payload, PAYLOAD, 0))
|
||||||
|
unlock_failed = 1;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if (unlock_failed)
|
||||||
|
return 1;
|
||||||
|
if (hash_eq(payload, PAYLOAD, PAYLOAD))
|
||||||
|
unlocked = 1;
|
||||||
|
else
|
||||||
|
unlock_failed = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const struct handler unlock_proto = {
|
||||||
|
.type = UNLOCK,
|
||||||
|
.first = unlock_first,
|
||||||
|
.more = unlock_more,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* ----- Firmware upload --------------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
static bool fw_first(const uint8_t *payload)
|
||||||
|
{
|
||||||
|
// if (!unlocked)
|
||||||
|
// return 0;
|
||||||
|
hash_init();
|
||||||
|
hash_merge(payload, PAYLOAD);
|
||||||
|
flash_start(APP_ADDR);
|
||||||
|
flash_write(payload, PAYLOAD);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool fw_more(uint8_t seq, uint8_t limit, const uint8_t *payload)
|
||||||
|
{
|
||||||
|
if (!flash_can_write(PAYLOAD))
|
||||||
|
return 0;
|
||||||
|
if (seq != limit) {
|
||||||
|
hash_merge(payload, PAYLOAD);
|
||||||
|
flash_write(payload, PAYLOAD);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
flash_end_write();
|
||||||
|
hash_end();
|
||||||
|
if (!hash_eq(payload, PAYLOAD, 0))
|
||||||
|
panic();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const struct handler fw_proto = {
|
||||||
|
.type = FIRMWARE,
|
||||||
|
.first = fw_first,
|
||||||
|
.more = fw_more,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* ----- Protocol table ---------------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
const struct handler *fw_protos[] = {
|
||||||
|
&unlock_proto,
|
||||||
|
&fw_proto,
|
||||||
|
NULL
|
||||||
|
};
|
21
fw/fw.h
Normal file
21
fw/fw.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* fw/fw.h - Firmware upload protocols
|
||||||
|
*
|
||||||
|
* Written 2012 by Werner Almesberger
|
||||||
|
* Copyright 2012 Werner Almesberger
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FW_H
|
||||||
|
#define FW_H
|
||||||
|
|
||||||
|
#include "proto.h"
|
||||||
|
|
||||||
|
|
||||||
|
extern const struct handler *fw_protos[];
|
||||||
|
|
||||||
|
#endif /* !FW_H */
|
61
fw/hash.c
Normal file
61
fw/hash.c
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* fw/hash.h - Secure hash
|
||||||
|
*
|
||||||
|
* Written 2012 by Werner Almesberger
|
||||||
|
* Copyright 2012 Werner Almesberger
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "hash.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define HASH_SIZE 128
|
||||||
|
|
||||||
|
|
||||||
|
static uint8_t hash[HASH_SIZE];
|
||||||
|
|
||||||
|
|
||||||
|
void hash_init(void)
|
||||||
|
{
|
||||||
|
memset(hash, 0, HASH_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void hash_merge(const uint8_t *buf, uint8_t len)
|
||||||
|
{
|
||||||
|
uint8_t i;
|
||||||
|
|
||||||
|
for (i = 0; i != len; i++)
|
||||||
|
hash[i & (HASH_SIZE-1)] ^= buf[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void hash_end(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool hash_eq(const uint8_t *buf, uint8_t len, uint8_t off)
|
||||||
|
{
|
||||||
|
uint8_t i;
|
||||||
|
|
||||||
|
for (i = 0; i != len; i++)
|
||||||
|
if (hash[(off+i) & (HASH_SIZE-1)] != buf[i])
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void hash_cp(uint8_t *buf, uint8_t len, uint8_t off)
|
||||||
|
{
|
||||||
|
memcpy(buf, hash+off, len);
|
||||||
|
}
|
26
fw/hash.h
Normal file
26
fw/hash.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* fw/hash.h - Secure hash
|
||||||
|
*
|
||||||
|
* Written 2012 by Werner Almesberger
|
||||||
|
* Copyright 2012 Werner Almesberger
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HASH_H
|
||||||
|
#define HASH_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
void hash_init(void);
|
||||||
|
void hash_merge(const uint8_t *buf, uint8_t len);
|
||||||
|
void hash_end(void);
|
||||||
|
bool hash_eq(const uint8_t *buf, uint8_t len, uint8_t off);
|
||||||
|
void hash_cp(uint8_t *buf, uint8_t len, uint8_t off);
|
||||||
|
|
||||||
|
#endif /* !HASH_H */
|
5
fw/io.h
5
fw/io.h
@ -13,6 +13,11 @@
|
|||||||
#ifndef IO_H
|
#ifndef IO_H
|
||||||
#define IO_H
|
#define IO_H
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define LED_B6 D, 5
|
||||||
|
#define LED_B7 D, 6
|
||||||
#define LED_B8 D, 7
|
#define LED_B8 D, 7
|
||||||
|
|
||||||
#define RF_SCLK B, 5
|
#define RF_SCLK B, 5
|
||||||
|
31
fw/proto.h
Normal file
31
fw/proto.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* fw/proto.h - Wireless protocol constants
|
||||||
|
*
|
||||||
|
* Written 2012 by Werner Almesberger
|
||||||
|
* Copyright 2012 Werner Almesberger
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PROTO_H
|
||||||
|
#define PROTO_H
|
||||||
|
|
||||||
|
#define PAYLOAD 64 /* most messages use a fixed 64 bytes payload */
|
||||||
|
|
||||||
|
enum pck_type {
|
||||||
|
PING = 0, /* version query */
|
||||||
|
PONG = 1, /* version response */
|
||||||
|
UNLOCK = 2, /* unlock firmware upload */
|
||||||
|
UNLOCK_ACK = 3, /* unlock acknowledgement */
|
||||||
|
FIRMWARE = 4, /* firmware upload */
|
||||||
|
FIRMWARE_ACK = 5, /* firmware upload acknowledgement */
|
||||||
|
IMAGE = 6, /* image upload */
|
||||||
|
IMAGE_ACK = 7, /* image upload acknowledgement */
|
||||||
|
PARAM = 8, /* parameter upload */
|
||||||
|
PARAM_ACK = 9, /* parameter upload acknowledgement */
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* !PROTO_H */
|
21
fw/rf.c
21
fw/rf.c
@ -44,8 +44,8 @@ static uint8_t reg_read(uint8_t reg)
|
|||||||
uint8_t value;
|
uint8_t value;
|
||||||
|
|
||||||
spi_begin();
|
spi_begin();
|
||||||
spi_io(AT86RF230_REG_READ | reg);
|
spi_send(AT86RF230_REG_READ | reg);
|
||||||
value = spi_io(0);
|
value = spi_recv();
|
||||||
spi_end();
|
spi_end();
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
@ -55,11 +55,12 @@ static uint8_t reg_read(uint8_t reg)
|
|||||||
static void reg_write(uint8_t reg, uint8_t value)
|
static void reg_write(uint8_t reg, uint8_t value)
|
||||||
{
|
{
|
||||||
spi_begin();
|
spi_begin();
|
||||||
spi_io(AT86RF230_REG_WRITE | reg);
|
spi_send(AT86RF230_REG_WRITE | reg);
|
||||||
spi_io(value);
|
spi_send(value);
|
||||||
spi_end();
|
spi_end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void rf_init(void)
|
void rf_init(void)
|
||||||
{
|
{
|
||||||
spi_init();
|
spi_init();
|
||||||
@ -89,10 +90,10 @@ void rf_send(const void *buf, uint8_t size)
|
|||||||
_delay_us(1); /* tTR9 = 1 us */
|
_delay_us(1); /* tTR9 = 1 us */
|
||||||
|
|
||||||
spi_begin();
|
spi_begin();
|
||||||
spi_io(AT86RF230_BUF_WRITE);
|
spi_send(AT86RF230_BUF_WRITE);
|
||||||
spi_io(size+2); /* CRC */
|
spi_send(size+2); /* CRC */
|
||||||
for (i = 0; i != size; i++)
|
for (i = 0; i != size; i++)
|
||||||
spi_io(((const uint8_t *) buf)[i]);
|
spi_send(((const uint8_t *) buf)[i]);
|
||||||
spi_end();
|
spi_end();
|
||||||
|
|
||||||
reg_read(REG_IRQ_STATUS);
|
reg_read(REG_IRQ_STATUS);
|
||||||
@ -122,8 +123,8 @@ uint8_t rf_recv(void *buf, uint8_t size)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
spi_begin();
|
spi_begin();
|
||||||
spi_io(AT86RF230_BUF_READ);
|
spi_send(AT86RF230_BUF_READ);
|
||||||
len = spi_io(0);
|
len = spi_recv();
|
||||||
if (!len || (len & 0x80)) {
|
if (!len || (len & 0x80)) {
|
||||||
spi_end();
|
spi_end();
|
||||||
return 0;
|
return 0;
|
||||||
@ -131,7 +132,7 @@ uint8_t rf_recv(void *buf, uint8_t size)
|
|||||||
if (size > len)
|
if (size > len)
|
||||||
size = len;
|
size = len;
|
||||||
for (i = 0; i != size; i++)
|
for (i = 0; i != size; i++)
|
||||||
((uint8_t *) buf)[i] = spi_io(0);
|
((uint8_t *) buf)[i] = spi_recv();
|
||||||
spi_end();
|
spi_end();
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
22
fw/spi.h
22
fw/spi.h
@ -21,4 +21,26 @@ void spi_begin(void);
|
|||||||
uint8_t spi_io(uint8_t v);
|
uint8_t spi_io(uint8_t v);
|
||||||
void spi_end(void);
|
void spi_end(void);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Interestingly, the #defines below produce slightly shorter code (6 bytes)
|
||||||
|
* than the inlines.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static inline void spi_send(uint8_t v)
|
||||||
|
{
|
||||||
|
spi_io(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline uint8_t spi_recv(void)
|
||||||
|
{
|
||||||
|
return spi_io(0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define spi_send(v) spi_io(v)
|
||||||
|
#define spi_recv() spi_io(0)
|
||||||
|
|
||||||
#endif /* !SPI_H */
|
#endif /* !SPI_H */
|
||||||
|
1
fw/unlock-secret.inc
Normal file
1
fw/unlock-secret.inc
Normal file
@ -0,0 +1 @@
|
|||||||
|
1, 2, 3
|
Loading…
Reference in New Issue
Block a user