Use osmo_fd_*_{disable,enable}
[osmocom-bb.git] / src / host / osmocon / osmocon.c
blobd49c3fdffbbada213c569e4d59e0ee631ed41e66
1 /* osmocon */
3 /* (C) 2010,2018 by Harald Welte <laforge@gnumonks.org>
4 * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
5 * (C) 2010 by Steve Markgraf <steve@steve-m.de>
7 * All Rights Reserved
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 #include <ctype.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <stdint.h>
31 #include <fcntl.h>
32 #include <errno.h>
33 #include <termios.h>
34 #include <sys/ioctl.h>
35 #include <sys/types.h>
36 #include <sys/socket.h>
37 #include <sys/stat.h>
38 #include <sys/un.h>
40 #include <sercomm.h>
42 #include <osmocom/core/linuxlist.h>
43 #include <osmocom/core/select.h>
44 #include <osmocom/core/serial.h>
45 #include <osmocom/core/talloc.h>
46 #include <osmocom/core/timer.h>
47 #include <osmocom/core/application.h>
48 #include <osmocom/core/socket.h>
50 #include <arpa/inet.h>
52 #define MODEM_BAUDRATE B115200
53 #define MAX_DNLOAD_SIZE 0xFFFF
54 #define MAX_HDR_SIZE 128
55 #define MAGIC_OFFSET 0x3be2
57 #define DEFAULT_BEACON_INTERVAL 50000
58 #define ROMLOAD_INIT_BAUDRATE B19200
59 #define ROMLOAD_DL_BAUDRATE B115200
60 #define ROMLOAD_BLOCK_HDR_LEN 10
61 #define ROMLOAD_ADDRESS 0x820000
63 #define MTK_INIT_BAUDRATE B19200
64 #define MTK_ADDRESS 0x40001400
65 #define MTK_BLOCK_SIZE 1024
67 struct tool_server *tool_server_for_dlci[256];
69 /**
70 * a connection from some other tool
72 struct tool_connection {
73 struct tool_server *server;
74 struct llist_head entry;
75 struct osmo_fd fd;
78 /**
79 * server for a tool
81 struct tool_server {
82 struct osmo_fd bfd;
83 uint8_t dlci;
84 struct llist_head connections;
88 enum dnload_state {
89 WAITING_PROMPT1,
90 WAITING_PROMPT2,
91 DOWNLOADING,
94 enum romload_state {
95 WAITING_IDENTIFICATION,
96 WAITING_PARAM_ACK,
97 SENDING_BLOCKS,
98 SENDING_LAST_BLOCK,
99 LAST_BLOCK_SENT,
100 WAITING_BLOCK_ACK,
101 WAITING_CHECKSUM_ACK,
102 WAITING_BRANCH_ACK,
103 FINISHED,
106 enum mtk_state {
107 MTK_INIT_1,
108 MTK_INIT_2,
109 MTK_INIT_3,
110 MTK_INIT_4,
111 MTK_WAIT_WRITE_ACK,
112 MTK_WAIT_ADDR_ACK,
113 MTK_WAIT_SIZE_ACK,
114 MTK_SENDING_BLOCKS,
115 MTK_WAIT_BRANCH_CMD_ACK,
116 MTK_WAIT_BRANCH_ADDR_ACK,
117 MTK_FINISHED,
120 enum dnload_mode {
121 MODE_C123,
122 MODE_C123xor,
123 MODE_C140,
124 MODE_C140xor,
125 MODE_C155,
126 MODE_ROMLOAD,
127 MODE_MTK,
128 MODE_INVALID,
131 struct dnload {
132 enum dnload_state state;
133 enum romload_state romload_state;
134 enum mtk_state mtk_state;
135 enum dnload_mode mode, previous_mode;
136 struct osmo_fd serial_fd;
137 char *filename;
139 int expect_hdlc;
140 int do_chainload;
142 int dump_rx;
143 int dump_tx;
144 int beacon_interval;
146 /* data to be downloaded */
147 uint8_t *data;
148 int data_len;
150 uint8_t *write_ptr;
152 /* romload: block to be downloaded */
153 uint8_t *block;
154 int block_len;
155 uint8_t block_number;
156 uint16_t block_payload_size;
157 int romload_dl_checksum;
158 uint8_t *block_ptr;
159 uint8_t load_address[4];
161 uint8_t mtk_send_size[4];
162 int block_count;
163 int echo_bytecount;
165 struct tool_server layer2_server;
166 struct tool_server loader_server;
170 static struct dnload dnload;
171 static struct osmo_timer_list tick_timer;
173 /* Compal ramloader specific */
174 static const uint8_t phone_prompt1[] = { 0x1b, 0xf6, 0x02, 0x00, 0x41, 0x01, 0x40 };
175 static const uint8_t dnload_cmd[] = { 0x1b, 0xf6, 0x02, 0x00, 0x52, 0x01, 0x53 };
176 static const uint8_t phone_prompt2[] = { 0x1b, 0xf6, 0x02, 0x00, 0x41, 0x02, 0x43 };
177 static const uint8_t phone_ack[] = { 0x1b, 0xf6, 0x02, 0x00, 0x41, 0x03, 0x42 };
178 static const uint8_t phone_nack_magic[]= { 0x1b, 0xf6, 0x02, 0x00, 0x41, 0x03, 0x57 };
179 static const uint8_t phone_nack[] = { 0x1b, 0xf6, 0x02, 0x00, 0x45, 0x53, 0x16 };
180 static const uint8_t ftmtool[] = { 0x66, 0x74, 0x6d, 0x74, 0x6f, 0x6f, 0x6c };
181 static const uint8_t phone_magic[] = { 0x31, 0x30, 0x30, 0x33 }; /* "1003" */
183 /* The C123 has a hard-coded check inside the ramloader that requires the
184 * following bytes to be always the first four bytes of the image */
185 static const uint8_t data_hdr_c123[] = { 0xee, 0x4c, 0x9f, 0x63 };
187 /* The C155 doesn't have some strange restriction on what the first four bytes
188 * have to be, but it starts the ramloader in THUMB mode. We use the following
189 * four bytes to switch back to ARM mode:
190 800100: 4778 bx pc
191 800102: 46c0 nop ; (mov r8, r8)
193 static const uint8_t data_hdr_c155[] = { 0x78, 0x47, 0xc0, 0x46 };
195 /* small loader that enables the bootrom and executes the TI romloader:
196 * _start:
197 * ldr r1, =0x000a0000
198 * wait:
199 * subs r1, r1, #1
200 * bne wait
201 * ldr r1, =0xfffffb10
202 * ldr r2, =0x100
203 * strh r2, [r1]
204 * ldr pc, =0x0
206 static const uint8_t chainloader[] = {
207 0x0a, 0x18, 0xa0, 0xe3, 0x01, 0x10, 0x51, 0xe2, 0xfd, 0xff, 0xff,
208 0x1a, 0x08, 0x10, 0x9f, 0xe5, 0x01, 0x2c, 0xa0, 0xe3, 0xb0, 0x20,
209 0xc1, 0xe1, 0x00, 0xf0, 0xa0, 0xe3, 0x10, 0xfb, 0xff, 0xff,
212 /* Calypso romloader specific */
213 static const uint8_t romload_ident_cmd[] = { 0x3c, 0x69 }; /* <i */
214 static const uint8_t __attribute__((__unused__)) romload_abort_cmd[] = { 0x3c, 0x61 }; /* <a */
215 static const uint8_t romload_write_cmd[] = { 0x3c, 0x77 }; /* <w */
216 static const uint8_t romload_checksum_cmd[] = { 0x3c, 0x63 }; /* <c */
217 static const uint8_t romload_branch_cmd[] = { 0x3c, 0x62 }; /* <b */
218 static const uint8_t romload_ident_ack[] = { 0x3e, 0x69 }; /* >i */
219 static const uint8_t romload_param_ack[] = { 0x3e, 0x70 }; /* >p */
220 static const uint8_t __attribute__((__unused__)) romload_param_nack[] = { 0x3e, 0x50 }; /* >P */
221 static const uint8_t romload_block_ack[] = { 0x3e, 0x77 }; /* >w */
222 static const uint8_t romload_block_nack[] = { 0x3e, 0x57 }; /* >W */
223 static const uint8_t romload_checksum_ack[] = { 0x3e, 0x63 }; /* >c */
224 static const uint8_t romload_checksum_nack[] = { 0x3e, 0x43 }; /* >C */
225 static const uint8_t romload_branch_ack[] = { 0x3e, 0x62 }; /* >b */
226 static const uint8_t romload_branch_nack[] = { 0x3e, 0x42 }; /* >B */
228 /* romload_param: {"<p", uint8_t baudrate, uint8_t dpll, uint16_t memory_config,
229 * uint8_t strobe_af, uint32_t uart_timeout} */
231 static const uint8_t romload_param[] = { 0x3c, 0x70, 0x00, 0x00, 0x00, 0x04,
232 0x00, 0x00, 0x00, 0x00, 0x00 };
234 /* MTK romloader specific */
235 static const uint8_t mtk_init_cmd[] = { 0xa0, 0x0a, 0x50, 0x05 };
236 static const uint8_t mtk_init_resp[] = { 0x5f, 0xf5, 0xaf, 0xfa };
237 static const uint8_t mtk_command[] = { 0xa1, 0xa2, 0xa4, 0xa8 };
239 static void beacon_timer_cb(void *p)
241 int rc;
243 if (dnload.romload_state == WAITING_IDENTIFICATION) {
244 rc = write(dnload.serial_fd.fd, romload_ident_cmd,
245 sizeof(romload_ident_cmd));
247 if (!(rc == sizeof(romload_ident_cmd)))
248 printf("Error sending identification beacon\n");
250 osmo_timer_schedule(p, 0, dnload.beacon_interval);
254 static void mtk_timer_cb(void *p)
256 int rc;
258 if (dnload.mtk_state == MTK_INIT_1) {
259 printf("Sending MTK romloader beacon...\n");
260 rc = write(dnload.serial_fd.fd, &mtk_init_cmd[0], 1);
262 if (!(rc == 1))
263 printf("Error sending identification beacon\n");
265 osmo_timer_schedule(p, 0, dnload.beacon_interval);
269 /* Read the to-be-downloaded file, prepend header and length, append XOR sum */
270 int read_file(const char *filename, int chainload)
272 int fd, rc, i;
273 struct stat st;
274 const uint8_t *hdr = NULL;
275 int payload_size;
276 int hdr_len = 0;
277 uint8_t *file_data;
278 uint16_t tot_len;
279 uint8_t nibble;
280 uint8_t running_xor = 0x02;
282 if (!chainload) {
283 fd = open(filename, O_RDONLY);
284 if (fd < 0) {
285 perror("opening file");
286 exit(1);
289 rc = fstat(fd, &st);
290 if (rc < 0) {
291 perror("fstat");
292 close(fd);
293 return -EIO;
295 if ((st.st_size > MAX_DNLOAD_SIZE) && (dnload.mode != MODE_ROMLOAD)) {
296 fprintf(stderr, "The maximum file size is 64kBytes (%u bytes)\n",
297 MAX_DNLOAD_SIZE);
298 close(fd);
299 return -EFBIG;
301 } else {
302 st.st_size = sizeof(chainloader);
305 free(dnload.data);
306 dnload.data = NULL;
308 if (dnload.mode == MODE_C140 || dnload.mode == MODE_C140xor) {
309 if (st.st_size < (MAGIC_OFFSET + sizeof(phone_magic)))
310 payload_size = MAGIC_OFFSET + sizeof(phone_magic);
311 else {
312 printf("\nThe filesize is larger than 15kb, code on "
313 "the magic address will be overwritten!\nUse "
314 "loader.bin and upload the application with "
315 "osmoload instead!\n\n");
316 payload_size = st.st_size;
318 } else
319 payload_size = st.st_size;
321 dnload.data = malloc(MAX_HDR_SIZE + payload_size);
323 if (!dnload.data) {
324 if (!chainload)
325 close(fd);
326 fprintf(stderr, "No memory\n");
327 return -ENOMEM;
330 /* copy in the header, if any */
331 switch (dnload.mode) {
332 case MODE_C155:
333 hdr = data_hdr_c155;
334 hdr_len = sizeof(data_hdr_c155);
335 break;
336 case MODE_C140:
337 case MODE_C140xor:
338 case MODE_C123:
339 case MODE_C123xor:
340 hdr = data_hdr_c123;
341 hdr_len = sizeof(data_hdr_c123);
342 break;
343 case MODE_ROMLOAD:
344 break;
345 default:
346 break;
349 if (hdr && hdr_len)
350 memcpy(dnload.data, hdr, hdr_len);
352 /* 2 bytes for length + header */
353 file_data = dnload.data + 2 + hdr_len;
355 /* write the length, keep running XOR */
356 tot_len = hdr_len + payload_size;
357 nibble = tot_len >> 8;
358 dnload.data[0] = nibble;
359 running_xor ^= nibble;
360 nibble = tot_len & 0xff;
361 dnload.data[1] = nibble;
362 running_xor ^= nibble;
364 if (hdr_len && hdr) {
365 memcpy(dnload.data+2, hdr, hdr_len);
367 for (i = 0; i < hdr_len; i++)
368 running_xor ^= hdr[i];
371 if (!chainload) {
372 rc = read(fd, file_data, st.st_size);
373 if (rc < 0) {
374 perror("error reading file\n");
375 free(dnload.data);
376 dnload.data = NULL;
377 close(fd);
378 return -EIO;
380 if (rc < st.st_size) {
381 free(dnload.data);
382 dnload.data = NULL;
383 close(fd);
384 fprintf(stderr, "Short read of file (%d < %d)\n",
385 rc, (int)st.st_size);
386 return -EIO;
388 close(fd);
389 } else {
390 memcpy(file_data, chainloader, st.st_size);
393 dnload.data_len = (file_data+payload_size) - dnload.data;
395 /* fill memory between data end and magic, add magic */
396 if(dnload.mode == MODE_C140 || dnload.mode == MODE_C140xor) {
397 if (st.st_size < MAGIC_OFFSET)
398 memset(file_data + st.st_size, 0x00,
399 payload_size - st.st_size);
400 memcpy(dnload.data + MAGIC_OFFSET, phone_magic,
401 sizeof(phone_magic));
404 /* calculate XOR sum */
405 for (i = 0; i < payload_size; i++)
406 running_xor ^= file_data[i];
408 dnload.data[dnload.data_len++] = running_xor;
410 /* initialize write pointer to start of data */
411 dnload.write_ptr = dnload.data;
413 printf("read_file(%s): file_size=%u, hdr_len=%u, dnload_len=%u\n",
414 chainload ? "chainloader" : filename, (int)st.st_size,
415 hdr_len, dnload.data_len);
417 return 0;
420 static void osmocon_osmo_hexdump(const uint8_t *data, unsigned int len)
422 int n;
424 for (n=0; n < len; n++)
425 printf("%02x ", data[n]);
426 printf(" ");
427 for (n=0; n < len; n++)
428 if (isprint(data[n]))
429 putchar(data[n]);
430 else
431 putchar('.');
432 printf("\n");
435 static int romload_prepare_block(void)
437 int i;
439 int block_checksum = 5;
440 int remaining_bytes;
441 int fill_bytes;
442 uint8_t *block_data;
443 uint32_t block_address;
445 dnload.block_len = ROMLOAD_BLOCK_HDR_LEN + dnload.block_payload_size;
447 /* if first block, allocate memory */
448 if (!dnload.block_number) {
449 dnload.block = malloc(dnload.block_len);
450 if (!dnload.block) {
451 fprintf(stderr, "No memory\n");
452 return -ENOMEM;
454 dnload.romload_dl_checksum = 0;
455 /* initialize write pointer to start of data */
456 dnload.write_ptr = dnload.data;
459 block_address = ROMLOAD_ADDRESS +
460 (dnload.block_number * dnload.block_payload_size);
462 /* prepare our block header (10 bytes) */
463 memcpy(dnload.block, romload_write_cmd, sizeof(romload_write_cmd));
464 dnload.block[2] = 0x01; /* block index */
465 /* should normally be the block number, but hangs when sending !0x01 */
466 dnload.block[3] = 0x01; /* dnload.block_number+1 */
467 dnload.block[4] = (dnload.block_payload_size >> 8) & 0xff;
468 dnload.block[5] = dnload.block_payload_size & 0xff;
469 dnload.block[6] = (block_address >> 24) & 0xff;
470 dnload.block[7] = (block_address >> 16) & 0xff;
471 dnload.block[8] = (block_address >> 8) & 0xff;
472 dnload.block[9] = block_address & 0xff;
474 block_data = dnload.block + ROMLOAD_BLOCK_HDR_LEN;
475 dnload.write_ptr = dnload.data + 2 +
476 (dnload.block_payload_size * dnload.block_number);
478 remaining_bytes = dnload.data_len - 3 -
479 (dnload.block_payload_size * dnload.block_number);
481 memcpy(block_data, dnload.write_ptr, OSMO_MIN(dnload.block_payload_size, remaining_bytes));
483 if (remaining_bytes <= dnload.block_payload_size) {
484 fill_bytes = (dnload.block_payload_size - remaining_bytes);
485 memset(block_data + remaining_bytes, 0x00, fill_bytes);
486 dnload.romload_state = SENDING_LAST_BLOCK;
487 } else {
488 dnload.romload_state = SENDING_BLOCKS;
491 /* block checksum is lsb of ~(5 + block_size_lsb + all bytes of
492 * block_address + all data bytes) */
493 for (i = 5; i < ROMLOAD_BLOCK_HDR_LEN + dnload.block_payload_size; i++)
494 block_checksum += dnload.block[i];
496 /* checksum is lsb of ~(sum of LSBs of all block checksums) */
497 dnload.romload_dl_checksum += ~(block_checksum) & 0xff;
499 /* initialize block pointer to start of block */
500 dnload.block_ptr = dnload.block;
502 dnload.block_number++;
503 osmo_fd_update_when(&dnload.serial_fd, 0, OSMO_FD_READ | OSMO_FD_WRITE);
504 return 0;
507 static int mtk_prepare_block(void)
509 int i;
510 int remaining_bytes;
511 int fill_bytes;
512 uint8_t *block_data;
513 uint8_t tmp_byteswap;
514 uint32_t tmp_size;
516 dnload.block_len = MTK_BLOCK_SIZE;
517 dnload.echo_bytecount = 0;
519 /* if first block, allocate memory */
520 if (!dnload.block_number) {
521 dnload.block = malloc(dnload.block_len);
522 if (!dnload.block) {
523 fprintf(stderr, "No memory\n");
524 return -ENOMEM;
527 /* calculate the number of blocks we need to send */
528 dnload.block_count = (dnload.data_len-3) / MTK_BLOCK_SIZE;
529 /* add one more block if no multiple of blocksize */
530 if((dnload.data_len-3) % MTK_BLOCK_SIZE)
531 dnload.block_count++;
533 /* divide by 2, since we have to tell the mtk loader the size
534 * as count of uint16 (odd transfer sizes are not possible) */
535 tmp_size = (dnload.block_count * MTK_BLOCK_SIZE)/2;
536 dnload.mtk_send_size[0] = (tmp_size >> 24) & 0xff;
537 dnload.mtk_send_size[1] = (tmp_size >> 16) & 0xff;
538 dnload.mtk_send_size[2] = (tmp_size >> 8) & 0xff;
539 dnload.mtk_send_size[3] = tmp_size & 0xff;
541 /* initialize write pointer to start of data */
542 dnload.write_ptr = dnload.data;
545 block_data = dnload.block;
546 dnload.write_ptr = dnload.data + 2 +
547 (dnload.block_len * dnload.block_number);
549 remaining_bytes = dnload.data_len - 3 -
550 (dnload.block_len * dnload.block_number);
552 memcpy(block_data, dnload.write_ptr, MTK_BLOCK_SIZE);
554 if (remaining_bytes <= MTK_BLOCK_SIZE) {
555 fill_bytes = (MTK_BLOCK_SIZE - remaining_bytes);
556 printf("Preparing the last block, filling %i bytes\n",
557 fill_bytes);
558 memset(block_data + remaining_bytes, 0x00, fill_bytes);
559 dnload.romload_state = SENDING_LAST_BLOCK;
560 } else {
561 dnload.romload_state = SENDING_BLOCKS;
562 printf("Preparing block %i\n", dnload.block_number+1);
565 /* for the mtk romloader we need to swap MSB <-> LSB */
566 for (i = 0; i < dnload.block_len; i += 2) {
567 tmp_byteswap = dnload.block[i];
568 dnload.block[i] = dnload.block[i+1];
569 dnload.block[i+1] = tmp_byteswap;
572 /* initialize block pointer to start of block */
573 dnload.block_ptr = dnload.block;
575 dnload.block_number++;
576 return 0;
579 static int handle_write_block(void)
581 int bytes_left, write_len, rc;
582 int progress = 100 * (dnload.block_number * dnload.block_payload_size)
583 / dnload.data_len;
585 if (dnload.block_ptr >= dnload.block + dnload.block_len) {
586 printf("Progress: %i%%\r", progress);
587 fflush(stdout);
588 dnload.write_ptr = dnload.data;
589 osmo_fd_write_disable(&dnload.serial_fd);
590 if (dnload.romload_state == SENDING_LAST_BLOCK) {
591 dnload.romload_state = LAST_BLOCK_SENT;
592 printf("Finished, sent %i blocks in total\n",
593 dnload.block_number);
594 } else {
595 dnload.romload_state = WAITING_BLOCK_ACK;
598 return 0;
601 /* try to write a maximum of block_len bytes */
602 bytes_left = (dnload.block + dnload.block_len) - dnload.block_ptr;
603 write_len = dnload.block_len;
604 if (bytes_left < dnload.block_len)
605 write_len = bytes_left;
607 rc = write(dnload.serial_fd.fd, dnload.block_ptr, write_len);
608 if (rc < 0) {
609 perror("Error during write");
610 return rc;
613 dnload.block_ptr += rc;
615 return 0;
618 #define WRITE_BLOCK 4096
620 static int handle_write_dnload(void)
622 int bytes_left, write_len, rc;
623 uint8_t xor_init = 0x02;
625 printf("handle_write(): ");
626 if (dnload.write_ptr == dnload.data) {
627 /* no bytes have been transferred yet */
628 switch (dnload.mode) {
629 case MODE_C155:
630 case MODE_C140xor:
631 case MODE_C123xor:
632 rc = write(dnload.serial_fd.fd, &xor_init, 1);
633 OSMO_ASSERT(rc == 1);
634 break;
635 default:
636 break;
638 } else if (dnload.write_ptr >= dnload.data + dnload.data_len) {
639 printf("finished\n");
640 dnload.write_ptr = dnload.data;
641 osmo_fd_write_disable(&dnload.serial_fd);
642 return 1;
645 /* try to write a maximum of WRITE_BLOCK bytes */
646 bytes_left = (dnload.data + dnload.data_len) - dnload.write_ptr;
647 write_len = WRITE_BLOCK;
648 if (bytes_left < WRITE_BLOCK)
649 write_len = bytes_left;
651 rc = write(dnload.serial_fd.fd, dnload.write_ptr, write_len);
652 if (rc < 0) {
653 perror("Error during write");
654 return rc;
656 OSMO_ASSERT(rc == write_len);
658 dnload.write_ptr += rc;
660 printf("%u bytes (%lu/%u)\n", rc, dnload.write_ptr - dnload.data,
661 dnload.data_len);
663 return 0;
666 static int handle_sercomm_write(void)
668 uint8_t buffer[256];
669 int i, count = 0, end = 0;
671 for (i = 0; i < sizeof(buffer); i++) {
672 if (sercomm_drv_pull(&buffer[i]) == 0) {
673 end = 1;
674 break;
676 count++;
679 if (count) {
680 if (write(dnload.serial_fd.fd, buffer, count) != count)
681 perror("short write");
684 if (end)
685 osmo_fd_write_disable(&dnload.serial_fd);
687 return 0;
690 static int handle_write(void)
692 /* TODO: simplify this again (global state: downloading, sercomm) */
693 switch (dnload.mode) {
694 case MODE_ROMLOAD:
695 switch (dnload.romload_state) {
696 case SENDING_BLOCKS:
697 case SENDING_LAST_BLOCK:
698 return handle_write_block();
699 default:
700 return handle_sercomm_write();
702 break;
703 case MODE_MTK:
704 switch (dnload.mtk_state) {
705 case MTK_SENDING_BLOCKS:
706 return handle_write_block();
707 default:
708 return handle_sercomm_write();
710 break;
711 default:
712 switch (dnload.state) {
713 case DOWNLOADING:
714 return handle_write_dnload();
715 default:
716 return handle_sercomm_write();
720 return 0;
723 static uint8_t buffer[sizeof(phone_prompt1)];
724 static uint8_t *bufptr = buffer;
726 static void hdlc_send_to_phone(uint8_t dlci, uint8_t *data, int len)
728 struct msgb *msg;
729 uint8_t *dest;
731 if(dnload.dump_tx) {
732 printf("hdlc_send(dlci=%u): ", dlci);
733 osmocon_osmo_hexdump(data, len);
736 if (len > 512) {
737 fprintf(stderr, "Too much data to send. %u\n", len);
738 return;
741 /* push the message into the stack */
742 msg = sercomm_alloc_msgb(512);
743 if (!msg) {
744 fprintf(stderr, "Failed to create data for the frame.\n");
745 return;
748 /* copy the data */
749 dest = msgb_put(msg, len);
750 memcpy(dest, data, len);
752 sercomm_sendmsg(dlci, msg);
754 osmo_fd_write_enable(&dnload.serial_fd);
757 static void hdlc_console_cb(uint8_t dlci, struct msgb *msg)
759 write(1, msg->data, msg->len);
760 msgb_free(msg);
763 static void hdlc_tool_cb(uint8_t dlci, struct msgb *msg)
765 struct tool_server *srv = tool_server_for_dlci[dlci];
767 if(dnload.dump_rx) {
768 printf("hdlc_recv(dlci=%u): ", dlci);
769 osmocon_osmo_hexdump(msg->data, msg->len);
772 if(srv) {
773 struct tool_connection *con;
774 uint16_t *len;
776 len = (uint16_t *) msgb_push(msg, 2);
777 *len = htons(msg->len - sizeof(*len));
779 llist_for_each_entry(con, &srv->connections, entry) {
780 if (write(con->fd.fd, msg->data, msg->len) != msg->len) {
781 fprintf(stderr,
782 "Failed to write msg to the socket..\n");
783 continue;
788 msgb_free(msg);
791 static int handle_buffer(int buf_used_len)
793 int nbytes, buf_left, i;
795 buf_left = buf_used_len - (bufptr - buffer);
796 if (buf_left <= 0) {
797 memmove(buffer, buffer+1, buf_used_len-1);
798 bufptr -= 1;
799 buf_left = 1;
802 nbytes = read(dnload.serial_fd.fd, bufptr, buf_left);
803 if (nbytes <= 0)
804 return nbytes;
806 if (!dnload.expect_hdlc) {
807 printf("got %i bytes from modem, ", nbytes);
808 printf("data looks like: ");
809 osmocon_osmo_hexdump(bufptr, nbytes);
810 } else {
811 for (i = 0; i < nbytes; ++i)
812 if (sercomm_drv_rx_char(bufptr[i]) == 0)
813 printf("Dropping sample '%c'\n", bufptr[i]);
816 return nbytes;
819 /* Compal ramloader */
820 static int handle_read(void)
822 int rc, nbytes;
824 nbytes = handle_buffer(sizeof(buffer));
825 if (nbytes <= 0)
826 return nbytes;
828 if (!memcmp(buffer, phone_prompt1, sizeof(phone_prompt1))) {
829 printf("Received PROMPT1 from phone, responding with CMD\n");
830 dnload.expect_hdlc = 0;
831 dnload.state = WAITING_PROMPT2;
832 if(dnload.filename) {
833 rc = write(dnload.serial_fd.fd, dnload_cmd, sizeof(dnload_cmd));
835 /* re-read file */
836 rc = read_file(dnload.filename, dnload.do_chainload);
837 if (rc < 0) {
838 fprintf(stderr, "read_file(%s) failed with %d\n",
839 dnload.filename, rc);
840 exit(1);
843 } else if (!memcmp(buffer, phone_prompt2, sizeof(phone_prompt2))) {
844 printf("Received PROMPT2 from phone, starting download\n");
845 osmo_fd_update_when(&dnload.serial_fd, 0, OSMO_FD_READ | OSMO_FD_WRITE);
846 dnload.state = DOWNLOADING;
847 } else if (!memcmp(buffer, phone_ack, sizeof(phone_ack))) {
848 printf("Received DOWNLOAD ACK from phone, your code is"
849 " running now!\n");
850 osmo_fd_update_when(&dnload.serial_fd, 0, OSMO_FD_READ);
851 dnload.state = WAITING_PROMPT1;
852 dnload.write_ptr = dnload.data;
853 dnload.expect_hdlc = 1;
855 /* check for romloader chainloading mode used as a workaround
856 * for the magic on the C139/C140 and J100i */
857 if (dnload.do_chainload) {
858 printf("Enabled Compal ramloader -> Calypso romloader"
859 " chainloading mode\n");
860 bufptr = buffer;
861 dnload.previous_mode = dnload.mode;
862 dnload.mode = MODE_ROMLOAD;
863 osmo_serial_set_baudrate(dnload.serial_fd.fd, ROMLOAD_INIT_BAUDRATE);
864 tick_timer.cb = &beacon_timer_cb;
865 tick_timer.data = &tick_timer;
866 osmo_timer_schedule(&tick_timer, 0, dnload.beacon_interval);
868 } else if (!memcmp(buffer, phone_nack, sizeof(phone_nack))) {
869 printf("Received DOWNLOAD NACK from phone, something went"
870 " wrong :(\n");
871 osmo_fd_update_when(&dnload.serial_fd, 0, OSMO_FD_READ);
872 dnload.state = WAITING_PROMPT1;
873 dnload.write_ptr = dnload.data;
874 } else if (!memcmp(buffer, phone_nack_magic, sizeof(phone_nack_magic))) {
875 printf("Received MAGIC NACK from phone, you need to"
876 " have \"1003\" at 0x803ce0\n");
877 osmo_fd_update_when(&dnload.serial_fd, 0, OSMO_FD_READ);
878 dnload.state = WAITING_PROMPT1;
879 dnload.write_ptr = dnload.data;
880 } else if (!memcmp(buffer, ftmtool, sizeof(ftmtool))) {
881 printf("Received FTMTOOL from phone, ramloader has aborted\n");
882 osmo_fd_update_when(&dnload.serial_fd, 0, OSMO_FD_READ);
883 dnload.state = WAITING_PROMPT1;
884 dnload.write_ptr = dnload.data;
886 bufptr += nbytes;
888 return nbytes;
891 /* "Calypso non-secure romloader" */
892 static int handle_read_romload(void)
894 int rc, nbytes, buf_used_len;
896 /* virtually limit buffer length for romloader, since responses
897 * are shorter and vary in length */
899 switch (dnload.romload_state) {
900 case WAITING_PARAM_ACK:
901 buf_used_len = 4; /* ">p" + uint16_t len */
902 break;
903 case WAITING_CHECKSUM_ACK:
904 buf_used_len = 3; /* ">c" + uint8_t checksum */
905 break;
906 case FINISHED:
907 buf_used_len = sizeof(buffer);
908 break;
909 default:
910 buf_used_len = 2; /* ">*" */
913 nbytes = handle_buffer(buf_used_len);
914 if (nbytes <= 0)
915 return nbytes;
917 switch (dnload.romload_state) {
918 case WAITING_IDENTIFICATION:
919 if (memcmp(buffer, romload_ident_ack,
920 sizeof(romload_ident_ack)))
921 break;
923 printf("Received ident ack from phone, sending "
924 "parameter sequence\n");
925 dnload.expect_hdlc = 1;
926 dnload.romload_state = WAITING_PARAM_ACK;
927 rc = write(dnload.serial_fd.fd, romload_param,
928 sizeof(romload_param));
929 /* re-read file */
930 rc = read_file(dnload.filename, 0);
931 if (rc < 0) {
932 fprintf(stderr, "read_file(%s) failed with %d\n",
933 dnload.filename, rc);
934 exit(1);
936 break;
937 case WAITING_PARAM_ACK:
938 if (memcmp(buffer, romload_param_ack,
939 sizeof(romload_param_ack)))
940 break;
942 printf("Received parameter ack from phone, "
943 "starting download\n");
944 osmo_serial_set_baudrate(dnload.serial_fd.fd, ROMLOAD_DL_BAUDRATE);
946 /* using the max blocksize the phone tells us */
947 dnload.block_payload_size = ((buffer[3] << 8) + buffer[2]);
948 dnload.block_payload_size -= ROMLOAD_BLOCK_HDR_LEN;
949 dnload.romload_state = SENDING_BLOCKS;
950 dnload.block_number = 0;
951 romload_prepare_block();
952 bufptr -= 2;
953 break;
954 case WAITING_BLOCK_ACK:
955 case LAST_BLOCK_SENT:
956 if (!memcmp(buffer, romload_block_ack,
957 sizeof(romload_block_ack))) {
958 if (dnload.romload_state == LAST_BLOCK_SENT) {
959 /* send the checksum */
960 uint8_t final_checksum =
961 (~(dnload.romload_dl_checksum) & 0xff);
962 rc = write(dnload.serial_fd.fd,
963 romload_checksum_cmd,
964 sizeof(romload_checksum_cmd));
965 rc = write(dnload.serial_fd.fd,
966 &final_checksum, 1);
967 dnload.romload_state = WAITING_CHECKSUM_ACK;
968 } else
969 romload_prepare_block();
970 } else if (!memcmp(buffer, romload_block_nack,
971 sizeof(romload_block_nack))) {
972 printf("Received block nack from phone, "
973 "something went wrong, aborting\n");
974 osmo_serial_set_baudrate(dnload.serial_fd.fd, ROMLOAD_INIT_BAUDRATE);
975 dnload.romload_state = WAITING_IDENTIFICATION;
976 osmo_timer_schedule(&tick_timer, 0, dnload.beacon_interval);
978 break;
979 case WAITING_CHECKSUM_ACK:
980 if (!memcmp(buffer, romload_checksum_ack,
981 sizeof(romload_checksum_ack))) {
983 rc = write(dnload.serial_fd.fd, romload_branch_cmd,
984 sizeof(romload_branch_cmd));
985 rc = write(dnload.serial_fd.fd, &dnload.load_address,
986 sizeof(dnload.load_address));
987 dnload.romload_state = WAITING_BRANCH_ACK;
988 bufptr -= 1;
989 } else if (!memcmp(buffer, romload_checksum_nack,
990 sizeof(romload_checksum_nack))) {
991 printf("Checksum on phone side (0x%02x) doesn't "
992 "match ours, aborting\n", ~buffer[2]);
993 osmo_serial_set_baudrate(dnload.serial_fd.fd, ROMLOAD_INIT_BAUDRATE);
994 dnload.romload_state = WAITING_IDENTIFICATION;
995 osmo_timer_schedule(&tick_timer, 0, dnload.beacon_interval);
996 bufptr -= 1;
998 break;
999 case WAITING_BRANCH_ACK:
1000 if (!memcmp(buffer, romload_branch_ack,
1001 sizeof(romload_branch_ack))) {
1002 printf("Received branch ack, your code is running now!\n");
1003 osmo_fd_update_when(&dnload.serial_fd, 0, OSMO_FD_READ);
1004 dnload.romload_state = FINISHED;
1005 dnload.write_ptr = dnload.data;
1006 dnload.expect_hdlc = 1;
1008 if (!dnload.do_chainload)
1009 break;
1011 /* if using chainloading mode, switch back to the Compal
1012 * ramloader settings to make sure the auto-reload
1013 * feature works */
1014 bufptr = buffer;
1015 dnload.mode = dnload.previous_mode;
1016 dnload.romload_state = WAITING_IDENTIFICATION;
1017 osmo_serial_set_baudrate(dnload.serial_fd.fd, MODEM_BAUDRATE);
1018 } else if (!memcmp(buffer, romload_branch_nack,
1019 sizeof(romload_branch_nack))) {
1020 printf("Received branch nack, aborting\n");
1021 osmo_serial_set_baudrate(dnload.serial_fd.fd, ROMLOAD_INIT_BAUDRATE);
1022 dnload.romload_state = WAITING_IDENTIFICATION;
1023 osmo_timer_schedule(&tick_timer, 0, dnload.beacon_interval);
1025 break;
1026 default:
1027 break;
1030 bufptr += nbytes;
1031 return nbytes;
1034 /* MTK romloader */
1035 static int handle_read_mtk(void)
1037 int rc, nbytes, buf_used_len;
1039 switch (dnload.mtk_state) {
1040 case MTK_WAIT_ADDR_ACK:
1041 case MTK_WAIT_SIZE_ACK:
1042 case MTK_WAIT_BRANCH_ADDR_ACK:
1043 buf_used_len = 4;
1044 break;
1045 case MTK_FINISHED:
1046 buf_used_len = sizeof(buffer);
1047 break;
1048 default:
1049 buf_used_len = 1;
1052 nbytes = handle_buffer(buf_used_len);
1053 if (nbytes <= 0)
1054 return nbytes;
1056 switch (dnload.mtk_state) {
1057 case MTK_INIT_1:
1058 if (!(buffer[0] == mtk_init_resp[0]))
1059 break;
1060 dnload.mtk_state = MTK_INIT_2;
1061 printf("Received init magic byte 1\n");
1062 rc = write(dnload.serial_fd.fd, &mtk_init_cmd[1], 1);
1063 break;
1064 case MTK_INIT_2:
1065 if (!(buffer[0] == mtk_init_resp[1]))
1066 break;
1067 dnload.mtk_state = MTK_INIT_3;
1068 printf("Received init magic byte 2\n");
1069 rc = write(dnload.serial_fd.fd, &mtk_init_cmd[2], 1);
1070 break;
1071 case MTK_INIT_3:
1072 if (!(buffer[0] == mtk_init_resp[2]))
1073 break;
1074 dnload.mtk_state = MTK_INIT_4;
1075 printf("Received init magic byte 3\n");
1076 rc = write(dnload.serial_fd.fd, &mtk_init_cmd[3], 1);
1077 break;
1078 case MTK_INIT_4:
1079 if (!(buffer[0] == mtk_init_resp[3]))
1080 break;
1081 dnload.mtk_state = MTK_WAIT_WRITE_ACK;
1082 printf("Received init magic byte 4, requesting write\n");
1083 rc = write(dnload.serial_fd.fd, &mtk_command[0], 1);
1084 break;
1085 case MTK_WAIT_WRITE_ACK:
1086 if (!(buffer[0] == mtk_command[0]))
1087 break;
1088 dnload.mtk_state = MTK_WAIT_ADDR_ACK;
1089 printf("Received write ack, sending load address\n");
1091 rc = write(dnload.serial_fd.fd, &dnload.load_address,
1092 sizeof(dnload.load_address));
1093 break;
1094 case MTK_WAIT_ADDR_ACK:
1095 if (memcmp(buffer, dnload.load_address,
1096 sizeof(dnload.load_address)))
1097 break;
1098 printf("Received address ack from phone, sending loadsize\n");
1099 /* re-read file */
1100 rc = read_file(dnload.filename, 0);
1101 if (rc < 0) {
1102 fprintf(stderr, "read_file(%s) failed with %d\n",
1103 dnload.filename, rc);
1104 exit(1);
1106 dnload.block_number = 0;
1107 mtk_prepare_block();
1108 dnload.mtk_state = MTK_WAIT_SIZE_ACK;
1109 rc = write(dnload.serial_fd.fd, &dnload.mtk_send_size,
1110 sizeof(dnload.mtk_send_size));
1111 break;
1112 case MTK_WAIT_SIZE_ACK:
1113 if (memcmp(buffer, dnload.mtk_send_size,
1114 sizeof(dnload.mtk_send_size)))
1115 break;
1116 printf("Received size ack\n");
1117 dnload.expect_hdlc = 1;
1118 dnload.mtk_state = MTK_SENDING_BLOCKS;
1119 osmo_fd_update_when(&dnload.serial_fd, 0, OSMO_FD_READ | OSMO_FD_WRITE);
1120 bufptr -= 3;
1121 break;
1122 case MTK_SENDING_BLOCKS:
1123 if (!(buffer[0] == dnload.block[dnload.echo_bytecount]))
1124 printf("Warning: Byte %i of Block %i doesn't match,"
1125 " check your serial connection!\n",
1126 dnload.echo_bytecount, dnload.block_number);
1127 dnload.echo_bytecount++;
1129 if ((dnload.echo_bytecount+1) > MTK_BLOCK_SIZE) {
1130 if ( dnload.block_number == dnload.block_count) {
1131 rc = write(dnload.serial_fd.fd,
1132 &mtk_command[3], 1);
1133 printf("Sending branch command\n");
1134 dnload.expect_hdlc = 0;
1135 dnload.mtk_state = MTK_WAIT_BRANCH_CMD_ACK;
1136 break;
1138 printf("Received Block %i preparing next block\n",
1139 dnload.block_number);
1140 mtk_prepare_block();
1141 osmo_fd_update_when(&dnload.serial_fd, 0, OSMO_FD_READ | OSMO_FD_WRITE);
1143 break;
1144 case MTK_WAIT_BRANCH_CMD_ACK:
1145 if (!(buffer[0] == mtk_command[3]))
1146 break;
1147 dnload.mtk_state = MTK_WAIT_BRANCH_ADDR_ACK;
1148 printf("Received branch command ack, sending address\n");
1150 rc = write(dnload.serial_fd.fd, &dnload.load_address,
1151 sizeof(dnload.load_address));
1152 break;
1153 case MTK_WAIT_BRANCH_ADDR_ACK:
1154 if (memcmp(buffer, dnload.load_address,
1155 sizeof(dnload.load_address)))
1156 break;
1157 printf("Received branch address ack, code should run now\n");
1158 osmo_serial_set_baudrate(dnload.serial_fd.fd, MODEM_BAUDRATE);
1159 osmo_fd_update_when(&dnload.serial_fd, 0, OSMO_FD_READ);
1160 dnload.mtk_state = MTK_FINISHED;
1161 dnload.write_ptr = dnload.data;
1162 dnload.expect_hdlc = 1;
1163 break;
1164 default:
1165 break;
1168 bufptr += nbytes;
1169 return nbytes;
1172 static int serial_read(struct osmo_fd *fd, unsigned int flags)
1174 int rc;
1175 if (flags & OSMO_FD_READ) {
1176 switch (dnload.mode) {
1177 case MODE_ROMLOAD:
1178 while ((rc = handle_read_romload()) > 0);
1179 break;
1180 case MODE_MTK:
1181 while ((rc = handle_read_mtk()) > 0);
1182 break;
1183 default:
1184 while ((rc = handle_read()) > 0);
1185 break;
1187 if (rc == 0)
1188 exit(2);
1191 if (flags & OSMO_FD_WRITE) {
1192 rc = handle_write();
1193 if (rc == 1)
1194 dnload.state = WAITING_PROMPT1;
1196 return 0;
1199 static int parse_mode(const char *arg)
1201 if (!strcasecmp(arg, "c123"))
1202 return MODE_C123;
1203 else if (!strcasecmp(arg, "c123xor"))
1204 return MODE_C123xor;
1205 else if (!strcasecmp(arg, "c140"))
1206 return MODE_C140;
1207 else if (!strcasecmp(arg, "c140xor"))
1208 return MODE_C140xor;
1209 else if (!strcasecmp(arg, "c155"))
1210 return MODE_C155;
1211 else if (!strcasecmp(arg, "romload"))
1212 return MODE_ROMLOAD;
1213 else if (!strcasecmp(arg, "mtk"))
1214 return MODE_MTK;
1216 return MODE_INVALID;
1219 #define HELP_TEXT \
1220 "[ -v | -h ] [ -d [t][r] ] [ -p /dev/ttyXXXX ]\n" \
1221 "\t\t [ -c ] (enable chainloading of highram-images)\n" \
1222 "\t\t [ -s /tmp/osmocom_l2 ]\n" \
1223 "\t\t [ -l /tmp/osmocom_loader ]\n" \
1224 "\t\t [ -m {c123,c123xor,c140,c140xor,c155,romload,mtk} ]\n" \
1225 "\t\t [ -i beacon-interval (mS) ]\n" \
1226 "\t\t file.bin\n\n" \
1227 "* Open serial port /dev/ttyXXXX (connected to your phone)\n" \
1228 "* Perform handshaking with the ramloader in the phone\n" \
1229 "* Download file.bin to the attached phone (base address 0x00800100)\n"
1231 static int usage(const char *name)
1233 printf("Usage: %s ", name);
1234 printf(HELP_TEXT);
1235 exit(2);
1238 static int version(const char *name)
1240 printf("%s version %s\n", name, PACKAGE_VERSION);
1241 exit(2);
1244 static int un_tool_read(struct osmo_fd *fd, unsigned int flags)
1246 int rc, c;
1247 uint16_t length = 0xffff;
1248 uint8_t buf[4096];
1249 struct tool_connection *con = (struct tool_connection *)fd->data;
1251 c = 0;
1252 while(c < 2) {
1253 rc = read(fd->fd, buf + c, 2 - c);
1254 if(rc == 0) {
1255 // disconnect
1256 goto close;
1258 if(rc < 0) {
1259 if(errno == EAGAIN) {
1260 continue;
1262 fprintf(stderr, "Err from socket: %s\n", strerror(errno));
1263 goto close;
1265 c += rc;
1268 memcpy(&length, buf, sizeof length);
1269 length = ntohs(length);
1271 c = 0;
1272 while(c < length) {
1273 rc = read(fd->fd, buf + c, length - c);
1274 if(rc == 0) {
1275 // disconnect
1276 goto close;
1278 if(rc < 0) {
1279 if(errno == EAGAIN) {
1280 continue;
1282 fprintf(stderr, "Err from socket: %s\n", strerror(errno));
1283 goto close;
1285 c += rc;
1288 hdlc_send_to_phone(con->server->dlci, buf, length);
1290 return 0;
1291 close:
1293 close(fd->fd);
1294 osmo_fd_unregister(fd);
1295 llist_del(&con->entry);
1296 talloc_free(con);
1297 return -1;
1300 /* accept a new connection */
1301 static int tool_accept(struct osmo_fd *fd, unsigned int flags)
1303 struct tool_server *srv = (struct tool_server *)fd->data;
1304 struct tool_connection *con;
1305 struct sockaddr_un un_addr;
1306 socklen_t len;
1307 int rc;
1309 len = sizeof(un_addr);
1310 rc = accept(fd->fd, (struct sockaddr *) &un_addr, &len);
1311 if (rc < 0) {
1312 fprintf(stderr, "Failed to accept a new connection.\n");
1313 return -1;
1316 con = talloc_zero(NULL, struct tool_connection);
1317 if (!con) {
1318 fprintf(stderr, "Failed to create tool connection.\n");
1319 close(rc);
1320 return -1;
1323 con->server = srv;
1325 osmo_fd_setup(&con->fd, rc, OSMO_FD_READ, un_tool_read, con, 0);
1326 if (osmo_fd_register(&con->fd) != 0) {
1327 fprintf(stderr, "Failed to register the fd.\n");
1328 talloc_free(con);
1329 close(rc);
1330 return -1;
1333 llist_add(&con->entry, &srv->connections);
1334 return 0;
1338 * Register and start a tool server
1340 static int register_tool_server(struct tool_server *ts,
1341 const char *path,
1342 uint8_t dlci)
1344 struct osmo_fd *bfd = &ts->bfd;
1345 int rc;
1347 rc = osmo_sock_unix_init_ofd(bfd, SOCK_STREAM, 0, path, OSMO_SOCK_F_BIND);
1348 if (rc < 0) {
1349 fprintf(stderr, "Failed to create Unix Domain Socket.\n");
1350 return -1;
1353 bfd->cb = tool_accept;
1354 bfd->data = ts;
1356 ts->dlci = dlci;
1357 INIT_LLIST_HEAD(&ts->connections);
1359 tool_server_for_dlci[dlci] = ts;
1361 sercomm_register_rx_cb(dlci, hdlc_tool_cb);
1363 return 0;
1366 extern void hdlc_tpudbg_cb(uint8_t dlci, struct msgb *msg);
1368 void parse_debug(const char *str)
1370 while(*str) {
1371 switch(*str) {
1372 case 't':
1373 dnload.dump_tx = 1;
1374 break;
1375 case 'r':
1376 dnload.dump_rx = 1;
1377 break;
1378 default:
1379 printf("Unknown debug flag %c\n", *str);
1380 abort();
1381 break;
1383 str++;
1387 int main(int argc, char **argv)
1389 int opt, flags, fd;
1390 uint32_t tmp_load_address = ROMLOAD_ADDRESS;
1391 const char *serial_dev = "/dev/ttyUSB1";
1392 const char *layer2_un_path = "/tmp/osmocom_l2";
1393 const char *loader_un_path = "/tmp/osmocom_loader";
1395 dnload.mode = MODE_C123;
1396 dnload.beacon_interval = DEFAULT_BEACON_INTERVAL;
1397 dnload.do_chainload = 0;
1399 osmo_init_ignore_signals();
1401 while ((opt = getopt(argc, argv, "d:hl:p:m:cs:i:v")) != -1) {
1402 switch (opt) {
1403 case 'p':
1404 serial_dev = optarg;
1405 break;
1406 case 'm':
1407 dnload.mode = parse_mode(optarg);
1408 if (dnload.mode == MODE_INVALID)
1409 usage(argv[0]);
1410 break;
1411 case 's':
1412 layer2_un_path = optarg;
1413 break;
1414 case 'l':
1415 loader_un_path = optarg;
1416 break;
1417 case 'v':
1418 version(argv[0]);
1419 break;
1420 case 'd':
1421 parse_debug(optarg);
1422 break;
1423 case 'c':
1424 dnload.do_chainload = 1;
1425 break;
1426 case 'i':
1427 dnload.beacon_interval = atoi(optarg) * 1000;
1428 break;
1429 case 'h':
1430 default:
1431 usage(argv[0]);
1432 break;
1436 if (argc <= optind) {
1437 dnload.filename = NULL;
1438 } else {
1439 dnload.filename = argv[optind];
1442 fd = osmo_serial_init(serial_dev, MODEM_BAUDRATE);
1443 if (fd < 0) {
1444 fprintf(stderr, "Cannot open serial device %s\n", serial_dev);
1445 exit(1);
1448 osmo_fd_setup(&dnload.serial_fd, fd, OSMO_FD_READ, serial_read, NULL, 0);
1449 if (osmo_fd_register(&dnload.serial_fd) != 0) {
1450 fprintf(stderr, "Failed to register the serial.\n");
1451 exit(1);
1454 /* Set serial socket to non-blocking mode of operation */
1455 flags = fcntl(dnload.serial_fd.fd, F_GETFL);
1456 flags |= O_NONBLOCK;
1457 fcntl(dnload.serial_fd.fd, F_SETFL, flags);
1459 /* initialize the HDLC layer */
1460 sercomm_init();
1461 sercomm_register_rx_cb(SC_DLCI_CONSOLE, hdlc_console_cb);
1462 sercomm_register_rx_cb(SC_DLCI_DEBUG, hdlc_tpudbg_cb);
1464 /* unix domain socket handling */
1465 if (register_tool_server(&dnload.layer2_server, layer2_un_path,
1466 SC_DLCI_L1A_L23) != 0)
1467 exit(1);
1469 if (register_tool_server(&dnload.loader_server, loader_un_path,
1470 SC_DLCI_LOADER) != 0)
1471 exit(1);
1473 /* if in romload mode, start our beacon timer */
1474 if (dnload.mode == MODE_ROMLOAD) {
1475 tmp_load_address = ROMLOAD_ADDRESS;
1476 osmo_serial_set_baudrate(dnload.serial_fd.fd, ROMLOAD_INIT_BAUDRATE);
1477 tick_timer.cb = &beacon_timer_cb;
1478 tick_timer.data = &tick_timer;
1479 osmo_timer_schedule(&tick_timer, 0, dnload.beacon_interval);
1481 else if (dnload.mode == MODE_MTK) {
1482 tmp_load_address = MTK_ADDRESS;
1483 osmo_serial_set_baudrate(dnload.serial_fd.fd, MTK_INIT_BAUDRATE);
1484 tick_timer.cb = &mtk_timer_cb;
1485 tick_timer.data = &tick_timer;
1486 osmo_timer_schedule(&tick_timer, 0, dnload.beacon_interval);
1489 dnload.load_address[0] = (tmp_load_address >> 24) & 0xff;
1490 dnload.load_address[1] = (tmp_load_address >> 16) & 0xff;
1491 dnload.load_address[2] = (tmp_load_address >> 8) & 0xff;
1492 dnload.load_address[3] = tmp_load_address & 0xff;
1494 while (1) {
1495 if (osmo_select_main(0) < 0)
1496 break;
1499 close(dnload.serial_fd.fd);
1501 exit(0);