view loadtools/compalload.c @ 432:15e69d31c96f
tfc139: allow -B option just like rvtdump and rvinterf
author |
Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
date |
Sat, 21 Jun 2014 23:50:25 +0000 (2014-06-21) |
parents |
7b3fd0e2a352 |
children |
|
line source
/*
* This module implements Compal's serial code loading protocol to load
* what we call compalstage, a piece of code that re-enables the Calypso
* boot ROM and allows us to use the same loadagent which we use on
* freedom-enabled target devices.
*/
#include <sys/param.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <termios.h>
#include <unistd.h>
extern char default_helpers_dir[];
extern char *target_ttydev;
extern int target_fd;
extern struct termios target_termios;
static char compalstage_pathname[MAXPATHLEN];
static u_char *compalstage_imgbuf;
static size_t compalstage_len, compalstage_totlen;
static int rx_state;
static u_char rx_msg[3];
void
set_compalstage_short(arg)
char *arg;
{
if (strcmp(arg, "none"))
sprintf(compalstage_pathname, "%s/compalstage-%s.bin",
default_helpers_dir, arg);
else
compalstage_pathname[0] = 0;
}
void
set_compalstage_fullpath(arg)
char *arg;
{
strcpy(compalstage_pathname, arg);
}
static void
compute_checksum()
{
size_t i, l;
u_char ck;
ck = 0x02;
l = compalstage_len + 3;
for (i = 1; i < l; i++)
ck ^= compalstage_imgbuf[i];
compalstage_imgbuf[l] = ck;
}
static
handle_rx_msg()
{
static u_char download_cmd[7] = {0x1B, 0xF6, 0x02, 0x00,
0x52, 0x01, 0x53};
if (rx_msg[0] == 0x41 && rx_msg[1] == 0x01 && rx_msg[2] == 0x40) {
printf("Received PROMPT1, sending download command\n");
write(target_fd, download_cmd, 7);
return(0);
} else if (rx_msg[0] == 0x41 && rx_msg[1] == 0x02 && rx_msg[2] == 0x43){
printf("Received PROMPT2, sending download image\n");
write(target_fd, compalstage_imgbuf, compalstage_totlen);
return(0);
} else if (rx_msg[0] == 0x41 && rx_msg[1] == 0x03 && rx_msg[2] == 0x42){
printf("Received ACK; downloaded image should now be running!\n");
return(1);
} else if (rx_msg[0] == 0x45 && rx_msg[1] == 0x53 && rx_msg[2] == 0x16){
printf("Bootloader indicates bad checksum :-(\n");
return(0);
} else if (rx_msg[0] == 0x41 && rx_msg[1] == 0x03 && rx_msg[2] == 0x57){
printf("Bootloader indicates bad magic :-(\n");
return(0);
} else {
printf("Unknown msg from bootloader: 1B F6 02 00 %02X %02X %02X\n",
rx_msg[0], rx_msg[1], rx_msg[2]);
return(0);
}
}
static
handle_rx_byte(rxb)
{
switch (rx_state) {
case 0:
if (rxb == 0x1B)
rx_state = 1;
return(0);
case 1:
if (rxb == 0xF6)
rx_state = 2;
else if (rxb == 0x1B)
rx_state = 1;
else
rx_state = 0;
return(0);
case 2:
if (rxb == 0x02)
rx_state = 3;
else if (rxb == 0x1B)
rx_state = 1;
else
rx_state = 0;
return(0);
case 3:
if (rxb == 0x00)
rx_state = 4;
else if (rxb == 0x1B)
rx_state = 1;
else
rx_state = 0;
return(0);
case 4:
rx_msg[0] = rxb;
rx_state = 5;
return(0);
case 5:
rx_msg[1] = rxb;
rx_state = 6;
return(0);
case 6:
rx_msg[2] = rxb;
rx_state = 0;
return handle_rx_msg();
}
}
static void
read_loop()
{
u_char rdbuf[16];
int cc, i;
for (;;) {
cc = read(target_fd, rdbuf, sizeof rdbuf);
if (cc <= 0) {
fprintf(stderr, "EOF/error on target tty\n");
exit(1);
}
for (i = 0; i < cc; i++)
if (handle_rx_byte(rdbuf[i]))
return;
}
}
perform_compal_stage(for_boot_rom)
{
int fd;
struct stat st;
static int zero = 0;
if (!compalstage_pathname[0])
return(0);
fd = open(compalstage_pathname, O_RDONLY);
if (fd < 0) {
perror(compalstage_pathname);
exit(1);
}
fstat(fd, &st);
if (!S_ISREG(st.st_mode)) {
fprintf(stderr, "error: %s is not a regular file\n",
compalstage_pathname);
exit(1);
}
if (st.st_size > 65535) {
fprintf(stderr,
"error: %s exceed Compal download limit of 65535 bytes\n",
compalstage_pathname);
exit(1);
}
compalstage_len = st.st_size;
compalstage_totlen = compalstage_len + 4;
compalstage_imgbuf = malloc(compalstage_totlen);
if (!compalstage_imgbuf) {
perror("malloc");
exit(1);
}
compalstage_imgbuf[0] = 0x02;
compalstage_imgbuf[1] = compalstage_len >> 8;
compalstage_imgbuf[2] = compalstage_len;
if (read(fd, compalstage_imgbuf+3, compalstage_len) != compalstage_len){
fprintf(stderr, "%s: read error or short read\n",
compalstage_pathname);
exit(1);
}
close(fd);
compute_checksum();
printf("Using Compal stage image %s\n", compalstage_pathname);
cfsetispeed(&target_termios, B115200);
cfsetospeed(&target_termios, B115200);
if (tcsetattr(target_fd, TCSAFLUSH, &target_termios) < 0) {
perror("tcsetattr to switch baud rate");
exit(1);
}
ioctl(target_fd, FIONBIO, &zero);
printf("Waiting for PROMPT1 from target (%s) at 115200 baud\n",
target_ttydev);
read_loop();
free(compalstage_imgbuf);
if (for_boot_rom) {
cfsetispeed(&target_termios, B19200);
cfsetospeed(&target_termios, B19200);
if (tcsetattr(target_fd, TCSAFLUSH, &target_termios) < 0) {
perror("tcsetattr to switch baud rate");
exit(1);
}
}
return(1);
}