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>
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.
34 #include <sys/ioctl.h>
35 #include <sys/types.h>
36 #include <sys/socket.h>
42 #include <osmocom/core/linuxlist.h>
43 #include <osmocom/core/select.h>
44 #include <osmocom/core/talloc.h>
45 #include <osmocom/core/timer.h>
47 #include <arpa/inet.h>
49 #define MODEM_BAUDRATE B115200
50 #define MAX_DNLOAD_SIZE 0xFFFF
51 #define MAX_HDR_SIZE 128
52 #define MAGIC_OFFSET 0x3be2
54 #define DEFAULT_BEACON_INTERVAL 50000
55 #define ROMLOAD_INIT_BAUDRATE B19200
56 #define ROMLOAD_DL_BAUDRATE B115200
57 #define ROMLOAD_BLOCK_HDR_LEN 10
58 #define ROMLOAD_ADDRESS 0x820000
60 #define MTK_INIT_BAUDRATE B19200
61 #define MTK_ADDRESS 0x40001400
62 #define MTK_BLOCK_SIZE 1024
64 struct tool_server *tool_server_for_dlci[256];
67 * a connection from some other tool
69 struct tool_connection {
70 struct tool_server *server;
71 struct llist_head entry;
81 struct llist_head connections;
92 WAITING_IDENTIFICATION,
112 MTK_WAIT_BRANCH_CMD_ACK,
113 MTK_WAIT_BRANCH_ADDR_ACK,
128 enum dnload_state state;
129 enum romload_state romload_state;
130 enum mtk_state mtk_state;
131 enum dnload_mode mode;
132 struct osmo_fd serial_fd;
134 char *chainload_filename;
142 /* data to be downloaded */
148 /* romload: block to be downloaded */
151 uint8_t block_number;
152 uint16_t block_payload_size;
153 int romload_dl_checksum;
155 uint8_t load_address[4];
157 uint8_t mtk_send_size[4];
161 struct tool_server layer2_server;
162 struct tool_server loader_server;
166 static struct dnload dnload;
167 static struct osmo_timer_list tick_timer;
169 /* Compal ramloader specific */
170 static const uint8_t phone_prompt1[] = { 0x1b, 0xf6, 0x02, 0x00, 0x41, 0x01, 0x40 };
171 static const uint8_t dnload_cmd[] = { 0x1b, 0xf6, 0x02, 0x00, 0x52, 0x01, 0x53 };
172 static const uint8_t phone_prompt2[] = { 0x1b, 0xf6, 0x02, 0x00, 0x41, 0x02, 0x43 };
173 static const uint8_t phone_ack[] = { 0x1b, 0xf6, 0x02, 0x00, 0x41, 0x03, 0x42 };
174 static const uint8_t phone_nack_magic[]= { 0x1b, 0xf6, 0x02, 0x00, 0x41, 0x03, 0x57 };
175 static const uint8_t phone_nack[] = { 0x1b, 0xf6, 0x02, 0x00, 0x45, 0x53, 0x16 };
176 static const uint8_t ftmtool[] = { 0x66, 0x74, 0x6d, 0x74, 0x6f, 0x6f, 0x6c };
177 static const uint8_t phone_magic[] = { 0x31, 0x30, 0x30, 0x33 }; /* "1003" */
179 /* The C123 has a hard-coded check inside the ramloader that requires the
180 * following bytes to be always the first four bytes of the image */
181 static const uint8_t data_hdr_c123[] = { 0xee, 0x4c, 0x9f, 0x63 };
183 /* The C155 doesn't have some strange restriction on what the first four bytes
184 * have to be, but it starts the ramloader in THUMB mode. We use the following
185 * four bytes to switch back to ARM mode:
187 800102: 46c0 nop ; (mov r8, r8)
189 static const uint8_t data_hdr_c155[] = { 0x78, 0x47, 0xc0, 0x46 };
191 /* Calypso romloader specific */
192 static const uint8_t romload_ident_cmd[] = { 0x3c, 0x69 }; /* <i */
193 static const uint8_t romload_abort_cmd[] = { 0x3c, 0x61 }; /* <a */
194 static const uint8_t romload_write_cmd[] = { 0x3c, 0x77 }; /* <w */
195 static const uint8_t romload_checksum_cmd[] = { 0x3c, 0x63 }; /* <c */
196 static const uint8_t romload_branch_cmd[] = { 0x3c, 0x62 }; /* <b */
197 static const uint8_t romload_ident_ack[] = { 0x3e, 0x69 }; /* >i */
198 static const uint8_t romload_param_ack[] = { 0x3e, 0x70 }; /* >p */
199 static const uint8_t romload_param_nack[] = { 0x3e, 0x50 }; /* >P */
200 static const uint8_t romload_block_ack[] = { 0x3e, 0x77 }; /* >w */
201 static const uint8_t romload_block_nack[] = { 0x3e, 0x57 }; /* >W */
202 static const uint8_t romload_checksum_ack[] = { 0x3e, 0x63 }; /* >c */
203 static const uint8_t romload_checksum_nack[] = { 0x3e, 0x43 }; /* >C */
204 static const uint8_t romload_branch_ack[] = { 0x3e, 0x62 }; /* >b */
205 static const uint8_t romload_branch_nack[] = { 0x3e, 0x42 }; /* >B */
207 /* romload_param: {"<p", uint8_t baudrate, uint8_t dpll, uint16_t memory_config,
208 * uint8_t strobe_af, uint32_t uart_timeout} */
210 static const uint8_t romload_param[] = { 0x3c, 0x70, 0x00, 0x00, 0x00, 0x04,
211 0x00, 0x00, 0x00, 0x00, 0x00 };
213 /* MTK romloader specific */
214 static const uint8_t mtk_init_cmd[] = { 0xa0, 0x0a, 0x50, 0x05 };
215 static const uint8_t mtk_init_resp[] = { 0x5f, 0xf5, 0xaf, 0xfa };
216 static const uint8_t mtk_command[] = { 0xa1, 0xa2, 0xa4, 0xa8 };
218 /* FIXME: this routine is more or less what openbsc/src/rs232:rs232_setup()
219 * does, we should move it to libosmocore at some point */
220 static int serial_init(const char *serial_port)
222 int rc, serial_fd, v24;
225 serial_fd = open(serial_port, O_RDWR | O_NOCTTY | O_NDELAY);
227 perror("cannot open serial port");
231 //fcntl(serial_fd, F_SETFL, 0);
233 /* Configure serial interface */
234 rc = tcgetattr(serial_fd, &tio);
236 perror("tcgetattr()");
239 cfsetispeed(&tio, MODEM_BAUDRATE);
240 cfsetospeed(&tio, MODEM_BAUDRATE);
241 tio.c_cflag &= ~(PARENB | CSTOPB | CSIZE | CRTSCTS);
242 tio.c_cflag |= (CREAD | CLOCAL | CS8);
243 tio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
244 tio.c_iflag |= (INPCK | ISTRIP);
245 tio.c_iflag &= ~(ISTRIP | IXON | IXOFF | IGNBRK | INLCR | ICRNL | IGNCR);
246 tio.c_oflag &= ~(OPOST | ONLCR);
247 rc = tcsetattr(serial_fd, TCSANOW, &tio);
249 perror("tcsetattr()");
253 /* set ready to read/write */
254 v24 = TIOCM_DTR | TIOCM_RTS;
255 rc = ioctl(serial_fd, TIOCMBIS, &v24);
257 perror("ioctl(TIOCMBIS)");
264 static int serial_set_baudrate(speed_t baudrate)
269 rc = tcgetattr(dnload.serial_fd.fd, &tio);
271 perror("tcgetattr()");
274 cfsetispeed(&tio, baudrate);
275 cfsetospeed(&tio, baudrate);
277 rc = tcsetattr(dnload.serial_fd.fd, TCSANOW, &tio);
281 static void beacon_timer_cb(void *p)
285 if (dnload.romload_state == WAITING_IDENTIFICATION) {
286 printf("Sending Calypso romloader beacon...\n");
287 rc = write(dnload.serial_fd.fd, romload_ident_cmd,
288 sizeof(romload_ident_cmd));
290 if (!(rc == sizeof(romload_ident_cmd)))
291 printf("Error sending identification beacon\n");
293 osmo_timer_schedule(p, 0, dnload.beacon_interval);
297 static void mtk_timer_cb(void *p)
301 if (dnload.mtk_state == MTK_INIT_1) {
302 printf("Sending MTK romloader beacon...\n");
303 rc = write(dnload.serial_fd.fd, &mtk_init_cmd[0], 1);
306 printf("Error sending identification beacon\n");
308 osmo_timer_schedule(p, 0, dnload.beacon_interval);
312 /* Read the to-be-downloaded file, prepend header and length, append XOR sum */
313 int read_file(const char *filename)
317 const uint8_t *hdr = NULL;
323 uint8_t running_xor = 0x02;
325 fd = open(filename, O_RDONLY);
327 perror("opening file");
332 if (st.st_size > MAX_DNLOAD_SIZE) {
333 fprintf(stderr, "The maximum file size is 64kBytes (%u bytes)\n",
341 if (dnload.mode == MODE_C140 || dnload.mode == MODE_C140xor) {
342 if (st.st_size < (MAGIC_OFFSET + sizeof(phone_magic)))
343 payload_size = MAGIC_OFFSET + sizeof(phone_magic);
345 printf("\nThe filesize is larger than 15kb, code on "
346 "the magic address will be overwritten!\nUse "
347 "loader.bin and upload the application with "
348 "osmoload instead!\n\n");
349 payload_size = st.st_size;
352 payload_size = st.st_size;
354 dnload.data = malloc(MAX_HDR_SIZE + payload_size);
358 fprintf(stderr, "No memory\n");
362 /* copy in the header, if any */
363 switch (dnload.mode) {
366 hdr_len = sizeof(data_hdr_c155);
373 hdr_len = sizeof(data_hdr_c123);
382 memcpy(dnload.data, hdr, hdr_len);
384 /* 2 bytes for length + header */
385 file_data = dnload.data + 2 + hdr_len;
387 /* write the length, keep running XOR */
388 tot_len = hdr_len + payload_size;
389 nibble = tot_len >> 8;
390 dnload.data[0] = nibble;
391 running_xor ^= nibble;
392 nibble = tot_len & 0xff;
393 dnload.data[1] = nibble;
394 running_xor ^= nibble;
396 if (hdr_len && hdr) {
397 memcpy(dnload.data+2, hdr, hdr_len);
399 for (i = 0; i < hdr_len; i++)
400 running_xor ^= hdr[i];
403 rc = read(fd, file_data, st.st_size);
405 perror("error reading file\n");
411 if (rc < st.st_size) {
415 fprintf(stderr, "Short read of file (%d < %d)\n",
416 rc, (int)st.st_size);
422 dnload.data_len = (file_data+payload_size) - dnload.data;
424 /* fill memory between data end and magic, add magic */
425 if(dnload.mode == MODE_C140 || dnload.mode == MODE_C140xor) {
426 if (st.st_size < MAGIC_OFFSET)
427 memset(file_data + st.st_size, 0x00,
428 payload_size - st.st_size);
429 memcpy(dnload.data + MAGIC_OFFSET, phone_magic,
430 sizeof(phone_magic));
433 /* calculate XOR sum */
434 for (i = 0; i < payload_size; i++)
435 running_xor ^= file_data[i];
437 dnload.data[dnload.data_len++] = running_xor;
439 /* initialize write pointer to start of data */
440 dnload.write_ptr = dnload.data;
442 printf("read_file(%s): file_size=%u, hdr_len=%u, dnload_len=%u\n",
443 filename, (int)st.st_size, hdr_len, dnload.data_len);
448 static void osmocon_osmo_hexdump(const uint8_t *data, unsigned int len)
452 for (n=0; n < len; n++)
453 printf("%02x ", data[n]);
455 for (n=0; n < len; n++)
456 if (isprint(data[n]))
463 static int romload_prepare_block(void)
467 int block_checksum = 5;
471 uint32_t block_address;
473 dnload.block_len = ROMLOAD_BLOCK_HDR_LEN + dnload.block_payload_size;
475 /* if first block, allocate memory */
476 if (!dnload.block_number) {
477 dnload.block = malloc(dnload.block_len);
479 fprintf(stderr, "No memory\n");
482 dnload.romload_dl_checksum = 0;
483 /* initialize write pointer to start of data */
484 dnload.write_ptr = dnload.data;
487 block_address = ROMLOAD_ADDRESS +
488 (dnload.block_number * dnload.block_payload_size);
490 /* prepare our block header (10 bytes) */
491 memcpy(dnload.block, romload_write_cmd, sizeof(romload_write_cmd));
492 dnload.block[2] = 0x01; /* block index */
493 /* should normally be the block number, but hangs when sending !0x01 */
494 dnload.block[3] = 0x01; /* dnload.block_number+1 */
495 dnload.block[4] = (dnload.block_payload_size >> 8) & 0xff;
496 dnload.block[5] = dnload.block_payload_size & 0xff;
497 dnload.block[6] = (block_address >> 24) & 0xff;
498 dnload.block[7] = (block_address >> 16) & 0xff;
499 dnload.block[8] = (block_address >> 8) & 0xff;
500 dnload.block[9] = block_address & 0xff;
502 block_data = dnload.block + ROMLOAD_BLOCK_HDR_LEN;
503 dnload.write_ptr = dnload.data + 2 +
504 (dnload.block_payload_size * dnload.block_number);
506 remaining_bytes = dnload.data_len - 3 -
507 (dnload.block_payload_size * dnload.block_number);
509 memcpy(block_data, dnload.write_ptr, dnload.block_payload_size);
511 if (remaining_bytes <= dnload.block_payload_size) {
512 fill_bytes = (dnload.block_payload_size - remaining_bytes);
513 printf("Preparing the last block, filling %i bytes,",
515 memset(block_data + remaining_bytes, 0x00, fill_bytes);
516 dnload.romload_state = SENDING_LAST_BLOCK;
518 dnload.romload_state = SENDING_BLOCKS;
519 printf("Preparing block %i,", dnload.block_number+1);
522 /* block checksum is lsb of ~(5 + block_size_lsb + all bytes of
523 * block_address + all data bytes) */
524 for (i = 5; i < ROMLOAD_BLOCK_HDR_LEN + dnload.block_payload_size; i++)
525 block_checksum += dnload.block[i];
527 /* checksum is lsb of ~(sum of LSBs of all block checksums) */
528 printf(" block checksum is 0x%02x \n", ~(block_checksum) & 0xff);
529 dnload.romload_dl_checksum += ~(block_checksum) & 0xff;
531 /* initialize block pointer to start of block */
532 dnload.block_ptr = dnload.block;
534 dnload.block_number++;
535 dnload.serial_fd.when = BSC_FD_READ | BSC_FD_WRITE;
539 static int mtk_prepare_block(void)
546 uint8_t tmp_byteswap;
549 dnload.block_len = MTK_BLOCK_SIZE;
550 dnload.echo_bytecount = 0;
552 /* if first block, allocate memory */
553 if (!dnload.block_number) {
554 dnload.block = malloc(dnload.block_len);
556 fprintf(stderr, "No memory\n");
560 /* calculate the number of blocks we need to send */
561 dnload.block_count = (dnload.data_len-3) / MTK_BLOCK_SIZE;
562 /* add one more block if no multiple of blocksize */
563 if((dnload.data_len-3) % MTK_BLOCK_SIZE)
564 dnload.block_count++;
566 /* divide by 2, since we have to tell the mtk loader the size
567 * as count of uint16 (odd transfer sizes are not possible) */
568 tmp_size = (dnload.block_count * MTK_BLOCK_SIZE)/2;
569 dnload.mtk_send_size[0] = (tmp_size >> 24) & 0xff;
570 dnload.mtk_send_size[1] = (tmp_size >> 16) & 0xff;
571 dnload.mtk_send_size[2] = (tmp_size >> 8) & 0xff;
572 dnload.mtk_send_size[3] = tmp_size & 0xff;
574 /* initialize write pointer to start of data */
575 dnload.write_ptr = dnload.data;
578 block_data = dnload.block;
579 dnload.write_ptr = dnload.data + 2 +
580 (dnload.block_len * dnload.block_number);
582 remaining_bytes = dnload.data_len - 3 -
583 (dnload.block_len * dnload.block_number);
585 memcpy(block_data, dnload.write_ptr, MTK_BLOCK_SIZE);
587 if (remaining_bytes <= MTK_BLOCK_SIZE) {
588 fill_bytes = (MTK_BLOCK_SIZE - remaining_bytes);
589 printf("Preparing the last block, filling %i bytes\n",
591 memset(block_data + remaining_bytes, 0x00, fill_bytes);
592 dnload.romload_state = SENDING_LAST_BLOCK;
594 dnload.romload_state = SENDING_BLOCKS;
595 printf("Preparing block %i\n", dnload.block_number+1);
598 /* for the mtk romloader we need to swap MSB <-> LSB */
599 for (i = 0; i < dnload.block_len; i += 2) {
600 tmp_byteswap = dnload.block[i];
601 dnload.block[i] = dnload.block[i+1];
602 dnload.block[i+1] = tmp_byteswap;
605 /* initialize block pointer to start of block */
606 dnload.block_ptr = dnload.block;
608 dnload.block_number++;
612 static int handle_write_block(void)
614 int bytes_left, write_len, rc;
616 printf("handle_write_block(): ");
618 if (dnload.block_ptr >= dnload.block + dnload.block_len) {
619 printf("Block %i finished\n", dnload.block_number);
620 dnload.write_ptr = dnload.data;
621 dnload.serial_fd.when &= ~BSC_FD_WRITE;
622 if (dnload.romload_state == SENDING_LAST_BLOCK) {
623 dnload.romload_state = LAST_BLOCK_SENT;
624 printf("Finished, sent %i blocks in total\n",
625 dnload.block_number);
627 dnload.romload_state = WAITING_BLOCK_ACK;
633 /* try to write a maximum of block_len bytes */
634 bytes_left = (dnload.block + dnload.block_len) - dnload.block_ptr;
635 write_len = dnload.block_len;
636 if (bytes_left < dnload.block_len)
637 write_len = bytes_left;
639 rc = write(dnload.serial_fd.fd, dnload.block_ptr, write_len);
641 perror("Error during write");
645 dnload.block_ptr += rc;
647 printf("%u bytes (%tu/%u)\n", rc, dnload.block_ptr - dnload.block,
653 #define WRITE_BLOCK 4096
655 static int handle_write_dnload(void)
657 int bytes_left, write_len, rc;
658 uint8_t xor_init = 0x02;
660 printf("handle_write(): ");
661 if (dnload.write_ptr == dnload.data) {
662 /* no bytes have been transferred yet */
663 switch (dnload.mode) {
667 rc = write(dnload.serial_fd.fd, &xor_init, 1);
672 } else if (dnload.write_ptr >= dnload.data + dnload.data_len) {
673 printf("finished\n");
674 dnload.write_ptr = dnload.data;
675 dnload.serial_fd.when &= ~BSC_FD_WRITE;
679 /* try to write a maximum of WRITE_BLOCK bytes */
680 bytes_left = (dnload.data + dnload.data_len) - dnload.write_ptr;
681 write_len = WRITE_BLOCK;
682 if (bytes_left < WRITE_BLOCK)
683 write_len = bytes_left;
685 rc = write(dnload.serial_fd.fd, dnload.write_ptr, write_len);
687 perror("Error during write");
691 dnload.write_ptr += rc;
693 printf("%u bytes (%tu/%u)\n", rc, dnload.write_ptr - dnload.data,
699 static int handle_sercomm_write(void)
703 if (sercomm_drv_pull(&c) != 0) {
704 if (write(dnload.serial_fd.fd, &c, 1) != 1)
705 perror("short write");
707 dnload.serial_fd.when &= ~BSC_FD_WRITE;
712 static int handle_write(void)
714 /* TODO: simplify this again (global state: downloading, sercomm) */
715 switch (dnload.mode) {
717 switch (dnload.romload_state) {
719 case SENDING_LAST_BLOCK:
720 return handle_write_block();
722 return handle_sercomm_write();
726 switch (dnload.mtk_state) {
727 case MTK_SENDING_BLOCKS:
728 return handle_write_block();
730 return handle_sercomm_write();
734 switch (dnload.state) {
736 return handle_write_dnload();
738 return handle_sercomm_write();
745 static uint8_t buffer[sizeof(phone_prompt1)];
746 static uint8_t *bufptr = buffer;
748 static void hdlc_send_to_phone(uint8_t dlci, uint8_t *data, int len)
754 printf("hdlc_send(dlci=%u): ", dlci);
755 osmocon_osmo_hexdump(data, len);
759 fprintf(stderr, "Too much data to send. %u\n", len);
763 /* push the message into the stack */
764 msg = sercomm_alloc_msgb(512);
766 fprintf(stderr, "Failed to create data for the frame.\n");
771 dest = msgb_put(msg, len);
772 memcpy(dest, data, len);
774 sercomm_sendmsg(dlci, msg);
776 dnload.serial_fd.when |= BSC_FD_WRITE;
779 static void hdlc_console_cb(uint8_t dlci, struct msgb *msg)
781 write(1, msg->data, msg->len);
785 static void hdlc_tool_cb(uint8_t dlci, struct msgb *msg)
787 struct tool_server *srv = tool_server_for_dlci[dlci];
790 printf("hdlc_recv(dlci=%u): ", dlci);
791 osmocon_osmo_hexdump(msg->data, msg->len);
795 struct tool_connection *con;
798 len = (uint16_t *) msgb_push(msg, 2);
799 *len = htons(msg->len - sizeof(*len));
801 llist_for_each_entry(con, &srv->connections, entry) {
802 if (write(con->fd.fd, msg->data, msg->len) != msg->len) {
804 "Failed to write msg to the socket..\n");
813 static int handle_buffer(int buf_used_len)
815 int nbytes, buf_left, i;
817 buf_left = buf_used_len - (bufptr - buffer);
819 memmove(buffer, buffer+1, buf_used_len-1);
824 nbytes = read(dnload.serial_fd.fd, bufptr, buf_left);
828 if (!dnload.expect_hdlc) {
829 printf("got %i bytes from modem, ", nbytes);
830 printf("data looks like: ");
831 osmocon_osmo_hexdump(bufptr, nbytes);
833 for (i = 0; i < nbytes; ++i)
834 if (sercomm_drv_rx_char(bufptr[i]) == 0)
835 printf("Dropping sample '%c'\n", bufptr[i]);
841 /* Compal ramloader */
842 static int handle_read(void)
846 nbytes = handle_buffer(sizeof(buffer));
850 if (!memcmp(buffer, phone_prompt1, sizeof(phone_prompt1))) {
851 printf("Received PROMPT1 from phone, responding with CMD\n");
852 dnload.expect_hdlc = 0;
853 dnload.state = WAITING_PROMPT2;
854 if(dnload.filename) {
855 rc = write(dnload.serial_fd.fd, dnload_cmd, sizeof(dnload_cmd));
858 rc = read_file(dnload.filename);
860 fprintf(stderr, "read_file(%s) failed with %d\n",
861 dnload.filename, rc);
865 } else if (!memcmp(buffer, phone_prompt2, sizeof(phone_prompt2))) {
866 printf("Received PROMPT2 from phone, starting download\n");
867 dnload.serial_fd.when = BSC_FD_READ | BSC_FD_WRITE;
868 dnload.state = DOWNLOADING;
869 } else if (!memcmp(buffer, phone_ack, sizeof(phone_ack))) {
870 printf("Received DOWNLOAD ACK from phone, your code is"
872 dnload.serial_fd.when = BSC_FD_READ;
873 dnload.state = WAITING_PROMPT1;
874 dnload.write_ptr = dnload.data;
875 dnload.expect_hdlc = 1;
877 /* check for romloader chainloading mode used as a workaround
878 * for the magic on the C139/C140 and J100i */
879 if (dnload.chainload_filename != NULL) {
880 printf("Enabled Compal ramloader -> Calypso romloader"
881 " chainloading mode\n");
883 dnload.filename = dnload.chainload_filename;
884 dnload.mode = MODE_ROMLOAD;
885 serial_set_baudrate(ROMLOAD_INIT_BAUDRATE);
886 tick_timer.cb = &beacon_timer_cb;
887 tick_timer.data = &tick_timer;
888 osmo_timer_schedule(&tick_timer, 0, dnload.beacon_interval);
890 } else if (!memcmp(buffer, phone_nack, sizeof(phone_nack))) {
891 printf("Received DOWNLOAD NACK from phone, something went"
893 dnload.serial_fd.when = BSC_FD_READ;
894 dnload.state = WAITING_PROMPT1;
895 dnload.write_ptr = dnload.data;
896 } else if (!memcmp(buffer, phone_nack_magic, sizeof(phone_nack_magic))) {
897 printf("Received MAGIC NACK from phone, you need to"
898 " have \"1003\" at 0x803ce0\n");
899 dnload.serial_fd.when = BSC_FD_READ;
900 dnload.state = WAITING_PROMPT1;
901 dnload.write_ptr = dnload.data;
902 } else if (!memcmp(buffer, ftmtool, sizeof(ftmtool))) {
903 printf("Received FTMTOOL from phone, ramloader has aborted\n");
904 dnload.serial_fd.when = BSC_FD_READ;
905 dnload.state = WAITING_PROMPT1;
906 dnload.write_ptr = dnload.data;
913 /* "Calypso non-secure romloader" */
914 static int handle_read_romload(void)
916 int rc, nbytes, buf_used_len;
918 /* virtually limit buffer length for romloader, since responses
919 * are shorter and vary in length */
921 switch (dnload.romload_state) {
922 case WAITING_PARAM_ACK:
923 buf_used_len = 4; /* ">p" + uint16_t len */
925 case WAITING_CHECKSUM_ACK:
926 buf_used_len = 3; /* ">c" + uint8_t checksum */
929 buf_used_len = sizeof(buffer);
932 buf_used_len = 2; /* ">*" */
935 nbytes = handle_buffer(buf_used_len);
939 switch (dnload.romload_state) {
940 case WAITING_IDENTIFICATION:
941 if (memcmp(buffer, romload_ident_ack,
942 sizeof(romload_ident_ack)))
945 printf("Received ident ack from phone, sending "
946 "parameter sequence\n");
947 dnload.expect_hdlc = 1;
948 dnload.romload_state = WAITING_PARAM_ACK;
949 rc = write(dnload.serial_fd.fd, romload_param,
950 sizeof(romload_param));
952 rc = read_file(dnload.filename);
954 fprintf(stderr, "read_file(%s) failed with %d\n",
955 dnload.filename, rc);
959 case WAITING_PARAM_ACK:
960 if (memcmp(buffer, romload_param_ack,
961 sizeof(romload_param_ack)))
964 printf("Received parameter ack from phone, "
965 "starting download\n");
966 serial_set_baudrate(ROMLOAD_DL_BAUDRATE);
968 /* using the max blocksize the phone tells us */
969 dnload.block_payload_size = ((buffer[3] << 8) + buffer[2]);
970 printf("Used blocksize for download is %i bytes\n",
971 dnload.block_payload_size);
972 dnload.block_payload_size -= ROMLOAD_BLOCK_HDR_LEN;
973 dnload.romload_state = SENDING_BLOCKS;
974 dnload.block_number = 0;
975 romload_prepare_block();
978 case WAITING_BLOCK_ACK:
979 case LAST_BLOCK_SENT:
980 if (!memcmp(buffer, romload_block_ack,
981 sizeof(romload_block_ack))) {
982 printf("Received block ack from phone\n");
983 if (dnload.romload_state == LAST_BLOCK_SENT) {
984 /* send the checksum */
985 uint8_t final_checksum =
986 (~(dnload.romload_dl_checksum) & 0xff);
987 printf("Sending checksum: 0x%02x \n",
989 rc = write(dnload.serial_fd.fd,
990 romload_checksum_cmd,
991 sizeof(romload_checksum_cmd));
992 rc = write(dnload.serial_fd.fd,
994 dnload.romload_state = WAITING_CHECKSUM_ACK;
996 romload_prepare_block();
997 } else if (!memcmp(buffer, romload_block_nack,
998 sizeof(romload_block_nack))) {
999 printf("Received block nack from phone, "
1000 "something went wrong, aborting\n");
1001 serial_set_baudrate(ROMLOAD_INIT_BAUDRATE);
1002 dnload.romload_state = WAITING_IDENTIFICATION;
1003 osmo_timer_schedule(&tick_timer, 0, dnload.beacon_interval);
1006 case WAITING_CHECKSUM_ACK:
1007 if (!memcmp(buffer, romload_checksum_ack,
1008 sizeof(romload_checksum_ack))) {
1009 printf("Checksum on phone side matches, "
1010 "let's branch to your code\n");
1011 printf("Branching to 0x%08x\n", ROMLOAD_ADDRESS);
1013 rc = write(dnload.serial_fd.fd, romload_branch_cmd,
1014 sizeof(romload_branch_cmd));
1015 rc = write(dnload.serial_fd.fd, &dnload.load_address,
1016 sizeof(dnload.load_address));
1017 dnload.romload_state = WAITING_BRANCH_ACK;
1019 } else if (!memcmp(buffer, romload_checksum_nack,
1020 sizeof(romload_checksum_nack))) {
1021 printf("Checksum on phone side (0x%02x) doesn't "
1022 "match ours, aborting\n", ~buffer[2]);
1023 serial_set_baudrate(ROMLOAD_INIT_BAUDRATE);
1024 dnload.romload_state = WAITING_IDENTIFICATION;
1025 osmo_timer_schedule(&tick_timer, 0, dnload.beacon_interval);
1029 case WAITING_BRANCH_ACK:
1030 if (!memcmp(buffer, romload_branch_ack,
1031 sizeof(romload_branch_ack))) {
1032 printf("Received branch ack, your code is running now!\n");
1033 dnload.serial_fd.when = BSC_FD_READ;
1034 dnload.romload_state = FINISHED;
1035 dnload.write_ptr = dnload.data;
1036 dnload.expect_hdlc = 1;
1037 } else if (!memcmp(buffer, romload_branch_nack,
1038 sizeof(romload_branch_nack))) {
1039 printf("Received branch nack, aborting\n");
1040 serial_set_baudrate(ROMLOAD_INIT_BAUDRATE);
1041 dnload.romload_state = WAITING_IDENTIFICATION;
1042 osmo_timer_schedule(&tick_timer, 0, dnload.beacon_interval);
1054 static int handle_read_mtk(void)
1056 int rc, nbytes, buf_used_len;
1058 switch (dnload.mtk_state) {
1059 case MTK_WAIT_ADDR_ACK:
1060 case MTK_WAIT_SIZE_ACK:
1061 case MTK_WAIT_BRANCH_ADDR_ACK:
1065 buf_used_len = sizeof(buffer);
1071 nbytes = handle_buffer(buf_used_len);
1075 switch (dnload.mtk_state) {
1077 if (!(buffer[0] == mtk_init_resp[0]))
1079 dnload.mtk_state = MTK_INIT_2;
1080 printf("Received init magic byte 1\n");
1081 rc = write(dnload.serial_fd.fd, &mtk_init_cmd[1], 1);
1084 if (!(buffer[0] == mtk_init_resp[1]))
1086 dnload.mtk_state = MTK_INIT_3;
1087 printf("Received init magic byte 2\n");
1088 rc = write(dnload.serial_fd.fd, &mtk_init_cmd[2], 1);
1091 if (!(buffer[0] == mtk_init_resp[2]))
1093 dnload.mtk_state = MTK_INIT_4;
1094 printf("Received init magic byte 3\n");
1095 rc = write(dnload.serial_fd.fd, &mtk_init_cmd[3], 1);
1098 if (!(buffer[0] == mtk_init_resp[3]))
1100 dnload.mtk_state = MTK_WAIT_WRITE_ACK;
1101 printf("Received init magic byte 4, requesting write\n");
1102 rc = write(dnload.serial_fd.fd, &mtk_command[0], 1);
1104 case MTK_WAIT_WRITE_ACK:
1105 if (!(buffer[0] == mtk_command[0]))
1107 dnload.mtk_state = MTK_WAIT_ADDR_ACK;
1108 printf("Received write ack, sending load address\n");
1110 rc = write(dnload.serial_fd.fd, &dnload.load_address,
1111 sizeof(dnload.load_address));
1113 case MTK_WAIT_ADDR_ACK:
1114 if (memcmp(buffer, dnload.load_address,
1115 sizeof(dnload.load_address)))
1117 printf("Received address ack from phone, sending loadsize\n");
1119 rc = read_file(dnload.filename);
1121 fprintf(stderr, "read_file(%s) failed with %d\n",
1122 dnload.filename, rc);
1125 dnload.block_number = 0;
1126 mtk_prepare_block();
1127 dnload.mtk_state = MTK_WAIT_SIZE_ACK;
1128 rc = write(dnload.serial_fd.fd, &dnload.mtk_send_size,
1129 sizeof(dnload.mtk_send_size));
1131 case MTK_WAIT_SIZE_ACK:
1132 if (memcmp(buffer, dnload.mtk_send_size,
1133 sizeof(dnload.mtk_send_size)))
1135 printf("Received size ack\n");
1136 dnload.expect_hdlc = 1;
1137 dnload.mtk_state = MTK_SENDING_BLOCKS;
1138 dnload.serial_fd.when = BSC_FD_READ | BSC_FD_WRITE;
1141 case MTK_SENDING_BLOCKS:
1142 if (!(buffer[0] == dnload.block[dnload.echo_bytecount]))
1143 printf("Warning: Byte %i of Block %i doesn't match,"
1144 " check your serial connection!\n",
1145 dnload.echo_bytecount, dnload.block_number);
1146 dnload.echo_bytecount++;
1148 if ((dnload.echo_bytecount+1) > MTK_BLOCK_SIZE) {
1149 if ( dnload.block_number == dnload.block_count) {
1150 rc = write(dnload.serial_fd.fd,
1151 &mtk_command[3], 1);
1152 printf("Sending branch command\n");
1153 dnload.expect_hdlc = 0;
1154 dnload.mtk_state = MTK_WAIT_BRANCH_CMD_ACK;
1157 printf("Received Block %i preparing next block\n",
1158 dnload.block_number);
1159 mtk_prepare_block();
1160 dnload.serial_fd.when = BSC_FD_READ | BSC_FD_WRITE;
1163 case MTK_WAIT_BRANCH_CMD_ACK:
1164 if (!(buffer[0] == mtk_command[3]))
1166 dnload.mtk_state = MTK_WAIT_BRANCH_ADDR_ACK;
1167 printf("Received branch command ack, sending address\n");
1169 rc = write(dnload.serial_fd.fd, &dnload.load_address,
1170 sizeof(dnload.load_address));
1172 case MTK_WAIT_BRANCH_ADDR_ACK:
1173 if (memcmp(buffer, dnload.load_address,
1174 sizeof(dnload.load_address)))
1176 printf("Received branch address ack, code should run now\n");
1177 serial_set_baudrate(MODEM_BAUDRATE);
1178 dnload.serial_fd.when = BSC_FD_READ;
1179 dnload.mtk_state = MTK_FINISHED;
1180 dnload.write_ptr = dnload.data;
1181 dnload.expect_hdlc = 1;
1191 static int serial_read(struct osmo_fd *fd, unsigned int flags)
1194 if (flags & BSC_FD_READ) {
1195 switch (dnload.mode) {
1197 rc = handle_read_romload();
1200 rc = handle_read_mtk();
1210 if (flags & BSC_FD_WRITE) {
1211 rc = handle_write();
1213 dnload.state = WAITING_PROMPT1;
1218 static int parse_mode(const char *arg)
1220 if (!strcasecmp(arg, "c123"))
1222 else if (!strcasecmp(arg, "c123xor"))
1223 return MODE_C123xor;
1224 else if (!strcasecmp(arg, "c140"))
1226 else if (!strcasecmp(arg, "c140xor"))
1227 return MODE_C140xor;
1228 else if (!strcasecmp(arg, "c155"))
1230 else if (!strcasecmp(arg, "romload"))
1231 return MODE_ROMLOAD;
1232 else if (!strcasecmp(arg, "mtk"))
1239 "[ -v | -h ] [ -d [t][r] ] [ -p /dev/ttyXXXX ]\n" \
1240 "\t\t [ -s /tmp/osmocom_l2 ]\n" \
1241 "\t\t [ -l /tmp/osmocom_loader ]\n" \
1242 "\t\t [ -m {c123,c123xor,c140,c140xor,c155,romload,mtk} ]\n" \
1243 "\t\t [ -c /to-be-chainloaded-file.bin ]\n" \
1244 "\t\t [ -i beacon-interval (mS) ]\n" \
1245 "\t\t file.bin\n\n" \
1246 "* Open serial port /dev/ttyXXXX (connected to your phone)\n" \
1247 "* Perform handshaking with the ramloader in the phone\n" \
1248 "* Download file.bin to the attached phone (base address 0x00800100)\n"
1250 static int usage(const char *name)
1252 printf("Usage: %s ", name);
1257 static int version(const char *name)
1259 printf("%s version %s\n", name, PACKAGE_VERSION);
1263 static int un_tool_read(struct osmo_fd *fd, unsigned int flags)
1266 uint16_t length = 0xffff;
1268 struct tool_connection *con = (struct tool_connection *)fd->data;
1272 rc = read(fd->fd, &buf + c, 2 - c);
1278 if(errno == EAGAIN) {
1281 fprintf(stderr, "Err from socket: %s\n", strerror(errno));
1287 length = ntohs(*(uint16_t*)buf);
1291 rc = read(fd->fd, &buf + c, length - c);
1297 if(errno == EAGAIN) {
1300 fprintf(stderr, "Err from socket: %s\n", strerror(errno));
1306 hdlc_send_to_phone(con->server->dlci, buf, length);
1312 osmo_fd_unregister(fd);
1313 llist_del(&con->entry);
1318 /* accept a new connection */
1319 static int tool_accept(struct osmo_fd *fd, unsigned int flags)
1321 struct tool_server *srv = (struct tool_server *)fd->data;
1322 struct tool_connection *con;
1323 struct sockaddr_un un_addr;
1327 len = sizeof(un_addr);
1328 rc = accept(fd->fd, (struct sockaddr *) &un_addr, &len);
1330 fprintf(stderr, "Failed to accept a new connection.\n");
1334 con = talloc_zero(NULL, struct tool_connection);
1336 fprintf(stderr, "Failed to create tool connection.\n");
1343 con->fd.when = BSC_FD_READ;
1344 con->fd.cb = un_tool_read;
1346 if (osmo_fd_register(&con->fd) != 0) {
1347 fprintf(stderr, "Failed to register the fd.\n");
1351 llist_add(&con->entry, &srv->connections);
1356 * Register and start a tool server
1358 static int register_tool_server(struct tool_server *ts,
1362 struct osmo_fd *bfd = &ts->bfd;
1363 struct sockaddr_un local;
1364 unsigned int namelen;
1367 bfd->fd = socket(AF_UNIX, SOCK_STREAM, 0);
1370 fprintf(stderr, "Failed to create Unix Domain Socket.\n");
1374 local.sun_family = AF_UNIX;
1375 strncpy(local.sun_path, path, sizeof(local.sun_path));
1376 local.sun_path[sizeof(local.sun_path) - 1] = '\0';
1377 unlink(local.sun_path);
1379 /* we use the same magic that X11 uses in Xtranssock.c for
1380 * calculating the proper length of the sockaddr */
1381 #if defined(BSD44SOCKETS) || defined(__UNIXWARE__)
1382 local.sun_len = strlen(local.sun_path);
1384 #if defined(BSD44SOCKETS) || defined(SUN_LEN)
1385 namelen = SUN_LEN(&local);
1387 namelen = strlen(local.sun_path) +
1388 offsetof(struct sockaddr_un, sun_path);
1391 rc = bind(bfd->fd, (struct sockaddr *) &local, namelen);
1393 fprintf(stderr, "Failed to bind the unix domain socket. '%s'\n",
1398 if (listen(bfd->fd, 0) != 0) {
1399 fprintf(stderr, "Failed to listen.\n");
1403 bfd->when = BSC_FD_READ;
1404 bfd->cb = tool_accept;
1408 INIT_LLIST_HEAD(&ts->connections);
1410 tool_server_for_dlci[dlci] = ts;
1412 sercomm_register_rx_cb(dlci, hdlc_tool_cb);
1414 if (osmo_fd_register(bfd) != 0) {
1415 fprintf(stderr, "Failed to register the bfd.\n");
1422 extern void hdlc_tpudbg_cb(uint8_t dlci, struct msgb *msg);
1424 void parse_debug(const char *str)
1435 printf("Unknown debug flag %c\n", *str);
1443 int main(int argc, char **argv)
1446 uint32_t tmp_load_address = ROMLOAD_ADDRESS;
1447 const char *serial_dev = "/dev/ttyUSB1";
1448 const char *layer2_un_path = "/tmp/osmocom_l2";
1449 const char *loader_un_path = "/tmp/osmocom_loader";
1451 dnload.mode = MODE_C123;
1452 dnload.chainload_filename = NULL;
1453 dnload.beacon_interval = DEFAULT_BEACON_INTERVAL;
1455 while ((opt = getopt(argc, argv, "d:hl:p:m:c:s:i:v")) != -1) {
1458 serial_dev = optarg;
1461 dnload.mode = parse_mode(optarg);
1462 if (dnload.mode < 0)
1466 layer2_un_path = optarg;
1469 loader_un_path = optarg;
1475 parse_debug(optarg);
1478 dnload.chainload_filename = optarg;
1481 dnload.beacon_interval = atoi(optarg) * 1000;
1490 if (argc <= optind) {
1491 dnload.filename = NULL;
1493 dnload.filename = argv[optind];
1496 dnload.serial_fd.fd = serial_init(serial_dev);
1497 if (dnload.serial_fd.fd < 0) {
1498 fprintf(stderr, "Cannot open serial device %s\n", serial_dev);
1502 if (osmo_fd_register(&dnload.serial_fd) != 0) {
1503 fprintf(stderr, "Failed to register the serial.\n");
1507 /* Set serial socket to non-blocking mode of operation */
1508 flags = fcntl(dnload.serial_fd.fd, F_GETFL);
1509 flags |= O_NONBLOCK;
1510 fcntl(dnload.serial_fd.fd, F_SETFL, flags);
1512 dnload.serial_fd.when = BSC_FD_READ;
1513 dnload.serial_fd.cb = serial_read;
1515 /* initialize the HDLC layer */
1517 sercomm_register_rx_cb(SC_DLCI_CONSOLE, hdlc_console_cb);
1518 sercomm_register_rx_cb(SC_DLCI_DEBUG, hdlc_tpudbg_cb);
1520 /* unix domain socket handling */
1521 if (register_tool_server(&dnload.layer2_server, layer2_un_path,
1522 SC_DLCI_L1A_L23) != 0)
1525 if (register_tool_server(&dnload.loader_server, loader_un_path,
1526 SC_DLCI_LOADER) != 0)
1529 /* if in romload mode, start our beacon timer */
1530 if (dnload.mode == MODE_ROMLOAD) {
1531 tmp_load_address = ROMLOAD_ADDRESS;
1532 serial_set_baudrate(ROMLOAD_INIT_BAUDRATE);
1533 tick_timer.cb = &beacon_timer_cb;
1534 tick_timer.data = &tick_timer;
1535 osmo_timer_schedule(&tick_timer, 0, dnload.beacon_interval);
1537 else if (dnload.mode == MODE_MTK) {
1538 tmp_load_address = MTK_ADDRESS;
1539 serial_set_baudrate(MTK_INIT_BAUDRATE);
1540 tick_timer.cb = &mtk_timer_cb;
1541 tick_timer.data = &tick_timer;
1542 osmo_timer_schedule(&tick_timer, 0, dnload.beacon_interval);
1545 dnload.load_address[0] = (tmp_load_address >> 24) & 0xff;
1546 dnload.load_address[1] = (tmp_load_address >> 16) & 0xff;
1547 dnload.load_address[2] = (tmp_load_address >> 8) & 0xff;
1548 dnload.load_address[3] = tmp_load_address & 0xff;
1551 if (osmo_select_main(0) < 0)
1555 close(dnload.serial_fd.fd);