loader: incomplete crc support and query timeouts

This commit is contained in:
Ingo Albrecht 2010-03-30 19:47:56 +02:00
parent 154ff9e53a
commit f0f2dc81ee
2 changed files with 83 additions and 29 deletions

View File

@ -38,6 +38,7 @@
#include <osmocore/msgb.h>
#include <osmocore/select.h>
#include <osmocore/timer.h>
#include <osmocore/crc16.h>
#include <loader/protocol.h>
@ -75,6 +76,14 @@ static struct {
/* binary i/o for firmware images */
FILE *binfile;
char *binbuf;
uint32_t membase;
uint32_t memlen;
uint32_t memoff;
uint16_t memcrc;
uint16_t memreq;
/* memory operation state */
uint32_t req_length;
uint32_t req_address;
@ -169,10 +178,16 @@ loader_send_request(struct msgb *msg) {
static void loader_do_memdump(void *address, size_t length);
static void loader_do_memload();
static void
mem_progress() {
putchar('.');
fflush(stdout);
static memop_timeout(void *dummy) {
switch(osmoload.state) {
case STATE_LOAD_IN_PROGRESS:
printf("Timeout. Repeating.");
osmoload.memoff -= osmoload.memreq;
loader_do_memload();
break;
default:
break;
}
}
static void
@ -185,6 +200,7 @@ loader_handle_reply(struct msgb *msg) {
uint8_t cmd = msgb_get_u8(msg);
uint8_t length;
uint16_t crc;
uint32_t address;
uint32_t entrypoint;
@ -209,6 +225,7 @@ loader_handle_reply(struct msgb *msg) {
break;
case LOADER_MEM_WRITE:
length = msgb_get_u8(msg);
crc = msgb_get_u16(msg);
address = msgb_get_u32(msg);
break;
case LOADER_JUMP:
@ -261,13 +278,15 @@ loader_handle_reply(struct msgb *msg) {
break;
case STATE_DUMP_IN_PROGRESS:
if(cmd == LOADER_MEM_READ) {
mem_progress();
loader_do_memdump(data, length);
}
break;
case STATE_LOAD_IN_PROGRESS:
if(cmd == LOADER_MEM_WRITE) {
mem_progress();
if(osmoload.memcrc != crc) {
osmoload.memoff -= osmoload.memreq;
printf("bad CRC %x\n", crc);
}
loader_do_memload();
}
break;
@ -436,9 +455,7 @@ loader_do_memdump(void *data, size_t length) {
static void
loader_do_memload() {
int rc;
uint32_t rembytes = osmoload.req_length - osmoload.cur_length;
uint32_t rembytes = osmoload.memlen - osmoload.memoff;
if(!rembytes) {
puts("done.");
@ -446,31 +463,32 @@ loader_do_memload() {
return;
}
bsc_schedule_timer(&osmoload.timeout, 0, 500000);
uint8_t reqbytes = (rembytes < MEM_MSG_MAX) ? rembytes : MEM_MSG_MAX;
osmoload.memcrc = crc16(0, osmoload.binbuf + osmoload.memoff, reqbytes);
osmoload.memreq = reqbytes;
struct msgb *msg = msgb_alloc(MSGB_MAX, "loader");
msgb_put_u8(msg, LOADER_MEM_WRITE);
msgb_put_u8(msg, reqbytes);
msgb_put_u32(msg, osmoload.cur_address);
msgb_put_u16(msg, osmoload.memcrc);
msgb_put_u32(msg, osmoload.membase + osmoload.memoff);
unsigned c = 0;
unsigned char *p = msgb_put(msg, reqbytes);
while(c < reqbytes) {
rc = fread(p, 1, reqbytes, osmoload.binfile);
if(ferror(osmoload.binfile)) {
printf("Could not read from file: %s\n", strerror(errno));
}
c -= rc;
p += rc;
}
memcpy(p, osmoload.binbuf + osmoload.memoff, reqbytes);
printf("Sending %u bytes at offset %u to address %x with crc %x\n",
reqbytes, osmoload.memoff, osmoload.membase + osmoload.memoff,
osmoload.memcrc);
loader_send_request(msg);
msgb_free(msg);
osmoload.cur_address += reqbytes;
osmoload.cur_length += reqbytes;
osmoload.memoff += reqbytes;
}
static void
@ -507,17 +525,34 @@ loader_start_memload(uint32_t address, char *file) {
printf("Loading %u bytes of memory at 0x%x to file %s\n", length, address, file);
osmoload.binbuf = malloc(length);
if(!osmoload.binbuf) {
printf("Could not allocate %u bytes for %s.\n", length, file);
exit(1);
}
osmoload.binfile = fopen(file, "rb");
if(!osmoload.binfile) {
printf("Could not open %s: %s\n", file, strerror(errno));
exit(1);
}
osmoload.req_length = length;
osmoload.req_address = address;
unsigned c = length;
char *p = osmoload.binbuf;
while(c) {
rc = fread(p, 1, c, osmoload.binfile);
if(ferror(osmoload.binfile)) {
printf("Could not read from file: %s\n", strerror(errno));
}
c -= rc;
p += rc;
}
fclose(osmoload.binfile);
osmoload.binfile = NULL;
osmoload.cur_length = 0;
osmoload.cur_address = address;
osmoload.membase = address;
osmoload.memlen = length;
osmoload.memoff = 0;
loader_do_memload();
}
@ -552,7 +587,6 @@ loader_command(char *name, int cmdc, char **cmdv) {
} else if(!strcmp(cmd, "jumpflash")) {
loader_send_query(LOADER_ENTER_FLASH_LOADER);
} else if(!strcmp(cmd, "memput")) {
// XXX implement command line parsing
uint32_t address;
if(cmdc < 3) {
@ -646,6 +680,10 @@ loader_command(char *name, int cmdc, char **cmdv) {
osmoload.timeout.cb = &query_timeout;
bsc_schedule_timer(&osmoload.timeout, 0, 500000);
}
if(osmoload.state == STATE_LOAD_IN_PROGRESS) {
osmoload.timeout.cb = &memop_timeout;
}
}
void

View File

@ -33,6 +33,8 @@
#include <console.h>
#include <manifest.h>
#include <osmocore/crc16.h>
#include <abb/twl3025.h>
#include <rf/trf6151.h>
@ -168,6 +170,7 @@ static void cmd_handler(uint8_t dlci, struct msgb *msg) {
printf("command %u: ", command);
uint8_t nbytes;
uint16_t crc;
uint32_t address;
struct msgb *reply;
@ -229,13 +232,25 @@ static void cmd_handler(uint8_t dlci, struct msgb *msg) {
case LOADER_MEM_WRITE:
nbytes = msgb_get_u8(msg);
crc = msgb_get_u16(msg);
address = msgb_get_u32(msg);
printf("mem write %u @ %p\n", nbytes, (void*)address);
memcpy((void*)address, msgb_get(msg, nbytes), nbytes);
void *data = msgb_get(msg, nbytes);
reply = sercomm_alloc_msgb(6);
uint16_t mycrc = crc16(0, data, nbytes);
#if 0
printf("crc %x got %x\n", mycrc, crc);
hexdump(data, nbytes);
#endif
if(mycrc == crc) {
memcpy((void*)address, data, nbytes);
}
reply = sercomm_alloc_msgb(8);
if(!reply) {
printf("Failed to allocate reply buffer!\n");
@ -243,6 +258,7 @@ static void cmd_handler(uint8_t dlci, struct msgb *msg) {
msgb_put_u8(reply, LOADER_MEM_WRITE);
msgb_put_u8(reply, nbytes);
msgb_put_u16(reply, mycrc);
msgb_put_u32(reply, address);
sercomm_sendmsg(dlci, reply);
@ -271,7 +287,7 @@ static void cmd_handler(uint8_t dlci, struct msgb *msg) {
break;
default:
printf("unknown command\n", command);
printf("unknown command %d\n", command);
break;
}