comparison loadtools/romload.c @ 0:e7502631a0f9

initial import from freecalypso-sw rev 1033:5ab737ac3ad7
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 11 Jun 2016 00:13:35 +0000
parents
children 8c011177adb9
comparison
equal deleted inserted replaced
-1:000000000000 0:e7502631a0f9
1 /*
2 * This module implements the communication protocol for pushing our
3 * IRAM-loadable code to the Calypso ROM bootloader.
4 */
5
6 #include <sys/types.h>
7 #include <sys/ioctl.h>
8 #include <sys/time.h>
9 #include <sys/errno.h>
10 #include <stdint.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <strings.h>
14 #include <termios.h>
15 #include <unistd.h>
16 #include "baudrate.h"
17 #include "srecreader.h"
18
19 extern int errno;
20
21 extern char *target_ttydev;
22 extern int target_fd;
23 extern struct baudrate baud_rate_table[];
24 extern struct baudrate *find_baudrate_by_name();
25
26 struct srecreader iramimage;
27 struct baudrate *romload_baud_rate = baud_rate_table; /* 1st entry default */
28
29 /* global var always defined, but does anything only for GTA0x_AP_BUILD */
30 int gta_modem_poweron = 1;
31
32 static int beacon_interval = 13; /* in milliseconds */
33
34 static u_char beacon_cmd[2] = {'<', 'i'};
35
36 static u_char param_cmd[11] = {'<', 'p',
37 0x00, /* baud rate select code (115200) */
38 0x00, /* DPLL setup: leave it off like on power-up, */
39 /* OsmocomBB does the same thing */
40 0x00, 0x04, /* chip select timing (WS) settings */
41 /* our setting matches both OsmocomBB */
42 /* and what the ROM runs with */
43 /* before receiving this command */
44 0x22, /* FFFF:F900 register config, low byte */
45 /* OsmocomBB sends 0x00 here, but I've chosen */
46 /* 0x22 to match the setting of this register */
47 /* used by the boot ROM before this command. */
48 0x00, 0x01, 0xD4, 0xC0 /* UART timeout */
49 /* I've chosen the same value as what the */
50 /* boot ROM runs with before getting this cmd */
51 };
52
53 static u_char write_cmd[10] = {'<', 'w', 0x01, 0x01, 0x00};
54 static u_char cksum_cmd[3] = {'<', 'c'};
55 static u_char branch_cmd[6] = {'<', 'b'};
56
57 #define INTERMEDIATE_TIMEOUT 500 /* ms to wait for responses */
58 #define SERIAL_FLUSH_DELAY 200 /* also in ms */
59
60 /*
61 * The following function should be called by command line option
62 * parsers upon encountering the -i option.
63 */
64 set_beacon_interval(arg)
65 char *arg;
66 {
67 int i;
68
69 i = atoi(arg);
70 if (i < 2 || i > 500) {
71 fprintf(stderr, "invalid -i argument specified\n");
72 exit(1);
73 }
74 beacon_interval = i;
75 }
76
77 /*
78 * The following function should be called by command line option
79 * parsers upon encountering the -b option.
80 */
81 set_romload_baudrate(arg)
82 char *arg;
83 {
84 struct baudrate *br;
85
86 br = find_baudrate_by_name(arg);
87 if (!br)
88 exit(1); /* error msg already printed */
89 if (br->bootrom_code < 0) {
90 fprintf(stderr,
91 "baud rate of %s is not supported by the Calypso boot ROM\n",
92 br->name);
93 exit(1);
94 }
95 romload_baud_rate = br;
96 }
97
98 /*
99 * The following functions alter some of the parameters sent to the
100 * boot ROM in the <p command.
101 */
102 set_romload_pll_conf(byte)
103 {
104 param_cmd[3] = byte;
105 }
106
107 set_romload_rhea_cntl(byte)
108 {
109 param_cmd[6] = byte;
110 }
111
112 static int
113 expect_response(timeout)
114 {
115 char buf[2];
116 fd_set fds;
117 struct timeval tv;
118 int pass, cc;
119
120 for (pass = 0; pass < 2; ) {
121 FD_ZERO(&fds);
122 FD_SET(target_fd, &fds);
123 tv.tv_sec = 0;
124 tv.tv_usec = timeout * 1000;
125 cc = select(target_fd+1, &fds, NULL, NULL, &tv);
126 if (cc < 0) {
127 if (errno == EINTR)
128 continue;
129 perror("select");
130 exit(1);
131 }
132 if (cc < 1)
133 return(-1);
134 cc = read(target_fd, buf + pass, 2 - pass);
135 if (cc <= 0) {
136 perror("read after successful select");
137 exit(1);
138 }
139 if (pass == 0 && buf[0] != '>')
140 continue;
141 pass += cc;
142 }
143 return(buf[1]);
144 }
145
146 static
147 send_beacons()
148 {
149 printf("Sending beacons to %s\n", target_ttydev);
150 #ifdef GTA0x_AP_BUILD
151 if (gta_modem_poweron)
152 fork_gta_modem_poweron();
153 #endif
154 do
155 write(target_fd, beacon_cmd, sizeof beacon_cmd);
156 while (expect_response(beacon_interval) != 'i');
157 return 0;
158 }
159
160 static uint32_t
161 compute_block_cksum()
162 {
163 uint32_t sum;
164 int i, llen;
165
166 sum = iramimage.datalen + 5;
167 llen = iramimage.datalen + 4;
168 for (i = 0; i < llen; i++)
169 sum += iramimage.record[i+1];
170 return sum;
171 }
172
173 perform_romload()
174 {
175 int resp;
176 uint16_t image_cksum;
177 unsigned long rec_count;
178 static int zero = 0;
179
180 if (open_srec_file(&iramimage) < 0)
181 exit(1);
182 ioctl(target_fd, FIONBIO, &zero);
183 send_beacons();
184 printf("Got beacon response, attempting download\n");
185
186 usleep(SERIAL_FLUSH_DELAY * 1000);
187 tcflush(target_fd, TCIFLUSH);
188 param_cmd[2] = romload_baud_rate->bootrom_code;
189 write(target_fd, param_cmd, sizeof param_cmd);
190 resp = expect_response(INTERMEDIATE_TIMEOUT);
191 if (resp != 'p') {
192 if (resp < 0)
193 fprintf(stderr, "No response to <p command\n");
194 else if (isprint(resp))
195 fprintf(stderr,
196 "Got >%c in response to <p command; expected >p\n",
197 resp);
198 else
199 fprintf(stderr,
200 "Got > %02X in response to <p command; expected >p\n",
201 resp);
202 exit(1);
203 }
204 printf("<p command successful, switching to %s baud\n",
205 romload_baud_rate->name);
206 switch_baud_rate(romload_baud_rate);
207 usleep(SERIAL_FLUSH_DELAY * 1000);
208 tcflush(target_fd, TCIFLUSH);
209
210 image_cksum = 0;
211 for (rec_count = 0; ; ) {
212 if (read_s_record(&iramimage) < 0)
213 exit(1);
214 switch (iramimage.record_type) {
215 case '0':
216 if (iramimage.lineno == 1)
217 continue;
218 fprintf(stderr,
219 "%s: S0 record found in line %d (expected in line 1 only)\n",
220 iramimage.filename, iramimage.lineno);
221 exit(1);
222 case '3':
223 case '7':
224 if (s3s7_get_addr_data(&iramimage) < 0)
225 exit(1);
226 break;
227 default:
228 fprintf(stderr,
229 "%s line %d: S%c record type not supported\n",
230 iramimage.filename, iramimage.lineno,
231 iramimage.record_type);
232 exit(1);
233 }
234 if (iramimage.record_type == '7')
235 break;
236 /* must be S3 */
237 if (iramimage.datalen < 1) {
238 fprintf(stderr,
239 "%s line %d: S3 record has zero data length\n",
240 iramimage.filename, iramimage.lineno);
241 exit(1);
242 }
243 /* form <w command */
244 if (!rec_count)
245 printf("Sending image payload\n");
246 write_cmd[5] = iramimage.datalen;
247 bcopy(iramimage.record + 1, write_cmd + 6, 4);
248 write(target_fd, write_cmd, sizeof write_cmd);
249 write(target_fd, iramimage.record + 5, iramimage.datalen);
250 /* update our checksum accumulator */
251 image_cksum += ~compute_block_cksum() & 0xFF;
252 /* collect response */
253 resp = expect_response(INTERMEDIATE_TIMEOUT);
254 if (resp != 'w') {
255 fprintf(stderr, "Block #%lu: ", rec_count);
256 if (resp < 0)
257 fprintf(stderr, "No response to <w command\n");
258 else if (isprint(resp))
259 fprintf(stderr,
260 "Got >%c in response to <w command; expected >w\n",
261 resp);
262 else
263 fprintf(stderr,
264 "Got > %02X in response to <w command; expected >w\n",
265 resp);
266 exit(1);
267 }
268 putchar('.');
269 fflush(stdout);
270 rec_count++;
271 }
272 /* got S7 */
273 fclose(iramimage.openfile);
274 if (!rec_count) {
275 fprintf(stderr,
276 "%s line %d: S7 without any preceding S3 data records\n",
277 iramimage.filename, iramimage.lineno);
278 exit(1);
279 }
280
281 /* send <c */
282 printf("Sending checksum\n");
283 cksum_cmd[2] = ~image_cksum & 0xFF;
284 write(target_fd, cksum_cmd, sizeof cksum_cmd);
285 resp = expect_response(INTERMEDIATE_TIMEOUT);
286 if (resp != 'c') {
287 if (resp < 0)
288 fprintf(stderr, "No response to <c command\n");
289 else if (isprint(resp))
290 fprintf(stderr,
291 "Got >%c in response to <c command; expected >c\n",
292 resp);
293 else
294 fprintf(stderr,
295 "Got > %02X in response to <c command; expected >c\n",
296 resp);
297 exit(1);
298 }
299 printf("<c command successful, sending <b\n");
300
301 bcopy(iramimage.record + 1, branch_cmd + 2, 4);
302 write(target_fd, branch_cmd, sizeof branch_cmd);
303 resp = expect_response(INTERMEDIATE_TIMEOUT);
304 if (resp != 'b') {
305 if (resp < 0)
306 fprintf(stderr, "No response to <b command\n");
307 else if (isprint(resp))
308 fprintf(stderr,
309 "Got >%c in response to <b command; expected >b\n",
310 resp);
311 else
312 fprintf(stderr,
313 "Got > %02X in response to <b command; expected >b\n",
314 resp);
315 exit(1);
316 }
317 printf("<b command successful: downloaded image should now be running!\n");
318 return(0);
319 }