FreeCalypso > hg > freecalypso-tools
view loadtools/compalload.c @ 590:026df5681bd3
Source-dirs: libpwon and openmoko subdirs documented
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Mon, 03 Feb 2020 19:38:41 +0000 |
parents | 8c011177adb9 |
children |
line wrap: on
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 <unistd.h> extern char default_compalstage_dir[]; extern char *target_ttydev; extern int target_fd; 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_compalstage_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() { 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); set_fixed_baudrate("115200"); ioctl(target_fd, FIONBIO, &zero); printf("Waiting for PROMPT1 from target (%s) at 115200 baud\n", target_ttydev); read_loop(); free(compalstage_imgbuf); return(1); }