FreeCalypso > hg > freecalypso-sw
comparison loadtools/compalload.c @ 379:7b3fd0e2a352
loadtools: compalstage support implemented in fc-iram
| author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
|---|---|
| date | Mon, 09 Jun 2014 21:07:39 +0000 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 378:3164604a6c70 | 379:7b3fd0e2a352 |
|---|---|
| 1 /* | |
| 2 * This module implements Compal's serial code loading protocol to load | |
| 3 * what we call compalstage, a piece of code that re-enables the Calypso | |
| 4 * boot ROM and allows us to use the same loadagent which we use on | |
| 5 * freedom-enabled target devices. | |
| 6 */ | |
| 7 | |
| 8 #include <sys/param.h> | |
| 9 #include <sys/file.h> | |
| 10 #include <sys/stat.h> | |
| 11 #include <sys/ioctl.h> | |
| 12 #include <stdio.h> | |
| 13 #include <stdlib.h> | |
| 14 #include <string.h> | |
| 15 #include <strings.h> | |
| 16 #include <termios.h> | |
| 17 #include <unistd.h> | |
| 18 | |
| 19 extern char default_helpers_dir[]; | |
| 20 extern char *target_ttydev; | |
| 21 extern int target_fd; | |
| 22 extern struct termios target_termios; | |
| 23 | |
| 24 static char compalstage_pathname[MAXPATHLEN]; | |
| 25 static u_char *compalstage_imgbuf; | |
| 26 static size_t compalstage_len, compalstage_totlen; | |
| 27 static int rx_state; | |
| 28 static u_char rx_msg[3]; | |
| 29 | |
| 30 void | |
| 31 set_compalstage_short(arg) | |
| 32 char *arg; | |
| 33 { | |
| 34 if (strcmp(arg, "none")) | |
| 35 sprintf(compalstage_pathname, "%s/compalstage-%s.bin", | |
| 36 default_helpers_dir, arg); | |
| 37 else | |
| 38 compalstage_pathname[0] = 0; | |
| 39 } | |
| 40 | |
| 41 void | |
| 42 set_compalstage_fullpath(arg) | |
| 43 char *arg; | |
| 44 { | |
| 45 strcpy(compalstage_pathname, arg); | |
| 46 } | |
| 47 | |
| 48 static void | |
| 49 compute_checksum() | |
| 50 { | |
| 51 size_t i, l; | |
| 52 u_char ck; | |
| 53 | |
| 54 ck = 0x02; | |
| 55 l = compalstage_len + 3; | |
| 56 for (i = 1; i < l; i++) | |
| 57 ck ^= compalstage_imgbuf[i]; | |
| 58 compalstage_imgbuf[l] = ck; | |
| 59 } | |
| 60 | |
| 61 static | |
| 62 handle_rx_msg() | |
| 63 { | |
| 64 static u_char download_cmd[7] = {0x1B, 0xF6, 0x02, 0x00, | |
| 65 0x52, 0x01, 0x53}; | |
| 66 | |
| 67 if (rx_msg[0] == 0x41 && rx_msg[1] == 0x01 && rx_msg[2] == 0x40) { | |
| 68 printf("Received PROMPT1, sending download command\n"); | |
| 69 write(target_fd, download_cmd, 7); | |
| 70 return(0); | |
| 71 } else if (rx_msg[0] == 0x41 && rx_msg[1] == 0x02 && rx_msg[2] == 0x43){ | |
| 72 printf("Received PROMPT2, sending download image\n"); | |
| 73 write(target_fd, compalstage_imgbuf, compalstage_totlen); | |
| 74 return(0); | |
| 75 } else if (rx_msg[0] == 0x41 && rx_msg[1] == 0x03 && rx_msg[2] == 0x42){ | |
| 76 printf("Received ACK; downloaded image should now be running!\n"); | |
| 77 return(1); | |
| 78 } else if (rx_msg[0] == 0x45 && rx_msg[1] == 0x53 && rx_msg[2] == 0x16){ | |
| 79 printf("Bootloader indicates bad checksum :-(\n"); | |
| 80 return(0); | |
| 81 } else if (rx_msg[0] == 0x41 && rx_msg[1] == 0x03 && rx_msg[2] == 0x57){ | |
| 82 printf("Bootloader indicates bad magic :-(\n"); | |
| 83 return(0); | |
| 84 } else { | |
| 85 printf("Unknown msg from bootloader: 1B F6 02 00 %02X %02X %02X\n", | |
| 86 rx_msg[0], rx_msg[1], rx_msg[2]); | |
| 87 return(0); | |
| 88 } | |
| 89 } | |
| 90 | |
| 91 static | |
| 92 handle_rx_byte(rxb) | |
| 93 { | |
| 94 switch (rx_state) { | |
| 95 case 0: | |
| 96 if (rxb == 0x1B) | |
| 97 rx_state = 1; | |
| 98 return(0); | |
| 99 case 1: | |
| 100 if (rxb == 0xF6) | |
| 101 rx_state = 2; | |
| 102 else if (rxb == 0x1B) | |
| 103 rx_state = 1; | |
| 104 else | |
| 105 rx_state = 0; | |
| 106 return(0); | |
| 107 case 2: | |
| 108 if (rxb == 0x02) | |
| 109 rx_state = 3; | |
| 110 else if (rxb == 0x1B) | |
| 111 rx_state = 1; | |
| 112 else | |
| 113 rx_state = 0; | |
| 114 return(0); | |
| 115 case 3: | |
| 116 if (rxb == 0x00) | |
| 117 rx_state = 4; | |
| 118 else if (rxb == 0x1B) | |
| 119 rx_state = 1; | |
| 120 else | |
| 121 rx_state = 0; | |
| 122 return(0); | |
| 123 case 4: | |
| 124 rx_msg[0] = rxb; | |
| 125 rx_state = 5; | |
| 126 return(0); | |
| 127 case 5: | |
| 128 rx_msg[1] = rxb; | |
| 129 rx_state = 6; | |
| 130 return(0); | |
| 131 case 6: | |
| 132 rx_msg[2] = rxb; | |
| 133 rx_state = 0; | |
| 134 return handle_rx_msg(); | |
| 135 } | |
| 136 } | |
| 137 | |
| 138 static void | |
| 139 read_loop() | |
| 140 { | |
| 141 u_char rdbuf[16]; | |
| 142 int cc, i; | |
| 143 | |
| 144 for (;;) { | |
| 145 cc = read(target_fd, rdbuf, sizeof rdbuf); | |
| 146 if (cc <= 0) { | |
| 147 fprintf(stderr, "EOF/error on target tty\n"); | |
| 148 exit(1); | |
| 149 } | |
| 150 for (i = 0; i < cc; i++) | |
| 151 if (handle_rx_byte(rdbuf[i])) | |
| 152 return; | |
| 153 } | |
| 154 } | |
| 155 | |
| 156 perform_compal_stage(for_boot_rom) | |
| 157 { | |
| 158 int fd; | |
| 159 struct stat st; | |
| 160 static int zero = 0; | |
| 161 | |
| 162 if (!compalstage_pathname[0]) | |
| 163 return(0); | |
| 164 fd = open(compalstage_pathname, O_RDONLY); | |
| 165 if (fd < 0) { | |
| 166 perror(compalstage_pathname); | |
| 167 exit(1); | |
| 168 } | |
| 169 fstat(fd, &st); | |
| 170 if (!S_ISREG(st.st_mode)) { | |
| 171 fprintf(stderr, "error: %s is not a regular file\n", | |
| 172 compalstage_pathname); | |
| 173 exit(1); | |
| 174 } | |
| 175 if (st.st_size > 65535) { | |
| 176 fprintf(stderr, | |
| 177 "error: %s exceed Compal download limit of 65535 bytes\n", | |
| 178 compalstage_pathname); | |
| 179 exit(1); | |
| 180 } | |
| 181 compalstage_len = st.st_size; | |
| 182 compalstage_totlen = compalstage_len + 4; | |
| 183 compalstage_imgbuf = malloc(compalstage_totlen); | |
| 184 if (!compalstage_imgbuf) { | |
| 185 perror("malloc"); | |
| 186 exit(1); | |
| 187 } | |
| 188 compalstage_imgbuf[0] = 0x02; | |
| 189 compalstage_imgbuf[1] = compalstage_len >> 8; | |
| 190 compalstage_imgbuf[2] = compalstage_len; | |
| 191 if (read(fd, compalstage_imgbuf+3, compalstage_len) != compalstage_len){ | |
| 192 fprintf(stderr, "%s: read error or short read\n", | |
| 193 compalstage_pathname); | |
| 194 exit(1); | |
| 195 } | |
| 196 close(fd); | |
| 197 compute_checksum(); | |
| 198 | |
| 199 printf("Using Compal stage image %s\n", compalstage_pathname); | |
| 200 cfsetispeed(&target_termios, B115200); | |
| 201 cfsetospeed(&target_termios, B115200); | |
| 202 if (tcsetattr(target_fd, TCSAFLUSH, &target_termios) < 0) { | |
| 203 perror("tcsetattr to switch baud rate"); | |
| 204 exit(1); | |
| 205 } | |
| 206 ioctl(target_fd, FIONBIO, &zero); | |
| 207 printf("Waiting for PROMPT1 from target (%s) at 115200 baud\n", | |
| 208 target_ttydev); | |
| 209 read_loop(); | |
| 210 free(compalstage_imgbuf); | |
| 211 | |
| 212 if (for_boot_rom) { | |
| 213 cfsetispeed(&target_termios, B19200); | |
| 214 cfsetospeed(&target_termios, B19200); | |
| 215 if (tcsetattr(target_fd, TCSAFLUSH, &target_termios) < 0) { | |
| 216 perror("tcsetattr to switch baud rate"); | |
| 217 exit(1); | |
| 218 } | |
| 219 } | |
| 220 | |
| 221 return(1); | |
| 222 } |
