osmocon: Improve performance by handling several serial bytes at a time
[osmocom-bb.git] / src / host / osmocon / osmocon.c
blob648d4164a78e28cb925fb30be7b300dff547b921
1 /* osmocon */
3 /* (C) 2010 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>
48 #include <arpa/inet.h>
50 #define MODEM_BAUDRATE B115200
51 #define MAX_DNLOAD_SIZE 0xFFFF
52 #define MAX_HDR_SIZE 128
53 #define MAGIC_OFFSET 0x3be2
55 #define DEFAULT_BEACON_INTERVAL 50000
56 #define ROMLOAD_INIT_BAUDRATE B19200
57 #define ROMLOAD_DL_BAUDRATE B115200
58 #define ROMLOAD_BLOCK_HDR_LEN 10
59 #define ROMLOAD_ADDRESS 0x820000
61 #define MTK_INIT_BAUDRATE B19200
62 #define MTK_ADDRESS 0x40001400
63 #define MTK_BLOCK_SIZE 1024
65 struct tool_server *tool_server_for_dlci[256];
67 /**
68 * a connection from some other tool
70 struct tool_connection {
71 struct tool_server *server;
72 struct llist_head entry;
73 struct osmo_fd fd;
76 /**
77 * server for a tool
79 struct tool_server {
80 struct osmo_fd bfd;
81 uint8_t dlci;
82 struct llist_head connections;
86 enum dnload_state {
87 WAITING_PROMPT1,
88 WAITING_PROMPT2,
89 DOWNLOADING,
92 enum romload_state {
93 WAITING_IDENTIFICATION,
94 WAITING_PARAM_ACK,
95 SENDING_BLOCKS,
96 SENDING_LAST_BLOCK,
97 LAST_BLOCK_SENT,
98 WAITING_BLOCK_ACK,
99 WAITING_CHECKSUM_ACK,
100 WAITING_BRANCH_ACK,
101 FINISHED,
104 enum mtk_state {
105 MTK_INIT_1,
106 MTK_INIT_2,
107 MTK_INIT_3,
108 MTK_INIT_4,
109 MTK_WAIT_WRITE_ACK,
110 MTK_WAIT_ADDR_ACK,
111 MTK_WAIT_SIZE_ACK,
112 MTK_SENDING_BLOCKS,
113 MTK_WAIT_BRANCH_CMD_ACK,
114 MTK_WAIT_BRANCH_ADDR_ACK,
115 MTK_FINISHED,
118 enum dnload_mode {
119 MODE_C123,
120 MODE_C123xor,
121 MODE_C140,
122 MODE_C140xor,
123 MODE_C155,
124 MODE_ROMLOAD,
125 MODE_MTK,
126 MODE_INVALID,
129 struct dnload {
130 enum dnload_state state;
131 enum romload_state romload_state;
132 enum mtk_state mtk_state;
133 enum dnload_mode mode, previous_mode;
134 struct osmo_fd serial_fd;
135 char *filename;
137 int expect_hdlc;
138 int do_chainload;
140 int dump_rx;
141 int dump_tx;
142 int beacon_interval;
144 /* data to be downloaded */
145 uint8_t *data;
146 int data_len;
148 uint8_t *write_ptr;
150 /* romload: block to be downloaded */
151 uint8_t *block;
152 int block_len;
153 uint8_t block_number;
154 uint16_t block_payload_size;
155 int romload_dl_checksum;
156 uint8_t *block_ptr;
157 uint8_t load_address[4];
159 uint8_t mtk_send_size[4];
160 int block_count;
161 int echo_bytecount;
163 struct tool_server layer2_server;
164 struct tool_server loader_server;
168 static struct dnload dnload;
169 static struct osmo_timer_list tick_timer;
171 /* Compal ramloader specific */
172 static const uint8_t phone_prompt1[] = { 0x1b, 0xf6, 0x02, 0x00, 0x41, 0x01, 0x40 };
173 static const uint8_t dnload_cmd[] = { 0x1b, 0xf6, 0x02, 0x00, 0x52, 0x01, 0x53 };
174 static const uint8_t phone_prompt2[] = { 0x1b, 0xf6, 0x02, 0x00, 0x41, 0x02, 0x43 };
175 static const uint8_t phone_ack[] = { 0x1b, 0xf6, 0x02, 0x00, 0x41, 0x03, 0x42 };
176 static const uint8_t phone_nack_magic[]= { 0x1b, 0xf6, 0x02, 0x00, 0x41, 0x03, 0x57 };
177 static const uint8_t phone_nack[] = { 0x1b, 0xf6, 0x02, 0x00, 0x45, 0x53, 0x16 };
178 static const uint8_t ftmtool[] = { 0x66, 0x74, 0x6d, 0x74, 0x6f, 0x6f, 0x6c };
179 static const uint8_t phone_magic[] = { 0x31, 0x30, 0x30, 0x33 }; /* "1003" */
181 /* The C123 has a hard-coded check inside the ramloader that requires the
182 * following bytes to be always the first four bytes of the image */
183 static const uint8_t data_hdr_c123[] = { 0xee, 0x4c, 0x9f, 0x63 };
185 /* The C155 doesn't have some strange restriction on what the first four bytes
186 * have to be, but it starts the ramloader in THUMB mode. We use the following
187 * four bytes to switch back to ARM mode:
188 800100: 4778 bx pc
189 800102: 46c0 nop ; (mov r8, r8)
191 static const uint8_t data_hdr_c155[] = { 0x78, 0x47, 0xc0, 0x46 };
193 /* small loader that enables the bootrom and executes the TI romloader:
194 * _start:
195 * ldr r1, =0x000a0000
196 * wait:
197 * subs r1, r1, #1
198 * bne wait
199 * ldr r1, =0xfffffb10
200 * ldr r2, =0x100
201 * strh r2, [r1]
202 * ldr pc, =0x0
204 static const uint8_t chainloader[] = {
205 0x0a, 0x18, 0xa0, 0xe3, 0x01, 0x10, 0x51, 0xe2, 0xfd, 0xff, 0xff,
206 0x1a, 0x08, 0x10, 0x9f, 0xe5, 0x01, 0x2c, 0xa0, 0xe3, 0xb0, 0x20,
207 0xc1, 0xe1, 0x00, 0xf0, 0xa0, 0xe3, 0x10, 0xfb, 0xff, 0xff,
210 /* Calypso romloader specific */
211 static const uint8_t romload_ident_cmd[] = { 0x3c, 0x69 }; /* <i */
212 static const uint8_t romload_abort_cmd[] = { 0x3c, 0x61 }; /* <a */
213 static const uint8_t romload_write_cmd[] = { 0x3c, 0x77 }; /* <w */
214 static const uint8_t romload_checksum_cmd[] = { 0x3c, 0x63 }; /* <c */
215 static const uint8_t romload_branch_cmd[] = { 0x3c, 0x62 }; /* <b */
216 static const uint8_t romload_ident_ack[] = { 0x3e, 0x69 }; /* >i */
217 static const uint8_t romload_param_ack[] = { 0x3e, 0x70 }; /* >p */
218 static const uint8_t romload_param_nack[] = { 0x3e, 0x50 }; /* >P */
219 static const uint8_t romload_block_ack[] = { 0x3e, 0x77 }; /* >w */
220 static const uint8_t romload_block_nack[] = { 0x3e, 0x57 }; /* >W */
221 static const uint8_t romload_checksum_ack[] = { 0x3e, 0x63 }; /* >c */
222 static const uint8_t romload_checksum_nack[] = { 0x3e, 0x43 }; /* >C */
223 static const uint8_t romload_branch_ack[] = { 0x3e, 0x62 }; /* >b */
224 static const uint8_t romload_branch_nack[] = { 0x3e, 0x42 }; /* >B */
226 /* romload_param: {"<p", uint8_t baudrate, uint8_t dpll, uint16_t memory_config,
227 * uint8_t strobe_af, uint32_t uart_timeout} */
229 static const uint8_t romload_param[] = { 0x3c, 0x70, 0x00, 0x00, 0x00, 0x04,
230 0x00, 0x00, 0x00, 0x00, 0x00 };
232 /* MTK romloader specific */
233 static const uint8_t mtk_init_cmd[] = { 0xa0, 0x0a, 0x50, 0x05 };
234 static const uint8_t mtk_init_resp[] = { 0x5f, 0xf5, 0xaf, 0xfa };
235 static const uint8_t mtk_command[] = { 0xa1, 0xa2, 0xa4, 0xa8 };
237 static void beacon_timer_cb(void *p)
239 int rc;
241 if (dnload.romload_state == WAITING_IDENTIFICATION) {
242 rc = write(dnload.serial_fd.fd, romload_ident_cmd,
243 sizeof(romload_ident_cmd));
245 if (!(rc == sizeof(romload_ident_cmd)))
246 printf("Error sending identification beacon\n");
248 osmo_timer_schedule(p, 0, dnload.beacon_interval);
252 static void mtk_timer_cb(void *p)
254 int rc;
256 if (dnload.mtk_state == MTK_INIT_1) {
257 printf("Sending MTK romloader beacon...\n");
258 rc = write(dnload.serial_fd.fd, &mtk_init_cmd[0], 1);
260 if (!(rc == 1))
261 printf("Error sending identification beacon\n");
263 osmo_timer_schedule(p, 0, dnload.beacon_interval);
267 /* Read the to-be-downloaded file, prepend header and length, append XOR sum */
268 int read_file(const char *filename, int chainload)
270 int fd, rc, i;
271 struct stat st;
272 const uint8_t *hdr = NULL;
273 int payload_size;
274 int hdr_len = 0;
275 uint8_t *file_data;
276 uint16_t tot_len;
277 uint8_t nibble;
278 uint8_t running_xor = 0x02;
280 if (!chainload) {
281 fd = open(filename, O_RDONLY);
282 if (fd < 0) {
283 perror("opening file");
284 exit(1);
287 rc = fstat(fd, &st);
288 if ((st.st_size > MAX_DNLOAD_SIZE) && (dnload.mode != MODE_ROMLOAD)) {
289 fprintf(stderr, "The maximum file size is 64kBytes (%u bytes)\n",
290 MAX_DNLOAD_SIZE);
291 return -EFBIG;
293 } else {
294 st.st_size = sizeof(chainloader);
297 free(dnload.data);
298 dnload.data = NULL;
300 if (dnload.mode == MODE_C140 || dnload.mode == MODE_C140xor) {
301 if (st.st_size < (MAGIC_OFFSET + sizeof(phone_magic)))
302 payload_size = MAGIC_OFFSET + sizeof(phone_magic);
303 else {
304 printf("\nThe filesize is larger than 15kb, code on "
305 "the magic address will be overwritten!\nUse "
306 "loader.bin and upload the application with "
307 "osmoload instead!\n\n");
308 payload_size = st.st_size;
310 } else
311 payload_size = st.st_size;
313 dnload.data = malloc(MAX_HDR_SIZE + payload_size);
315 if (!dnload.data) {
316 close(fd);
317 fprintf(stderr, "No memory\n");
318 return -ENOMEM;
321 /* copy in the header, if any */
322 switch (dnload.mode) {
323 case MODE_C155:
324 hdr = data_hdr_c155;
325 hdr_len = sizeof(data_hdr_c155);
326 break;
327 case MODE_C140:
328 case MODE_C140xor:
329 case MODE_C123:
330 case MODE_C123xor:
331 hdr = data_hdr_c123;
332 hdr_len = sizeof(data_hdr_c123);
333 break;
334 case MODE_ROMLOAD:
335 break;
336 default:
337 break;
340 if (hdr && hdr_len)
341 memcpy(dnload.data, hdr, hdr_len);
343 /* 2 bytes for length + header */
344 file_data = dnload.data + 2 + hdr_len;
346 /* write the length, keep running XOR */
347 tot_len = hdr_len + payload_size;
348 nibble = tot_len >> 8;
349 dnload.data[0] = nibble;
350 running_xor ^= nibble;
351 nibble = tot_len & 0xff;
352 dnload.data[1] = nibble;
353 running_xor ^= nibble;
355 if (hdr_len && hdr) {
356 memcpy(dnload.data+2, hdr, hdr_len);
358 for (i = 0; i < hdr_len; i++)
359 running_xor ^= hdr[i];
362 if (!chainload) {
363 rc = read(fd, file_data, st.st_size);
364 if (rc < 0) {
365 perror("error reading file\n");
366 free(dnload.data);
367 dnload.data = NULL;
368 close(fd);
369 return -EIO;
371 if (rc < st.st_size) {
372 free(dnload.data);
373 dnload.data = NULL;
374 close(fd);
375 fprintf(stderr, "Short read of file (%d < %d)\n",
376 rc, (int)st.st_size);
377 return -EIO;
379 close(fd);
380 } else {
381 memcpy(file_data, chainloader, st.st_size);
384 dnload.data_len = (file_data+payload_size) - dnload.data;
386 /* fill memory between data end and magic, add magic */
387 if(dnload.mode == MODE_C140 || dnload.mode == MODE_C140xor) {
388 if (st.st_size < MAGIC_OFFSET)
389 memset(file_data + st.st_size, 0x00,
390 payload_size - st.st_size);
391 memcpy(dnload.data + MAGIC_OFFSET, phone_magic,
392 sizeof(phone_magic));
395 /* calculate XOR sum */
396 for (i = 0; i < payload_size; i++)
397 running_xor ^= file_data[i];
399 dnload.data[dnload.data_len++] = running_xor;
401 /* initialize write pointer to start of data */
402 dnload.write_ptr = dnload.data;
404 printf("read_file(%s): file_size=%u, hdr_len=%u, dnload_len=%u\n",
405 chainload ? "chainloader" : filename, (int)st.st_size,
406 hdr_len, dnload.data_len);
408 return 0;
411 static void osmocon_osmo_hexdump(const uint8_t *data, unsigned int len)
413 int n;
415 for (n=0; n < len; n++)
416 printf("%02x ", data[n]);
417 printf(" ");
418 for (n=0; n < len; n++)
419 if (isprint(data[n]))
420 putchar(data[n]);
421 else
422 putchar('.');
423 printf("\n");
426 static int romload_prepare_block(void)
428 int i;
430 int block_checksum = 5;
431 int remaining_bytes;
432 int fill_bytes;
433 uint8_t *block_data;
434 uint32_t block_address;
436 dnload.block_len = ROMLOAD_BLOCK_HDR_LEN + dnload.block_payload_size;
438 /* if first block, allocate memory */
439 if (!dnload.block_number) {
440 dnload.block = malloc(dnload.block_len);
441 if (!dnload.block) {
442 fprintf(stderr, "No memory\n");
443 return -ENOMEM;
445 dnload.romload_dl_checksum = 0;
446 /* initialize write pointer to start of data */
447 dnload.write_ptr = dnload.data;
450 block_address = ROMLOAD_ADDRESS +
451 (dnload.block_number * dnload.block_payload_size);
453 /* prepare our block header (10 bytes) */
454 memcpy(dnload.block, romload_write_cmd, sizeof(romload_write_cmd));
455 dnload.block[2] = 0x01; /* block index */
456 /* should normally be the block number, but hangs when sending !0x01 */
457 dnload.block[3] = 0x01; /* dnload.block_number+1 */
458 dnload.block[4] = (dnload.block_payload_size >> 8) & 0xff;
459 dnload.block[5] = dnload.block_payload_size & 0xff;
460 dnload.block[6] = (block_address >> 24) & 0xff;
461 dnload.block[7] = (block_address >> 16) & 0xff;
462 dnload.block[8] = (block_address >> 8) & 0xff;
463 dnload.block[9] = block_address & 0xff;
465 block_data = dnload.block + ROMLOAD_BLOCK_HDR_LEN;
466 dnload.write_ptr = dnload.data + 2 +
467 (dnload.block_payload_size * dnload.block_number);
469 remaining_bytes = dnload.data_len - 3 -
470 (dnload.block_payload_size * dnload.block_number);
472 memcpy(block_data, dnload.write_ptr, dnload.block_payload_size);
474 if (remaining_bytes <= dnload.block_payload_size) {
475 fill_bytes = (dnload.block_payload_size - remaining_bytes);
476 memset(block_data + remaining_bytes, 0x00, fill_bytes);
477 dnload.romload_state = SENDING_LAST_BLOCK;
478 } else {
479 dnload.romload_state = SENDING_BLOCKS;
482 /* block checksum is lsb of ~(5 + block_size_lsb + all bytes of
483 * block_address + all data bytes) */
484 for (i = 5; i < ROMLOAD_BLOCK_HDR_LEN + dnload.block_payload_size; i++)
485 block_checksum += dnload.block[i];
487 /* checksum is lsb of ~(sum of LSBs of all block checksums) */
488 dnload.romload_dl_checksum += ~(block_checksum) & 0xff;
490 /* initialize block pointer to start of block */
491 dnload.block_ptr = dnload.block;
493 dnload.block_number++;
494 dnload.serial_fd.when = BSC_FD_READ | BSC_FD_WRITE;
495 return 0;
498 static int mtk_prepare_block(void)
500 int rc, i;
502 int remaining_bytes;
503 int fill_bytes;
504 uint8_t *block_data;
505 uint8_t tmp_byteswap;
506 uint32_t tmp_size;
508 dnload.block_len = MTK_BLOCK_SIZE;
509 dnload.echo_bytecount = 0;
511 /* if first block, allocate memory */
512 if (!dnload.block_number) {
513 dnload.block = malloc(dnload.block_len);
514 if (!dnload.block) {
515 fprintf(stderr, "No memory\n");
516 return -ENOMEM;
519 /* calculate the number of blocks we need to send */
520 dnload.block_count = (dnload.data_len-3) / MTK_BLOCK_SIZE;
521 /* add one more block if no multiple of blocksize */
522 if((dnload.data_len-3) % MTK_BLOCK_SIZE)
523 dnload.block_count++;
525 /* divide by 2, since we have to tell the mtk loader the size
526 * as count of uint16 (odd transfer sizes are not possible) */
527 tmp_size = (dnload.block_count * MTK_BLOCK_SIZE)/2;
528 dnload.mtk_send_size[0] = (tmp_size >> 24) & 0xff;
529 dnload.mtk_send_size[1] = (tmp_size >> 16) & 0xff;
530 dnload.mtk_send_size[2] = (tmp_size >> 8) & 0xff;
531 dnload.mtk_send_size[3] = tmp_size & 0xff;
533 /* initialize write pointer to start of data */
534 dnload.write_ptr = dnload.data;
537 block_data = dnload.block;
538 dnload.write_ptr = dnload.data + 2 +
539 (dnload.block_len * dnload.block_number);
541 remaining_bytes = dnload.data_len - 3 -
542 (dnload.block_len * dnload.block_number);
544 memcpy(block_data, dnload.write_ptr, MTK_BLOCK_SIZE);
546 if (remaining_bytes <= MTK_BLOCK_SIZE) {
547 fill_bytes = (MTK_BLOCK_SIZE - remaining_bytes);
548 printf("Preparing the last block, filling %i bytes\n",
549 fill_bytes);
550 memset(block_data + remaining_bytes, 0x00, fill_bytes);
551 dnload.romload_state = SENDING_LAST_BLOCK;
552 } else {
553 dnload.romload_state = SENDING_BLOCKS;
554 printf("Preparing block %i\n", dnload.block_number+1);
557 /* for the mtk romloader we need to swap MSB <-> LSB */
558 for (i = 0; i < dnload.block_len; i += 2) {
559 tmp_byteswap = dnload.block[i];
560 dnload.block[i] = dnload.block[i+1];
561 dnload.block[i+1] = tmp_byteswap;
564 /* initialize block pointer to start of block */
565 dnload.block_ptr = dnload.block;
567 dnload.block_number++;
568 return rc;
571 static int handle_write_block(void)
573 int bytes_left, write_len, rc;
574 int progress = 100 * (dnload.block_number * dnload.block_payload_size)
575 / dnload.data_len;
577 if (dnload.block_ptr >= dnload.block + dnload.block_len) {
578 printf("Progress: %i%%\r", progress);
579 fflush(stdout);
580 dnload.write_ptr = dnload.data;
581 dnload.serial_fd.when &= ~BSC_FD_WRITE;
582 if (dnload.romload_state == SENDING_LAST_BLOCK) {
583 dnload.romload_state = LAST_BLOCK_SENT;
584 printf("Finished, sent %i blocks in total\n",
585 dnload.block_number);
586 } else {
587 dnload.romload_state = WAITING_BLOCK_ACK;
590 return 0;
593 /* try to write a maximum of block_len bytes */
594 bytes_left = (dnload.block + dnload.block_len) - dnload.block_ptr;
595 write_len = dnload.block_len;
596 if (bytes_left < dnload.block_len)
597 write_len = bytes_left;
599 rc = write(dnload.serial_fd.fd, dnload.block_ptr, write_len);
600 if (rc < 0) {
601 perror("Error during write");
602 return rc;
605 dnload.block_ptr += rc;
607 return 0;
610 #define WRITE_BLOCK 4096
612 static int handle_write_dnload(void)
614 int bytes_left, write_len, rc;
615 uint8_t xor_init = 0x02;
617 printf("handle_write(): ");
618 if (dnload.write_ptr == dnload.data) {
619 /* no bytes have been transferred yet */
620 switch (dnload.mode) {
621 case MODE_C155:
622 case MODE_C140xor:
623 case MODE_C123xor:
624 rc = write(dnload.serial_fd.fd, &xor_init, 1);
625 break;
626 default:
627 break;
629 } else if (dnload.write_ptr >= dnload.data + dnload.data_len) {
630 printf("finished\n");
631 dnload.write_ptr = dnload.data;
632 dnload.serial_fd.when &= ~BSC_FD_WRITE;
633 return 1;
636 /* try to write a maximum of WRITE_BLOCK bytes */
637 bytes_left = (dnload.data + dnload.data_len) - dnload.write_ptr;
638 write_len = WRITE_BLOCK;
639 if (bytes_left < WRITE_BLOCK)
640 write_len = bytes_left;
642 rc = write(dnload.serial_fd.fd, dnload.write_ptr, write_len);
643 if (rc < 0) {
644 perror("Error during write");
645 return rc;
648 dnload.write_ptr += rc;
650 printf("%u bytes (%u/%u)\n", rc, dnload.write_ptr - dnload.data,
651 dnload.data_len);
653 return 0;
656 static int handle_sercomm_write(void)
658 uint8_t buffer[256];
659 int i, count = 0, end = 0;
661 for (i = 0; i < sizeof(buffer); i++) {
662 if (sercomm_drv_pull(&buffer[i]) == 0) {
663 end = 1;
664 break;
666 count++;
669 if (count) {
670 if (write(dnload.serial_fd.fd, buffer, count) != count)
671 perror("short write");
674 if (end)
675 dnload.serial_fd.when &= ~BSC_FD_WRITE;
677 return 0;
680 static int handle_write(void)
682 /* TODO: simplify this again (global state: downloading, sercomm) */
683 switch (dnload.mode) {
684 case MODE_ROMLOAD:
685 switch (dnload.romload_state) {
686 case SENDING_BLOCKS:
687 case SENDING_LAST_BLOCK:
688 return handle_write_block();
689 default:
690 return handle_sercomm_write();
692 break;
693 case MODE_MTK:
694 switch (dnload.mtk_state) {
695 case MTK_SENDING_BLOCKS:
696 return handle_write_block();
697 default:
698 return handle_sercomm_write();
700 break;
701 default:
702 switch (dnload.state) {
703 case DOWNLOADING:
704 return handle_write_dnload();
705 default:
706 return handle_sercomm_write();
710 return 0;
713 static uint8_t buffer[sizeof(phone_prompt1)];
714 static uint8_t *bufptr = buffer;
716 static void hdlc_send_to_phone(uint8_t dlci, uint8_t *data, int len)
718 struct msgb *msg;
719 uint8_t *dest;
721 if(dnload.dump_tx) {
722 printf("hdlc_send(dlci=%u): ", dlci);
723 osmocon_osmo_hexdump(data, len);
726 if (len > 512) {
727 fprintf(stderr, "Too much data to send. %u\n", len);
728 return;
731 /* push the message into the stack */
732 msg = sercomm_alloc_msgb(512);
733 if (!msg) {
734 fprintf(stderr, "Failed to create data for the frame.\n");
735 return;
738 /* copy the data */
739 dest = msgb_put(msg, len);
740 memcpy(dest, data, len);
742 sercomm_sendmsg(dlci, msg);
744 dnload.serial_fd.when |= BSC_FD_WRITE;
747 static void hdlc_console_cb(uint8_t dlci, struct msgb *msg)
749 write(1, msg->data, msg->len);
750 msgb_free(msg);
753 static void hdlc_tool_cb(uint8_t dlci, struct msgb *msg)
755 struct tool_server *srv = tool_server_for_dlci[dlci];
757 if(dnload.dump_rx) {
758 printf("hdlc_recv(dlci=%u): ", dlci);
759 osmocon_osmo_hexdump(msg->data, msg->len);
762 if(srv) {
763 struct tool_connection *con;
764 uint16_t *len;
766 len = (uint16_t *) msgb_push(msg, 2);
767 *len = htons(msg->len - sizeof(*len));
769 llist_for_each_entry(con, &srv->connections, entry) {
770 if (write(con->fd.fd, msg->data, msg->len) != msg->len) {
771 fprintf(stderr,
772 "Failed to write msg to the socket..\n");
773 continue;
778 msgb_free(msg);
781 static int handle_buffer(int buf_used_len)
783 int nbytes, buf_left, i;
785 buf_left = buf_used_len - (bufptr - buffer);
786 if (buf_left <= 0) {
787 memmove(buffer, buffer+1, buf_used_len-1);
788 bufptr -= 1;
789 buf_left = 1;
792 nbytes = read(dnload.serial_fd.fd, bufptr, buf_left);
793 if (nbytes <= 0)
794 return nbytes;
796 if (!dnload.expect_hdlc) {
797 printf("got %i bytes from modem, ", nbytes);
798 printf("data looks like: ");
799 osmocon_osmo_hexdump(bufptr, nbytes);
800 } else {
801 for (i = 0; i < nbytes; ++i)
802 if (sercomm_drv_rx_char(bufptr[i]) == 0)
803 printf("Dropping sample '%c'\n", bufptr[i]);
806 return nbytes;
809 /* Compal ramloader */
810 static int handle_read(void)
812 int rc, nbytes;
814 nbytes = handle_buffer(sizeof(buffer));
815 if (nbytes <= 0)
816 return nbytes;
818 if (!memcmp(buffer, phone_prompt1, sizeof(phone_prompt1))) {
819 printf("Received PROMPT1 from phone, responding with CMD\n");
820 dnload.expect_hdlc = 0;
821 dnload.state = WAITING_PROMPT2;
822 if(dnload.filename) {
823 rc = write(dnload.serial_fd.fd, dnload_cmd, sizeof(dnload_cmd));
825 /* re-read file */
826 rc = read_file(dnload.filename, dnload.do_chainload);
827 if (rc < 0) {
828 fprintf(stderr, "read_file(%s) failed with %d\n",
829 dnload.filename, rc);
830 exit(1);
833 } else if (!memcmp(buffer, phone_prompt2, sizeof(phone_prompt2))) {
834 printf("Received PROMPT2 from phone, starting download\n");
835 dnload.serial_fd.when = BSC_FD_READ | BSC_FD_WRITE;
836 dnload.state = DOWNLOADING;
837 } else if (!memcmp(buffer, phone_ack, sizeof(phone_ack))) {
838 printf("Received DOWNLOAD ACK from phone, your code is"
839 " running now!\n");
840 dnload.serial_fd.when = BSC_FD_READ;
841 dnload.state = WAITING_PROMPT1;
842 dnload.write_ptr = dnload.data;
843 dnload.expect_hdlc = 1;
845 /* check for romloader chainloading mode used as a workaround
846 * for the magic on the C139/C140 and J100i */
847 if (dnload.do_chainload) {
848 printf("Enabled Compal ramloader -> Calypso romloader"
849 " chainloading mode\n");
850 bufptr = buffer;
851 dnload.previous_mode = dnload.mode;
852 dnload.mode = MODE_ROMLOAD;
853 osmo_serial_set_baudrate(dnload.serial_fd.fd, ROMLOAD_INIT_BAUDRATE);
854 tick_timer.cb = &beacon_timer_cb;
855 tick_timer.data = &tick_timer;
856 osmo_timer_schedule(&tick_timer, 0, dnload.beacon_interval);
858 } else if (!memcmp(buffer, phone_nack, sizeof(phone_nack))) {
859 printf("Received DOWNLOAD NACK from phone, something went"
860 " wrong :(\n");
861 dnload.serial_fd.when = BSC_FD_READ;
862 dnload.state = WAITING_PROMPT1;
863 dnload.write_ptr = dnload.data;
864 } else if (!memcmp(buffer, phone_nack_magic, sizeof(phone_nack_magic))) {
865 printf("Received MAGIC NACK from phone, you need to"
866 " have \"1003\" at 0x803ce0\n");
867 dnload.serial_fd.when = BSC_FD_READ;
868 dnload.state = WAITING_PROMPT1;
869 dnload.write_ptr = dnload.data;
870 } else if (!memcmp(buffer, ftmtool, sizeof(ftmtool))) {
871 printf("Received FTMTOOL from phone, ramloader has aborted\n");
872 dnload.serial_fd.when = BSC_FD_READ;
873 dnload.state = WAITING_PROMPT1;
874 dnload.write_ptr = dnload.data;
876 bufptr += nbytes;
878 return nbytes;
881 /* "Calypso non-secure romloader" */
882 static int handle_read_romload(void)
884 int rc, nbytes, buf_used_len;
886 /* virtually limit buffer length for romloader, since responses
887 * are shorter and vary in length */
889 switch (dnload.romload_state) {
890 case WAITING_PARAM_ACK:
891 buf_used_len = 4; /* ">p" + uint16_t len */
892 break;
893 case WAITING_CHECKSUM_ACK:
894 buf_used_len = 3; /* ">c" + uint8_t checksum */
895 break;
896 case FINISHED:
897 buf_used_len = sizeof(buffer);
898 break;
899 default:
900 buf_used_len = 2; /* ">*" */
903 nbytes = handle_buffer(buf_used_len);
904 if (nbytes <= 0)
905 return nbytes;
907 switch (dnload.romload_state) {
908 case WAITING_IDENTIFICATION:
909 if (memcmp(buffer, romload_ident_ack,
910 sizeof(romload_ident_ack)))
911 break;
913 printf("Received ident ack from phone, sending "
914 "parameter sequence\n");
915 dnload.expect_hdlc = 1;
916 dnload.romload_state = WAITING_PARAM_ACK;
917 rc = write(dnload.serial_fd.fd, romload_param,
918 sizeof(romload_param));
919 /* re-read file */
920 rc = read_file(dnload.filename, 0);
921 if (rc < 0) {
922 fprintf(stderr, "read_file(%s) failed with %d\n",
923 dnload.filename, rc);
924 exit(1);
926 break;
927 case WAITING_PARAM_ACK:
928 if (memcmp(buffer, romload_param_ack,
929 sizeof(romload_param_ack)))
930 break;
932 printf("Received parameter ack from phone, "
933 "starting download\n");
934 osmo_serial_set_baudrate(dnload.serial_fd.fd, ROMLOAD_DL_BAUDRATE);
936 /* using the max blocksize the phone tells us */
937 dnload.block_payload_size = ((buffer[3] << 8) + buffer[2]);
938 dnload.block_payload_size -= ROMLOAD_BLOCK_HDR_LEN;
939 dnload.romload_state = SENDING_BLOCKS;
940 dnload.block_number = 0;
941 romload_prepare_block();
942 bufptr -= 2;
943 break;
944 case WAITING_BLOCK_ACK:
945 case LAST_BLOCK_SENT:
946 if (!memcmp(buffer, romload_block_ack,
947 sizeof(romload_block_ack))) {
948 if (dnload.romload_state == LAST_BLOCK_SENT) {
949 /* send the checksum */
950 uint8_t final_checksum =
951 (~(dnload.romload_dl_checksum) & 0xff);
952 rc = write(dnload.serial_fd.fd,
953 romload_checksum_cmd,
954 sizeof(romload_checksum_cmd));
955 rc = write(dnload.serial_fd.fd,
956 &final_checksum, 1);
957 dnload.romload_state = WAITING_CHECKSUM_ACK;
958 } else
959 romload_prepare_block();
960 } else if (!memcmp(buffer, romload_block_nack,
961 sizeof(romload_block_nack))) {
962 printf("Received block nack from phone, "
963 "something went wrong, aborting\n");
964 osmo_serial_set_baudrate(dnload.serial_fd.fd, ROMLOAD_INIT_BAUDRATE);
965 dnload.romload_state = WAITING_IDENTIFICATION;
966 osmo_timer_schedule(&tick_timer, 0, dnload.beacon_interval);
968 break;
969 case WAITING_CHECKSUM_ACK:
970 if (!memcmp(buffer, romload_checksum_ack,
971 sizeof(romload_checksum_ack))) {
973 rc = write(dnload.serial_fd.fd, romload_branch_cmd,
974 sizeof(romload_branch_cmd));
975 rc = write(dnload.serial_fd.fd, &dnload.load_address,
976 sizeof(dnload.load_address));
977 dnload.romload_state = WAITING_BRANCH_ACK;
978 bufptr -= 1;
979 } else if (!memcmp(buffer, romload_checksum_nack,
980 sizeof(romload_checksum_nack))) {
981 printf("Checksum on phone side (0x%02x) doesn't "
982 "match ours, aborting\n", ~buffer[2]);
983 osmo_serial_set_baudrate(dnload.serial_fd.fd, ROMLOAD_INIT_BAUDRATE);
984 dnload.romload_state = WAITING_IDENTIFICATION;
985 osmo_timer_schedule(&tick_timer, 0, dnload.beacon_interval);
986 bufptr -= 1;
988 break;
989 case WAITING_BRANCH_ACK:
990 if (!memcmp(buffer, romload_branch_ack,
991 sizeof(romload_branch_ack))) {
992 printf("Received branch ack, your code is running now!\n");
993 dnload.serial_fd.when = BSC_FD_READ;
994 dnload.romload_state = FINISHED;
995 dnload.write_ptr = dnload.data;
996 dnload.expect_hdlc = 1;
998 if (!dnload.do_chainload)
999 break;
1001 /* if using chainloading mode, switch back to the Compal
1002 * ramloader settings to make sure the auto-reload
1003 * feature works */
1004 bufptr = buffer;
1005 dnload.mode = dnload.previous_mode;
1006 dnload.romload_state = WAITING_IDENTIFICATION;
1007 osmo_serial_set_baudrate(dnload.serial_fd.fd, MODEM_BAUDRATE);
1008 } else if (!memcmp(buffer, romload_branch_nack,
1009 sizeof(romload_branch_nack))) {
1010 printf("Received branch nack, aborting\n");
1011 osmo_serial_set_baudrate(dnload.serial_fd.fd, ROMLOAD_INIT_BAUDRATE);
1012 dnload.romload_state = WAITING_IDENTIFICATION;
1013 osmo_timer_schedule(&tick_timer, 0, dnload.beacon_interval);
1015 break;
1016 default:
1017 break;
1020 bufptr += nbytes;
1021 return nbytes;
1024 /* MTK romloader */
1025 static int handle_read_mtk(void)
1027 int rc, nbytes, buf_used_len;
1029 switch (dnload.mtk_state) {
1030 case MTK_WAIT_ADDR_ACK:
1031 case MTK_WAIT_SIZE_ACK:
1032 case MTK_WAIT_BRANCH_ADDR_ACK:
1033 buf_used_len = 4;
1034 break;
1035 case MTK_FINISHED:
1036 buf_used_len = sizeof(buffer);
1037 break;
1038 default:
1039 buf_used_len = 1;
1042 nbytes = handle_buffer(buf_used_len);
1043 if (nbytes <= 0)
1044 return nbytes;
1046 switch (dnload.mtk_state) {
1047 case MTK_INIT_1:
1048 if (!(buffer[0] == mtk_init_resp[0]))
1049 break;
1050 dnload.mtk_state = MTK_INIT_2;
1051 printf("Received init magic byte 1\n");
1052 rc = write(dnload.serial_fd.fd, &mtk_init_cmd[1], 1);
1053 break;
1054 case MTK_INIT_2:
1055 if (!(buffer[0] == mtk_init_resp[1]))
1056 break;
1057 dnload.mtk_state = MTK_INIT_3;
1058 printf("Received init magic byte 2\n");
1059 rc = write(dnload.serial_fd.fd, &mtk_init_cmd[2], 1);
1060 break;
1061 case MTK_INIT_3:
1062 if (!(buffer[0] == mtk_init_resp[2]))
1063 break;
1064 dnload.mtk_state = MTK_INIT_4;
1065 printf("Received init magic byte 3\n");
1066 rc = write(dnload.serial_fd.fd, &mtk_init_cmd[3], 1);
1067 break;
1068 case MTK_INIT_4:
1069 if (!(buffer[0] == mtk_init_resp[3]))
1070 break;
1071 dnload.mtk_state = MTK_WAIT_WRITE_ACK;
1072 printf("Received init magic byte 4, requesting write\n");
1073 rc = write(dnload.serial_fd.fd, &mtk_command[0], 1);
1074 break;
1075 case MTK_WAIT_WRITE_ACK:
1076 if (!(buffer[0] == mtk_command[0]))
1077 break;
1078 dnload.mtk_state = MTK_WAIT_ADDR_ACK;
1079 printf("Received write ack, sending load address\n");
1081 rc = write(dnload.serial_fd.fd, &dnload.load_address,
1082 sizeof(dnload.load_address));
1083 break;
1084 case MTK_WAIT_ADDR_ACK:
1085 if (memcmp(buffer, dnload.load_address,
1086 sizeof(dnload.load_address)))
1087 break;
1088 printf("Received address ack from phone, sending loadsize\n");
1089 /* re-read file */
1090 rc = read_file(dnload.filename, 0);
1091 if (rc < 0) {
1092 fprintf(stderr, "read_file(%s) failed with %d\n",
1093 dnload.filename, rc);
1094 exit(1);
1096 dnload.block_number = 0;
1097 mtk_prepare_block();
1098 dnload.mtk_state = MTK_WAIT_SIZE_ACK;
1099 rc = write(dnload.serial_fd.fd, &dnload.mtk_send_size,
1100 sizeof(dnload.mtk_send_size));
1101 break;
1102 case MTK_WAIT_SIZE_ACK:
1103 if (memcmp(buffer, dnload.mtk_send_size,
1104 sizeof(dnload.mtk_send_size)))
1105 break;
1106 printf("Received size ack\n");
1107 dnload.expect_hdlc = 1;
1108 dnload.mtk_state = MTK_SENDING_BLOCKS;
1109 dnload.serial_fd.when = BSC_FD_READ | BSC_FD_WRITE;
1110 bufptr -= 3;
1111 break;
1112 case MTK_SENDING_BLOCKS:
1113 if (!(buffer[0] == dnload.block[dnload.echo_bytecount]))
1114 printf("Warning: Byte %i of Block %i doesn't match,"
1115 " check your serial connection!\n",
1116 dnload.echo_bytecount, dnload.block_number);
1117 dnload.echo_bytecount++;
1119 if ((dnload.echo_bytecount+1) > MTK_BLOCK_SIZE) {
1120 if ( dnload.block_number == dnload.block_count) {
1121 rc = write(dnload.serial_fd.fd,
1122 &mtk_command[3], 1);
1123 printf("Sending branch command\n");
1124 dnload.expect_hdlc = 0;
1125 dnload.mtk_state = MTK_WAIT_BRANCH_CMD_ACK;
1126 break;
1128 printf("Received Block %i preparing next block\n",
1129 dnload.block_number);
1130 mtk_prepare_block();
1131 dnload.serial_fd.when = BSC_FD_READ | BSC_FD_WRITE;
1133 break;
1134 case MTK_WAIT_BRANCH_CMD_ACK:
1135 if (!(buffer[0] == mtk_command[3]))
1136 break;
1137 dnload.mtk_state = MTK_WAIT_BRANCH_ADDR_ACK;
1138 printf("Received branch command ack, sending address\n");
1140 rc = write(dnload.serial_fd.fd, &dnload.load_address,
1141 sizeof(dnload.load_address));
1142 break;
1143 case MTK_WAIT_BRANCH_ADDR_ACK:
1144 if (memcmp(buffer, dnload.load_address,
1145 sizeof(dnload.load_address)))
1146 break;
1147 printf("Received branch address ack, code should run now\n");
1148 osmo_serial_set_baudrate(dnload.serial_fd.fd, MODEM_BAUDRATE);
1149 dnload.serial_fd.when = BSC_FD_READ;
1150 dnload.mtk_state = MTK_FINISHED;
1151 dnload.write_ptr = dnload.data;
1152 dnload.expect_hdlc = 1;
1153 break;
1154 default:
1155 break;
1158 bufptr += nbytes;
1159 return nbytes;
1162 static int serial_read(struct osmo_fd *fd, unsigned int flags)
1164 int rc;
1165 if (flags & BSC_FD_READ) {
1166 switch (dnload.mode) {
1167 case MODE_ROMLOAD:
1168 while ((rc = handle_read_romload()) > 0);
1169 break;
1170 case MODE_MTK:
1171 while ((rc = handle_read_mtk()) > 0);
1172 break;
1173 default:
1174 while ((rc = handle_read()) > 0);
1175 break;
1177 if (rc == 0)
1178 exit(2);
1181 if (flags & BSC_FD_WRITE) {
1182 rc = handle_write();
1183 if (rc == 1)
1184 dnload.state = WAITING_PROMPT1;
1186 return 0;
1189 static int parse_mode(const char *arg)
1191 if (!strcasecmp(arg, "c123"))
1192 return MODE_C123;
1193 else if (!strcasecmp(arg, "c123xor"))
1194 return MODE_C123xor;
1195 else if (!strcasecmp(arg, "c140"))
1196 return MODE_C140;
1197 else if (!strcasecmp(arg, "c140xor"))
1198 return MODE_C140xor;
1199 else if (!strcasecmp(arg, "c155"))
1200 return MODE_C155;
1201 else if (!strcasecmp(arg, "romload"))
1202 return MODE_ROMLOAD;
1203 else if (!strcasecmp(arg, "mtk"))
1204 return MODE_MTK;
1206 return MODE_INVALID;
1209 #define HELP_TEXT \
1210 "[ -v | -h ] [ -d [t][r] ] [ -p /dev/ttyXXXX ]\n" \
1211 "\t\t [ -c ] (enable chainloading of highram-images)\n" \
1212 "\t\t [ -s /tmp/osmocom_l2 ]\n" \
1213 "\t\t [ -l /tmp/osmocom_loader ]\n" \
1214 "\t\t [ -m {c123,c123xor,c140,c140xor,c155,romload,mtk} ]\n" \
1215 "\t\t [ -i beacon-interval (mS) ]\n" \
1216 "\t\t file.bin\n\n" \
1217 "* Open serial port /dev/ttyXXXX (connected to your phone)\n" \
1218 "* Perform handshaking with the ramloader in the phone\n" \
1219 "* Download file.bin to the attached phone (base address 0x00800100)\n"
1221 static int usage(const char *name)
1223 printf("Usage: %s ", name);
1224 printf(HELP_TEXT);
1225 exit(2);
1228 static int version(const char *name)
1230 printf("%s version %s\n", name, PACKAGE_VERSION);
1231 exit(2);
1234 static int un_tool_read(struct osmo_fd *fd, unsigned int flags)
1236 int rc, c;
1237 uint16_t length = 0xffff;
1238 uint8_t buf[4096];
1239 struct tool_connection *con = (struct tool_connection *)fd->data;
1241 c = 0;
1242 while(c < 2) {
1243 rc = read(fd->fd, &buf + c, 2 - c);
1244 if(rc == 0) {
1245 // disconnect
1246 goto close;
1248 if(rc < 0) {
1249 if(errno == EAGAIN) {
1250 continue;
1252 fprintf(stderr, "Err from socket: %s\n", strerror(errno));
1253 goto close;
1255 c += rc;
1258 memcpy(&length, buf, sizeof length);
1259 length = ntohs(length);
1261 c = 0;
1262 while(c < length) {
1263 rc = read(fd->fd, &buf + c, length - c);
1264 if(rc == 0) {
1265 // disconnect
1266 goto close;
1268 if(rc < 0) {
1269 if(errno == EAGAIN) {
1270 continue;
1272 fprintf(stderr, "Err from socket: %s\n", strerror(errno));
1273 goto close;
1275 c += rc;
1278 hdlc_send_to_phone(con->server->dlci, buf, length);
1280 return 0;
1281 close:
1283 close(fd->fd);
1284 osmo_fd_unregister(fd);
1285 llist_del(&con->entry);
1286 talloc_free(con);
1287 return -1;
1290 /* accept a new connection */
1291 static int tool_accept(struct osmo_fd *fd, unsigned int flags)
1293 struct tool_server *srv = (struct tool_server *)fd->data;
1294 struct tool_connection *con;
1295 struct sockaddr_un un_addr;
1296 socklen_t len;
1297 int rc;
1299 len = sizeof(un_addr);
1300 rc = accept(fd->fd, (struct sockaddr *) &un_addr, &len);
1301 if (rc < 0) {
1302 fprintf(stderr, "Failed to accept a new connection.\n");
1303 return -1;
1306 con = talloc_zero(NULL, struct tool_connection);
1307 if (!con) {
1308 fprintf(stderr, "Failed to create tool connection.\n");
1309 return -1;
1312 con->server = srv;
1314 con->fd.fd = rc;
1315 con->fd.when = BSC_FD_READ;
1316 con->fd.cb = un_tool_read;
1317 con->fd.data = con;
1318 if (osmo_fd_register(&con->fd) != 0) {
1319 fprintf(stderr, "Failed to register the fd.\n");
1320 return -1;
1323 llist_add(&con->entry, &srv->connections);
1324 return 0;
1328 * Register and start a tool server
1330 static int register_tool_server(struct tool_server *ts,
1331 const char *path,
1332 uint8_t dlci)
1334 struct osmo_fd *bfd = &ts->bfd;
1335 struct sockaddr_un local;
1336 unsigned int namelen;
1337 int rc;
1339 bfd->fd = socket(AF_UNIX, SOCK_STREAM, 0);
1341 if (bfd->fd < 0) {
1342 fprintf(stderr, "Failed to create Unix Domain Socket.\n");
1343 return -1;
1346 local.sun_family = AF_UNIX;
1347 strncpy(local.sun_path, path, sizeof(local.sun_path));
1348 local.sun_path[sizeof(local.sun_path) - 1] = '\0';
1349 unlink(local.sun_path);
1351 /* we use the same magic that X11 uses in Xtranssock.c for
1352 * calculating the proper length of the sockaddr */
1353 #if defined(BSD44SOCKETS) || defined(__UNIXWARE__)
1354 local.sun_len = strlen(local.sun_path);
1355 #endif
1356 #if defined(BSD44SOCKETS) || defined(SUN_LEN)
1357 namelen = SUN_LEN(&local);
1358 #else
1359 namelen = strlen(local.sun_path) +
1360 offsetof(struct sockaddr_un, sun_path);
1361 #endif
1363 rc = bind(bfd->fd, (struct sockaddr *) &local, namelen);
1364 if (rc != 0) {
1365 fprintf(stderr, "Failed to bind the unix domain socket. '%s'\n",
1366 local.sun_path);
1367 return -1;
1370 if (listen(bfd->fd, 0) != 0) {
1371 fprintf(stderr, "Failed to listen.\n");
1372 return -1;
1375 bfd->when = BSC_FD_READ;
1376 bfd->cb = tool_accept;
1377 bfd->data = ts;
1379 ts->dlci = dlci;
1380 INIT_LLIST_HEAD(&ts->connections);
1382 tool_server_for_dlci[dlci] = ts;
1384 sercomm_register_rx_cb(dlci, hdlc_tool_cb);
1386 if (osmo_fd_register(bfd) != 0) {
1387 fprintf(stderr, "Failed to register the bfd.\n");
1388 return -1;
1391 return 0;
1394 extern void hdlc_tpudbg_cb(uint8_t dlci, struct msgb *msg);
1396 void parse_debug(const char *str)
1398 while(*str) {
1399 switch(*str) {
1400 case 't':
1401 dnload.dump_tx = 1;
1402 break;
1403 case 'r':
1404 dnload.dump_rx = 1;
1405 break;
1406 default:
1407 printf("Unknown debug flag %c\n", *str);
1408 abort();
1409 break;
1411 str++;
1415 int main(int argc, char **argv)
1417 int opt, flags;
1418 uint32_t tmp_load_address = ROMLOAD_ADDRESS;
1419 const char *serial_dev = "/dev/ttyUSB1";
1420 const char *layer2_un_path = "/tmp/osmocom_l2";
1421 const char *loader_un_path = "/tmp/osmocom_loader";
1423 dnload.mode = MODE_C123;
1424 dnload.beacon_interval = DEFAULT_BEACON_INTERVAL;
1425 dnload.do_chainload = 0;
1427 while ((opt = getopt(argc, argv, "d:hl:p:m:cs:i:v")) != -1) {
1428 switch (opt) {
1429 case 'p':
1430 serial_dev = optarg;
1431 break;
1432 case 'm':
1433 dnload.mode = parse_mode(optarg);
1434 if (dnload.mode == MODE_INVALID)
1435 usage(argv[0]);
1436 break;
1437 case 's':
1438 layer2_un_path = optarg;
1439 break;
1440 case 'l':
1441 loader_un_path = optarg;
1442 break;
1443 case 'v':
1444 version(argv[0]);
1445 break;
1446 case 'd':
1447 parse_debug(optarg);
1448 break;
1449 case 'c':
1450 dnload.do_chainload = 1;
1451 break;
1452 case 'i':
1453 dnload.beacon_interval = atoi(optarg) * 1000;
1454 break;
1455 case 'h':
1456 default:
1457 usage(argv[0]);
1458 break;
1462 if (argc <= optind) {
1463 dnload.filename = NULL;
1464 } else {
1465 dnload.filename = argv[optind];
1468 dnload.serial_fd.fd = osmo_serial_init(serial_dev, MODEM_BAUDRATE);
1469 if (dnload.serial_fd.fd < 0) {
1470 fprintf(stderr, "Cannot open serial device %s\n", serial_dev);
1471 exit(1);
1474 if (osmo_fd_register(&dnload.serial_fd) != 0) {
1475 fprintf(stderr, "Failed to register the serial.\n");
1476 exit(1);
1479 /* Set serial socket to non-blocking mode of operation */
1480 flags = fcntl(dnload.serial_fd.fd, F_GETFL);
1481 flags |= O_NONBLOCK;
1482 fcntl(dnload.serial_fd.fd, F_SETFL, flags);
1484 dnload.serial_fd.when = BSC_FD_READ;
1485 dnload.serial_fd.cb = serial_read;
1487 /* initialize the HDLC layer */
1488 sercomm_init();
1489 sercomm_register_rx_cb(SC_DLCI_CONSOLE, hdlc_console_cb);
1490 sercomm_register_rx_cb(SC_DLCI_DEBUG, hdlc_tpudbg_cb);
1492 /* unix domain socket handling */
1493 if (register_tool_server(&dnload.layer2_server, layer2_un_path,
1494 SC_DLCI_L1A_L23) != 0)
1495 exit(1);
1497 if (register_tool_server(&dnload.loader_server, loader_un_path,
1498 SC_DLCI_LOADER) != 0)
1499 exit(1);
1501 /* if in romload mode, start our beacon timer */
1502 if (dnload.mode == MODE_ROMLOAD) {
1503 tmp_load_address = ROMLOAD_ADDRESS;
1504 osmo_serial_set_baudrate(dnload.serial_fd.fd, ROMLOAD_INIT_BAUDRATE);
1505 tick_timer.cb = &beacon_timer_cb;
1506 tick_timer.data = &tick_timer;
1507 osmo_timer_schedule(&tick_timer, 0, dnload.beacon_interval);
1509 else if (dnload.mode == MODE_MTK) {
1510 tmp_load_address = MTK_ADDRESS;
1511 osmo_serial_set_baudrate(dnload.serial_fd.fd, MTK_INIT_BAUDRATE);
1512 tick_timer.cb = &mtk_timer_cb;
1513 tick_timer.data = &tick_timer;
1514 osmo_timer_schedule(&tick_timer, 0, dnload.beacon_interval);
1517 dnload.load_address[0] = (tmp_load_address >> 24) & 0xff;
1518 dnload.load_address[1] = (tmp_load_address >> 16) & 0xff;
1519 dnload.load_address[2] = (tmp_load_address >> 8) & 0xff;
1520 dnload.load_address[3] = tmp_load_address & 0xff;
1522 while (1) {
1523 if (osmo_select_main(0) < 0)
1524 break;
1527 close(dnload.serial_fd.fd);
1529 exit(0);