mirror of
git://projects.qi-hardware.com/antorcha.git
synced 2024-11-01 09:24:05 +02:00
make firmware upload protocol less secure but lean; boot loader works
This commit is contained in:
parent
fb8e75cd2a
commit
89b10939f9
2
NOTES
2
NOTES
@ -93,3 +93,5 @@ authentication:
|
|||||||
- shared secret (128 bit, SHA1-hashed text with 128 bit salt)
|
- shared secret (128 bit, SHA1-hashed text with 128 bit salt)
|
||||||
- salt (128 bit)
|
- salt (128 bit)
|
||||||
- SHA1 from avrcryptolib
|
- SHA1 from avrcryptolib
|
||||||
|
- due to chip limitations, the secret key for firmware updates is sent
|
||||||
|
in the clear
|
||||||
|
10
PROTOCOL
10
PROTOCOL
@ -7,14 +7,8 @@ Protocol
|
|||||||
|
|
||||||
1 0 0 Pong (maybe return version string in the future)
|
1 0 0 Pong (maybe return version string in the future)
|
||||||
|
|
||||||
2 0 3 Unlock salt A (64 bytes payload)
|
4 0 N Unlock secret (64 bytes payload)
|
||||||
2 1 3 Unlock salt B
|
4 1..N-1 N Firmware binary (64 bytes payload)
|
||||||
2 2 3 Unlock hash A
|
|
||||||
2 3 3 Unlock hash B
|
|
||||||
|
|
||||||
3 n 0 Unlock ACK
|
|
||||||
|
|
||||||
4 0..N-1 N Firmware binary (64 bytes payload)
|
|
||||||
4 N N First half of hash
|
4 N N First half of hash
|
||||||
|
|
||||||
5 n N Firmware ACK
|
5 n N Firmware ACK
|
||||||
|
17
fw/Makefile
17
fw/Makefile
@ -15,15 +15,13 @@ SHELL = /bin/bash
|
|||||||
NAME = antorcha
|
NAME = antorcha
|
||||||
|
|
||||||
CFLAGS = -g -mmcu=$(CHIP) \
|
CFLAGS = -g -mmcu=$(CHIP) \
|
||||||
-DBOOT_ADDR=$(BOOT_ADDR) -DAPP_ADDR=$(APP_ADDR) -DAPP_END=$(APP_END) \
|
-DBOOT_ADDR=$(BOOT_ADDR) \
|
||||||
-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 = 0
|
BOOT_ADDR = 0x3800
|
||||||
APP_ADDR = 0x1000
|
|
||||||
APP_END = 0x4000
|
|
||||||
|
|
||||||
AVR_PREFIX = $(BIN_PATH) avr-
|
AVR_PREFIX = $(BIN_PATH) avr-
|
||||||
CC = $(AVR_PREFIX)gcc
|
CC = $(AVR_PREFIX)gcc
|
||||||
@ -31,9 +29,9 @@ OBJCOPY = $(AVR_PREFIX)objcopy
|
|||||||
#OBJDUMP = $(AVR_PREFIX)objdump
|
#OBJDUMP = $(AVR_PREFIX)objdump
|
||||||
SIZE = $(AVR_PREFIX)size
|
SIZE = $(AVR_PREFIX)size
|
||||||
|
|
||||||
OBJS = $(NAME).o $(COMMON_OBJS)
|
OBJS = $(NAME).o dispatch.o hash.o $(COMMON_OBJS)
|
||||||
BOOT_OBJS = boot.o flash.o fw.o $(COMMON_OBJS)
|
BOOT_OBJS = boot.o flash.o fw.o $(COMMON_OBJS)
|
||||||
COMMON_OBJS = dispatch.o hash.o rf.o spi.o
|
COMMON_OBJS = rf.o spi.o
|
||||||
|
|
||||||
# ----- Verbosity control -----------------------------------------------------
|
# ----- Verbosity control -----------------------------------------------------
|
||||||
|
|
||||||
@ -64,8 +62,7 @@ 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) \
|
||||||
@ -140,7 +137,9 @@ prog-app:
|
|||||||
|
|
||||||
prog:
|
prog:
|
||||||
ssh $(HOST) avrdude -F -p $(CHIP) -c nanonote_antorcha -e \
|
ssh $(HOST) avrdude -F -p $(CHIP) -c nanonote_antorcha -e \
|
||||||
-U flash:w:boot.hex:i
|
-U flash:w:boot.hex:i \
|
||||||
|
-U efuse:w:0x00:m \
|
||||||
|
-U lfuse:w:0xe2:m
|
||||||
# -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
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* fw/main.c - Initialization of Antorcha firmware
|
* fw/antorcha.c - Initialization of Antorcha application firmware
|
||||||
*
|
*
|
||||||
* Written 2012 by Werner Almesberger
|
* Written 2012 by Werner Almesberger
|
||||||
* Copyright 2012 Werner Almesberger
|
* Copyright 2012 Werner Almesberger
|
||||||
@ -11,50 +11,43 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <avr/io.h>
|
#include <avr/io.h>
|
||||||
|
#define F_CPU 8000000UL
|
||||||
|
#include <util/delay.h>
|
||||||
|
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "rf.h"
|
#include "rf.h"
|
||||||
|
#include "dispatch.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static const struct handler *protos[] = {
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
/* Port B has two LEDs and the rest is SPI */
|
uint8_t buf[PAYLOAD+5]; /* 3 bytes header, 2 bytes CRC */
|
||||||
PORTB = MASK(B, RF_nSS) | MASK(B, RF_nRST);
|
uint8_t got;
|
||||||
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;
|
* The boot loader has already initialized PORTx, DDRx, and MCUCR.PUD.
|
||||||
DDRC = 0x3f;
|
* It has also brought up RF and the underlying SPI.
|
||||||
|
*/
|
||||||
/* All port D pins drive LEDs */
|
|
||||||
PORTD = 0;
|
|
||||||
DDRD = 0xff;
|
|
||||||
|
|
||||||
/* disable pull-ups */
|
|
||||||
MCUCR |= 1 << PUD;
|
|
||||||
|
|
||||||
rf_init();
|
|
||||||
|
|
||||||
while (0) {
|
|
||||||
PORTC = 2;
|
|
||||||
PORTC = 0;
|
|
||||||
rf_send("HOLA ?", 6);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
SET(LED_B8);
|
||||||
|
_delay_ms(100);
|
||||||
|
CLR(LED_B8);
|
||||||
|
_delay_ms(100);
|
||||||
|
}
|
||||||
while (1) {
|
while (1) {
|
||||||
uint8_t buf[1], got;
|
got = rf_recv(buf, sizeof(buf));
|
||||||
|
if (got > 2)
|
||||||
do {
|
dispatch(buf, got-2, protos);
|
||||||
PORTC = 1;
|
|
||||||
PORTC = 0;
|
|
||||||
got = rf_recv(buf, 1);
|
|
||||||
}
|
|
||||||
while (!got);
|
|
||||||
|
|
||||||
PORTC = 2;
|
|
||||||
PORTC = 0;
|
|
||||||
PORTD = buf[0];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
12
fw/boot.c
12
fw/boot.c
@ -21,19 +21,19 @@
|
|||||||
#include "fw.h"
|
#include "fw.h"
|
||||||
|
|
||||||
|
|
||||||
#define MS_TO_LOOP(ms) ((uint32_t) (ms)*335)
|
#define MS_TO_LOOP(ms) ((uint32_t) (ms)*106)
|
||||||
|
|
||||||
|
|
||||||
static void wait_upload(void)
|
static void wait_upload(void)
|
||||||
{
|
{
|
||||||
uint8_t buf[PAYLOAD+5];
|
uint8_t buf[PAYLOAD+5]; /* 3 bytes header, 2 bytes CRC */
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
uint8_t got;
|
uint8_t got;
|
||||||
|
|
||||||
restart:
|
restart:
|
||||||
for (i = 0; i != MS_TO_LOOP(2000); i++) {
|
for (i = 0; i != MS_TO_LOOP(5000); i++) {
|
||||||
got = rf_recv(buf, sizeof(buf));
|
got = rf_recv(buf, sizeof(buf));
|
||||||
if (got && dispatch(buf, got, fw_protos))
|
if (got > 2 && fw_packet(buf, got-2))
|
||||||
goto restart;
|
goto restart;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,9 +70,7 @@ int main(void)
|
|||||||
SET(LED_B8);
|
SET(LED_B8);
|
||||||
wait_upload();
|
wait_upload();
|
||||||
CLR(LED_B8);
|
CLR(LED_B8);
|
||||||
while (1);
|
} while (pgm_read_byte(zero) == 0xff);
|
||||||
} while (pgm_read_byte(zero) != 0xff);
|
|
||||||
|
|
||||||
|
|
||||||
((void (*)(void)) 0)();
|
((void (*)(void)) 0)();
|
||||||
|
|
||||||
|
@ -15,13 +15,9 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#define F_CPU 8000000UL
|
|
||||||
#include <util/delay.h>
|
|
||||||
|
|
||||||
#include "rf.h"
|
#include "rf.h"
|
||||||
#include "proto.h"
|
#include "proto.h"
|
||||||
#include "dispatch.h"
|
#include "dispatch.h"
|
||||||
#include "io.h"
|
|
||||||
|
|
||||||
|
|
||||||
static uint8_t seq; /* last sequence number seen */
|
static uint8_t seq; /* last sequence number seen */
|
||||||
@ -34,10 +30,7 @@ static void send_ack(const uint8_t *buf)
|
|||||||
{
|
{
|
||||||
uint8_t ack[3] = { buf[0]+1, buf[1], 0 };
|
uint8_t ack[3] = { buf[0]+1, buf[1], 0 };
|
||||||
|
|
||||||
SET(LED_B6);
|
|
||||||
_delay_ms(1);
|
|
||||||
rf_send(ack, sizeof(ack));
|
rf_send(ack, sizeof(ack));
|
||||||
CLR(LED_B6);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -54,8 +47,6 @@ static bool answer_ping(const uint8_t *buf)
|
|||||||
|
|
||||||
bool dispatch(const uint8_t *buf, uint8_t len, const struct handler **protos)
|
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)
|
if (len == 3 && buf[0] == PING)
|
||||||
return answer_ping(buf);
|
return answer_ping(buf);
|
||||||
|
|
||||||
@ -78,23 +69,24 @@ CLR(LED_B7);
|
|||||||
limit = buf[2];
|
limit = buf[2];
|
||||||
send_ack(buf);
|
send_ack(buf);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
} else {
|
||||||
|
|
||||||
if (!curr_proto)
|
if (!curr_proto)
|
||||||
return 0;
|
return 0;
|
||||||
if (buf[0] != type)
|
if (buf[0] != type)
|
||||||
return 0;
|
return 0;
|
||||||
if (buf[1] > limit)
|
|
||||||
return 0;
|
|
||||||
if (buf[2] != limit)
|
if (buf[2] != limit)
|
||||||
return 0;
|
return 0;
|
||||||
|
if (buf[1] > limit)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (buf[1] == seq) {
|
if (buf[1]+1 == seq) {
|
||||||
send_ack(buf);
|
send_ack(buf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (buf[1] != seq+1)
|
if (buf[1] != seq)
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!curr_proto->more(buf[1], limit, buf+3))
|
if (!curr_proto->more(buf[1], limit, buf+3))
|
||||||
return 0;
|
return 0;
|
||||||
seq++;
|
seq++;
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "proto.h"
|
||||||
|
|
||||||
|
|
||||||
struct handler {
|
struct handler {
|
||||||
enum pck_type type;
|
enum pck_type type;
|
||||||
|
@ -26,15 +26,15 @@
|
|||||||
static uint32_t payload;
|
static uint32_t payload;
|
||||||
|
|
||||||
|
|
||||||
void flash_start(uint32_t addr)
|
void flash_start(void)
|
||||||
{
|
{
|
||||||
payload = addr;
|
payload = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int flash_can_write(uint16_t size)
|
int flash_can_write(uint16_t size)
|
||||||
{
|
{
|
||||||
return payload <= APP_END-size;
|
return payload <= BOOT_ADDR-size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
void flash_start(uint32_t addr);
|
void flash_start(void);
|
||||||
int flash_can_write(uint16_t size);
|
int flash_can_write(uint16_t size);
|
||||||
void flash_write(const uint8_t *buf, uint16_t size);
|
void flash_write(const uint8_t *buf, uint16_t size);
|
||||||
void flash_end_write(void);
|
void flash_end_write(void);
|
||||||
|
150
fw/fw.c
150
fw/fw.c
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* fw/fw.h - Firmware upload protocols
|
* fw/fw.h - Firmware upload protocol
|
||||||
*
|
*
|
||||||
* Written 2012 by Werner Almesberger
|
* Written 2012 by Werner Almesberger
|
||||||
* Copyright 2012 Werner Almesberger
|
* Copyright 2012 Werner Almesberger
|
||||||
@ -11,123 +11,85 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "hash.h"
|
#include "io.h"
|
||||||
#include "flash.h"
|
#include "flash.h"
|
||||||
#include "proto.h"
|
#include "proto.h"
|
||||||
#include "dispatch.h"
|
#include "rf.h"
|
||||||
#include "fw.h"
|
#include "fw.h"
|
||||||
|
|
||||||
|
|
||||||
static const uint8_t unlock_secret[] = {
|
static const uint8_t unlock_secret[PAYLOAD] = {
|
||||||
#include "unlock-secret.inc"
|
#include "unlock-secret.inc"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static void panic(void)
|
static bool locked = 1;
|
||||||
|
|
||||||
|
|
||||||
|
static bool fw_payload(uint8_t seq, uint8_t limit, const uint8_t *payload)
|
||||||
{
|
{
|
||||||
/* ??? */
|
if (!seq) {
|
||||||
}
|
locked = memcmp(unlock_secret, payload, PAYLOAD) != 0;
|
||||||
|
flash_start();
|
||||||
|
|
||||||
/* ----- 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;
|
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;
|
if (locked)
|
||||||
}
|
return 0;
|
||||||
|
|
||||||
|
|
||||||
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))
|
if (!flash_can_write(PAYLOAD))
|
||||||
return 0;
|
return 0;
|
||||||
if (seq != limit) {
|
|
||||||
hash_merge(payload, PAYLOAD);
|
|
||||||
flash_write(payload, PAYLOAD);
|
flash_write(payload, PAYLOAD);
|
||||||
return 1;
|
if (seq == limit)
|
||||||
}
|
|
||||||
flash_end_write();
|
flash_end_write();
|
||||||
hash_end();
|
|
||||||
if (!hash_eq(payload, PAYLOAD, 0))
|
|
||||||
panic();
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const struct handler fw_proto = {
|
bool fw_packet(const uint8_t *buf, uint8_t len)
|
||||||
.type = FIRMWARE,
|
{
|
||||||
.first = fw_first,
|
static uint8_t seq = 0;
|
||||||
.more = fw_more,
|
static uint8_t limit;
|
||||||
};
|
uint8_t ack[] = { FIRMWARE+1, buf[1], buf[2] };
|
||||||
|
|
||||||
|
/* short (barely visible) flash to indicate reception */
|
||||||
|
SET(LED_B7);
|
||||||
|
CLR(LED_B7);
|
||||||
|
|
||||||
/* ----- Protocol table ---------------------------------------------------- */
|
/* Check packet for formal validity */
|
||||||
|
|
||||||
|
if (len != 64+3)
|
||||||
|
return 0;
|
||||||
|
if (buf[0] != FIRMWARE)
|
||||||
|
return 0;
|
||||||
|
if (buf[1] > buf[2])
|
||||||
|
return 0;
|
||||||
|
|
||||||
const struct handler *fw_protos[] = {
|
/* Synchronize sequence numbers */
|
||||||
&unlock_proto,
|
|
||||||
&fw_proto,
|
if (!buf[1]) {
|
||||||
NULL
|
seq = buf[1];
|
||||||
};
|
limit = buf[2];
|
||||||
|
} else {
|
||||||
|
if (buf[2] != limit)
|
||||||
|
return 0;
|
||||||
|
if (buf[1]+1 == seq)
|
||||||
|
goto ack;
|
||||||
|
if (buf[1] != seq)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process the payload */
|
||||||
|
|
||||||
|
if (!fw_payload(buf[1], limit, buf+3))
|
||||||
|
return 0;
|
||||||
|
seq++;
|
||||||
|
ack:
|
||||||
|
/* clearly visible short blink to indicate progress */
|
||||||
|
SET(LED_B6);
|
||||||
|
rf_send(ack, sizeof(ack));
|
||||||
|
CLR(LED_B6);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
6
fw/fw.h
6
fw/fw.h
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* fw/fw.h - Firmware upload protocols
|
* fw/fw.h - Firmware upload protocol
|
||||||
*
|
*
|
||||||
* Written 2012 by Werner Almesberger
|
* Written 2012 by Werner Almesberger
|
||||||
* Copyright 2012 Werner Almesberger
|
* Copyright 2012 Werner Almesberger
|
||||||
@ -13,9 +13,9 @@
|
|||||||
#ifndef FW_H
|
#ifndef FW_H
|
||||||
#define FW_H
|
#define FW_H
|
||||||
|
|
||||||
#include "proto.h"
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
extern const struct handler *fw_protos[];
|
bool fw_packet(const uint8_t *buf, uint8_t len);
|
||||||
|
|
||||||
#endif /* !FW_H */
|
#endif /* !FW_H */
|
||||||
|
@ -18,8 +18,6 @@
|
|||||||
enum pck_type {
|
enum pck_type {
|
||||||
PING = 0, /* version query */
|
PING = 0, /* version query */
|
||||||
PONG = 1, /* version response */
|
PONG = 1, /* version response */
|
||||||
UNLOCK = 2, /* unlock firmware upload */
|
|
||||||
UNLOCK_ACK = 3, /* unlock acknowledgement */
|
|
||||||
FIRMWARE = 4, /* firmware upload */
|
FIRMWARE = 4, /* firmware upload */
|
||||||
FIRMWARE_ACK = 5, /* firmware upload acknowledgement */
|
FIRMWARE_ACK = 5, /* firmware upload acknowledgement */
|
||||||
IMAGE = 6, /* image upload */
|
IMAGE = 6, /* image upload */
|
||||||
|
6
fw/rf.c
6
fw/rf.c
@ -89,6 +89,9 @@ void rf_send(const void *buf, uint8_t size)
|
|||||||
reg_write(REG_TRX_STATE, TRX_CMD_PLL_ON);
|
reg_write(REG_TRX_STATE, TRX_CMD_PLL_ON);
|
||||||
_delay_us(1); /* tTR9 = 1 us */
|
_delay_us(1); /* tTR9 = 1 us */
|
||||||
|
|
||||||
|
/* be nice to senders with long turn-around time, e.g., atusb */
|
||||||
|
_delay_ms(2);
|
||||||
|
|
||||||
spi_begin();
|
spi_begin();
|
||||||
spi_send(AT86RF230_BUF_WRITE);
|
spi_send(AT86RF230_BUF_WRITE);
|
||||||
spi_send(size+2); /* CRC */
|
spi_send(size+2); /* CRC */
|
||||||
@ -115,6 +118,9 @@ uint8_t rf_recv(void *buf, uint8_t size)
|
|||||||
{
|
{
|
||||||
uint8_t irq, len, i;
|
uint8_t irq, len, i;
|
||||||
|
|
||||||
|
if (!PIN(RF_IRQ))
|
||||||
|
return 0;
|
||||||
|
|
||||||
irq = reg_read(REG_IRQ_STATUS);
|
irq = reg_read(REG_IRQ_STATUS);
|
||||||
if (!(irq & IRQ_TRX_END))
|
if (!(irq & IRQ_TRX_END))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -45,13 +45,17 @@ static void rf_init(struct atrf_dsc *dsc, int trim, int channel)
|
|||||||
|
|
||||||
static void rf_send(struct atrf_dsc *dsc, void *buf, int len)
|
static void rf_send(struct atrf_dsc *dsc, void *buf, int len)
|
||||||
{
|
{
|
||||||
|
uint8_t tmp[MAX_PSDU];
|
||||||
|
|
||||||
|
/* Copy the message to append the CRC placeholders */
|
||||||
|
memcpy(tmp, buf, len);
|
||||||
atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_PLL_ON);
|
atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_PLL_ON);
|
||||||
atrf_buf_write(dsc, buf, len);
|
atrf_buf_write(dsc, tmp, len+2);
|
||||||
atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TX_START);
|
atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TX_START);
|
||||||
wait_for_interrupt(dsc, IRQ_TRX_END,
|
wait_for_interrupt(dsc, IRQ_TRX_END,
|
||||||
IRQ_TRX_END | IRQ_PLL_LOCK, 10);
|
IRQ_TRX_END | IRQ_PLL_LOCK, 10);
|
||||||
atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_RX_ON);
|
atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_RX_ON);
|
||||||
#if 1
|
#if 0
|
||||||
int i;
|
int i;
|
||||||
fprintf(stderr, "\r%d:", len);
|
fprintf(stderr, "\r%d:", len);
|
||||||
for (i = 0; i != len; i++)
|
for (i = 0; i != len; i++)
|
||||||
@ -96,7 +100,7 @@ static void ping(struct atrf_dsc *dsc)
|
|||||||
|
|
||||||
|
|
||||||
static void packet(struct atrf_dsc *dsc,
|
static void packet(struct atrf_dsc *dsc,
|
||||||
uint8_t type, uint8_t seq, uint8_t last, void *payload, int len)
|
uint8_t type, uint8_t seq, uint8_t last, const void *payload, int len)
|
||||||
{
|
{
|
||||||
uint8_t tx_buf[PAYLOAD+3] = { type, seq, last };
|
uint8_t tx_buf[PAYLOAD+3] = { type, seq, last };
|
||||||
uint8_t rx_buf[10];
|
uint8_t rx_buf[10];
|
||||||
@ -109,8 +113,11 @@ static void packet(struct atrf_dsc *dsc,
|
|||||||
if (verbose)
|
if (verbose)
|
||||||
write(2, ">", 1);
|
write(2, ">", 1);
|
||||||
got = rf_recv(dsc, rx_buf, sizeof(rx_buf));
|
got = rf_recv(dsc, rx_buf, sizeof(rx_buf));
|
||||||
if (got <= 0)
|
if (got <= 0) {
|
||||||
|
if (!seq && verbose)
|
||||||
|
write(2, "\b", 1);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
if (verbose)
|
if (verbose)
|
||||||
write(2, "\b?", 2);
|
write(2, "\b?", 2);
|
||||||
if (got < 3)
|
if (got < 3)
|
||||||
@ -126,34 +133,11 @@ static void packet(struct atrf_dsc *dsc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const uint8_t unlock_secret[] = {
|
static const uint8_t unlock_secret[PAYLOAD] = {
|
||||||
#include "unlock-secret.inc"
|
#include "unlock-secret.inc"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static void unlock(struct atrf_dsc *dsc)
|
|
||||||
{
|
|
||||||
uint8_t payload[PAYLOAD];
|
|
||||||
|
|
||||||
if (verbose)
|
|
||||||
write(2, "unlock ", 9);
|
|
||||||
memset(payload, 0, PAYLOAD);
|
|
||||||
hash_init();
|
|
||||||
hash_merge(unlock_secret, sizeof(unlock_secret));
|
|
||||||
hash_merge(payload, PAYLOAD);
|
|
||||||
hash_merge(payload, PAYLOAD);
|
|
||||||
packet(dsc, UNLOCK, 0, 3, payload, PAYLOAD);
|
|
||||||
packet(dsc, UNLOCK, 1, 3, payload, PAYLOAD);
|
|
||||||
hash_end();
|
|
||||||
hash_cp(payload, PAYLOAD, 0);
|
|
||||||
packet(dsc, UNLOCK, 2, 3, payload, PAYLOAD);
|
|
||||||
hash_cp(payload, PAYLOAD, PAYLOAD);
|
|
||||||
packet(dsc, UNLOCK, 3, 3, payload, PAYLOAD);
|
|
||||||
if (verbose)
|
|
||||||
write(2, "\n", 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void send_firmware(struct atrf_dsc *dsc, void *buf, int len)
|
static void send_firmware(struct atrf_dsc *dsc, void *buf, int len)
|
||||||
{
|
{
|
||||||
uint8_t payload[PAYLOAD];
|
uint8_t payload[PAYLOAD];
|
||||||
@ -163,9 +147,9 @@ static void send_firmware(struct atrf_dsc *dsc, void *buf, int len)
|
|||||||
write(2, "firmware ", 9);
|
write(2, "firmware ", 9);
|
||||||
last = (len+63)/64;
|
last = (len+63)/64;
|
||||||
seq = 0;
|
seq = 0;
|
||||||
|
packet(dsc, FIRMWARE, seq++, last, unlock_secret, PAYLOAD);
|
||||||
while (len >= PAYLOAD) {
|
while (len >= PAYLOAD) {
|
||||||
packet(dsc, FIRMWARE, seq++, last, buf, PAYLOAD);
|
packet(dsc, FIRMWARE, seq++, last, buf, PAYLOAD);
|
||||||
hash_merge(buf, PAYLOAD);
|
|
||||||
buf += PAYLOAD;
|
buf += PAYLOAD;
|
||||||
len -= PAYLOAD;
|
len -= PAYLOAD;
|
||||||
}
|
}
|
||||||
@ -173,11 +157,7 @@ static void send_firmware(struct atrf_dsc *dsc, void *buf, int len)
|
|||||||
memcpy(payload, buf, len);
|
memcpy(payload, buf, len);
|
||||||
memset(payload+len, 0, PAYLOAD-len);
|
memset(payload+len, 0, PAYLOAD-len);
|
||||||
packet(dsc, FIRMWARE, seq++, last, payload, PAYLOAD);
|
packet(dsc, FIRMWARE, seq++, last, payload, PAYLOAD);
|
||||||
hash_merge(payload, PAYLOAD);
|
|
||||||
}
|
}
|
||||||
hash_end();
|
|
||||||
hash_cp(payload, PAYLOAD, 0);
|
|
||||||
packet(dsc, FIRMWARE, seq, last, payload, PAYLOAD);
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
write(2, "\n", 1);
|
write(2, "\n", 1);
|
||||||
}
|
}
|
||||||
@ -201,7 +181,6 @@ static void firmware(struct atrf_dsc *dsc, const char *name)
|
|||||||
}
|
}
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
|
||||||
unlock(dsc);
|
|
||||||
send_firmware(dsc, fw, len);
|
send_firmware(dsc, fw, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user