# HG changeset patch # User Michael Spacefalcon # Date 1402348059 0 # Node ID 7b3fd0e2a352c2287e23a410b6b8a22e5ee67c81 # Parent 3164604a6c703f53b62a06915bdae557ee6ce5db loadtools: compalstage support implemented in fc-iram diff -r 3164604a6c70 -r 7b3fd0e2a352 loadtools/Makefile --- a/loadtools/Makefile Mon Jun 09 06:10:01 2014 +0000 +++ b/loadtools/Makefile Mon Jun 09 21:07:39 2014 +0000 @@ -6,7 +6,8 @@ scripts/pirelli.init loadtool.help INSTBIN=/usr/local/bin INSTSCR=/usr/local/share/freecalypso -EXTRA_OBJ= + +EXTRA_OBJ= compalload.o IRAM_OBJS= defpath.o hexdecode.o hwparam.o hwparamstubs.o romload.o \ sercomm.o sertool.o srecreader.o ttypassthru.o ${EXTRA_OBJ} diff -r 3164604a6c70 -r 7b3fd0e2a352 loadtools/compalload.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/loadtools/compalload.c Mon Jun 09 21:07:39 2014 +0000 @@ -0,0 +1,222 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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); +} diff -r 3164604a6c70 -r 7b3fd0e2a352 loadtools/sertool.c --- a/loadtools/sertool.c Mon Jun 09 06:10:01 2014 +0000 +++ b/loadtools/sertool.c Mon Jun 09 21:07:39 2014 +0000 @@ -23,11 +23,17 @@ extern int optind; int c; - while ((c = getopt(argc, argv, "b:h:H:i:n")) != EOF) + while ((c = getopt(argc, argv, "b:c:C:h:H:i:n")) != EOF) switch (c) { case 'b': set_romload_baudrate(optarg); continue; + case 'c': + set_compalstage_short(optarg); + continue; + case 'C': + set_compalstage_fullpath(optarg); + continue; case 'h': read_hwparam_file_shortname(optarg); continue; @@ -52,6 +58,7 @@ iramimage.filename = argv[optind+1]; open_target_serial(); + perform_compal_stage(1); perform_romload(); tty_passthru(); exit(0);