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>
43 #include <osmocore/linuxlist.h>
44 #include <osmocore/select.h>
45 #include <osmocore/talloc.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 ROMLOAD_INIT_BAUDRATE B19200
55 #define ROMLOAD_DL_BAUDRATE B115200
56 #define ROMLOAD_BEACON_INTERVAL 50000
57 #define ROMLOAD_BLOCK_HDR_LEN 10
58 #define ROMLOAD_ADDRESS 0x820000
60 struct tool_server *tool_server_for_dlci[256];
63 * a connection from some other tool
65 struct tool_connection {
66 struct tool_server *server;
67 struct llist_head entry;
77 struct llist_head connections;
88 WAITING_IDENTIFICATION,
109 enum dnload_state state;
110 enum romload_state romload_state;
111 enum dnload_mode mode;
112 struct bsc_fd serial_fd;
117 /* data to be downloaded */
123 /* romload: block to be downloaded */
126 uint8_t block_number;
127 uint16_t block_payload_size;
128 int romload_dl_checksum;
131 struct tool_server layer2_server;
132 struct tool_server loader_server;
136 static struct dnload dnload;
138 /* Compal ramloader specific */
139 static const uint8_t phone_prompt1[] = { 0x1b, 0xf6, 0x02, 0x00, 0x41, 0x01, 0x40 };
140 static const uint8_t dnload_cmd[] = { 0x1b, 0xf6, 0x02, 0x00, 0x52, 0x01, 0x53 };
141 static const uint8_t phone_prompt2[] = { 0x1b, 0xf6, 0x02, 0x00, 0x41, 0x02, 0x43 };
142 static const uint8_t phone_ack[] = { 0x1b, 0xf6, 0x02, 0x00, 0x41, 0x03, 0x42 };
143 static const uint8_t phone_nack_magic[]= { 0x1b, 0xf6, 0x02, 0x00, 0x41, 0x03, 0x57 };
144 static const uint8_t phone_nack[] = { 0x1b, 0xf6, 0x02, 0x00, 0x45, 0x53, 0x16 };
145 static const uint8_t ftmtool[] = { 0x66, 0x74, 0x6d, 0x74, 0x6f, 0x6f, 0x6c };
146 static const uint8_t phone_magic[] = { 0x31, 0x30, 0x30, 0x33 }; /* "1003" */
148 /* romloader specific */
149 static const uint8_t romload_ident_cmd[] = { 0x3c, 0x69 }; /* <i */
150 static const uint8_t romload_abort_cmd[] = { 0x3c, 0x61 }; /* <a */
151 static const uint8_t romload_write_cmd[] = { 0x3c, 0x77 }; /* <w */
152 static const uint8_t romload_checksum_cmd[] = { 0x3c, 0x63 }; /* <c */
153 static const uint8_t romload_branch_cmd[] = { 0x3c, 0x62 }; /* <b */
154 static const uint8_t romload_ident_ack[] = { 0x3e, 0x69 }; /* >i */
155 static const uint8_t romload_param_ack[] = { 0x3e, 0x70 }; /* >p */
156 static const uint8_t romload_param_nack[] = { 0x3e, 0x50 }; /* >P */
157 static const uint8_t romload_block_ack[] = { 0x3e, 0x77 }; /* >w */
158 static const uint8_t romload_block_nack[] = { 0x3e, 0x57 }; /* >W */
159 static const uint8_t romload_checksum_ack[] = { 0x3e, 0x63 }; /* >c */
160 static const uint8_t romload_checksum_nack[] = { 0x3e, 0x43 }; /* >C */
161 static const uint8_t romload_branch_ack[] = { 0x3e, 0x62 }; /* >b */
162 static const uint8_t romload_branch_nack[] = { 0x3e, 0x42 }; /* >B */
164 /* romload_param: {"<p", uint8_t baudrate, uint8_t dpll, uint16_t memory_config,
165 * uint8_t strobe_af, uint32_t uart_timeout} */
167 static const uint8_t romload_param[] = { 0x3c, 0x70, 0x00, 0x00, 0x00, 0x04,
168 0x00, 0x00, 0x00, 0x00, 0x00 };
170 /* The C123 has a hard-coded check inside the ramloader that requires the following
171 * bytes to be always the first four bytes of the image */
172 static const uint8_t data_hdr_c123[] = { 0xee, 0x4c, 0x9f, 0x63 };
174 /* The C155 doesn't have some strange restriction on what the first four bytes have
175 * to be, but it starts the ramloader in THUMB mode. We use the following four bytes
176 * to switch back to ARM mode:
178 800102: 46c0 nop ; (mov r8, r8)
180 static const uint8_t data_hdr_c155[] = { 0x78, 0x47, 0xc0, 0x46 };
182 /* FIXME: this routine is more or less what openbsc/src/rs232:rs232_setup()
183 * does, we should move it to libosmocore at some point */
184 static int serial_init(const char *serial_port)
186 int rc, serial_fd, v24;
189 serial_fd = open(serial_port, O_RDWR | O_NOCTTY | O_NDELAY);
191 perror("cannot open serial port");
195 //fcntl(serial_fd, F_SETFL, 0);
197 /* Configure serial interface */
198 rc = tcgetattr(serial_fd, &tio);
200 perror("tcgetattr()");
203 cfsetispeed(&tio, MODEM_BAUDRATE);
204 cfsetospeed(&tio, MODEM_BAUDRATE);
205 tio.c_cflag &= ~(PARENB | CSTOPB | CSIZE | CRTSCTS);
206 tio.c_cflag |= (CREAD | CLOCAL | CS8);
207 tio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
208 tio.c_iflag |= (INPCK | ISTRIP);
209 tio.c_iflag &= ~(ISTRIP | IXON | IXOFF | IGNBRK | INLCR | ICRNL | IGNCR);
210 tio.c_oflag &= ~(OPOST | ONLCR);
211 rc = tcsetattr(serial_fd, TCSANOW, &tio);
213 perror("tcsetattr()");
217 /* set ready to read/write */
218 v24 = TIOCM_DTR | TIOCM_RTS;
219 rc = ioctl(serial_fd, TIOCMBIS, &v24);
221 perror("ioctl(TIOCMBIS)");
228 static int serial_set_baudrate(speed_t baudrate)
233 cfsetispeed(&tio, baudrate);
234 cfsetospeed(&tio, baudrate);
236 rc = tcsetattr(dnload.serial_fd.fd, TCSANOW, &tio);
240 static void reload_beacon_timer(void)
242 struct itimerval t_val;
245 /* load timer to our <i beacon interval */
246 bzero(&t_val, sizeof(t_val));
247 t_val.it_value.tv_usec = ROMLOAD_BEACON_INTERVAL;
249 if ((rc = setitimer(ITIMER_REAL, &t_val, NULL)) < 0) {
250 fprintf(stderr, "Error in setitimer()\n");
255 static void beacon_timer_cb(int signr)
259 if (dnload.romload_state == WAITING_IDENTIFICATION) {
260 printf("Sending beacon...\n");
261 rc = write(dnload.serial_fd.fd, romload_ident_cmd,
262 sizeof(romload_ident_cmd));
264 if (!(rc == sizeof(romload_ident_cmd)))
265 printf("Error sending identification beacon\n");
267 reload_beacon_timer();
271 static void start_beacon_timer(void)
273 if (signal(SIGALRM, beacon_timer_cb) == SIG_ERR) {
274 fprintf(stderr, "Cannot register signal handler\n");
278 reload_beacon_timer();
281 /* Read the to-be-downloaded file, prepend header and length, append XOR sum */
282 int read_file(const char *filename)
286 const uint8_t *hdr = NULL;
292 uint8_t running_xor = 0x02;
294 fd = open(filename, O_RDONLY);
296 perror("opening file");
301 if (st.st_size > MAX_DNLOAD_SIZE) {
302 fprintf(stderr, "The maximum file size is 64kBytes (%u bytes)\n",
312 if (dnload.mode == MODE_C140 || dnload.mode == MODE_C140xor) {
313 if (st.st_size < (MAGIC_OFFSET + sizeof(phone_magic)))
314 payload_size = MAGIC_OFFSET + sizeof(phone_magic);
316 printf("\nThe filesize is larger than 15kb, code on "
317 "the magic address will be overwritten!\nUse "
318 "loader.bin and upload the application with "
319 "osmoload instead!\n\n");
320 payload_size = st.st_size;
323 payload_size = st.st_size;
325 dnload.data = malloc(MAX_HDR_SIZE + payload_size);
329 fprintf(stderr, "No memory\n");
333 /* copy in the header, if any */
334 switch (dnload.mode) {
337 hdr_len = sizeof(data_hdr_c155);
344 hdr_len = sizeof(data_hdr_c123);
353 memcpy(dnload.data, hdr, hdr_len);
355 /* 2 bytes for length + header */
356 file_data = dnload.data + 2 + hdr_len;
358 /* write the length, keep running XOR */
359 tot_len = hdr_len + payload_size;
360 nibble = tot_len >> 8;
361 dnload.data[0] = nibble;
362 running_xor ^= nibble;
363 nibble = tot_len & 0xff;
364 dnload.data[1] = nibble;
365 running_xor ^= nibble;
367 if (hdr_len && hdr) {
368 memcpy(dnload.data+2, hdr, hdr_len);
370 for (i = 0; i < hdr_len; i++)
371 running_xor ^= hdr[i];
374 rc = read(fd, file_data, st.st_size);
376 perror("error reading file\n");
382 if (rc < st.st_size) {
386 fprintf(stderr, "Short read of file (%d < %d)\n",
387 rc, (int)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 filename, (int)st.st_size, hdr_len, dnload.data_len);
419 static void hexdump(const uint8_t *data, unsigned int len)
421 const uint8_t *bufptr = data;
424 for (n=0; n < len; n++, bufptr++)
425 printf("%02x ", *bufptr);
429 static int romload_prepare_block(void)
433 int block_checksum = 5;
437 uint32_t block_address;
439 dnload.block_len = ROMLOAD_BLOCK_HDR_LEN + dnload.block_payload_size;
441 /* if first block, allocate memory */
442 if (!dnload.block_number){
443 dnload.block = malloc(dnload.block_len);
445 fprintf(stderr, "No memory\n");
448 dnload.romload_dl_checksum = 0;
449 /* initialize write pointer to start of data */
450 dnload.write_ptr = dnload.data;
453 block_address = ROMLOAD_ADDRESS +
454 (dnload.block_number * dnload.block_payload_size);
456 /* prepare our block header (10 bytes) */
457 memcpy(dnload.block, romload_write_cmd, sizeof(romload_write_cmd));
458 dnload.block[2] = 0x01; /* block index */
459 /* should normally be the block number, but hangs when sending !0x01 */
460 dnload.block[3] = 0x01; /* dnload.block_number+1 */
461 dnload.block[4] = (dnload.block_payload_size >> 8) & 0xff;
462 dnload.block[5] = dnload.block_payload_size & 0xff;
463 dnload.block[6] = (block_address >> 24) & 0xff;
464 dnload.block[7] = (block_address >> 16) & 0xff;
465 dnload.block[8] = (block_address >> 8) & 0xff;
466 dnload.block[9] = block_address & 0xff;
468 block_data = dnload.block + ROMLOAD_BLOCK_HDR_LEN;
469 dnload.write_ptr = dnload.data + 2 +
470 (dnload.block_payload_size * dnload.block_number);
472 remaining_bytes = dnload.data_len-3 -
473 (dnload.block_payload_size * dnload.block_number);
475 memcpy(block_data, dnload.write_ptr, dnload.block_payload_size);
477 if (remaining_bytes <= dnload.block_payload_size) {
478 fill_bytes = (dnload.block_payload_size - remaining_bytes);
479 printf("Preparing the last block, filling %i bytes,",
481 memset(block_data + remaining_bytes, 0x00, fill_bytes);
482 dnload.romload_state = SENDING_LAST_BLOCK;
484 dnload.romload_state = SENDING_BLOCKS;
485 printf("Preparing block %i,", dnload.block_number+1);
488 /* block checksum is lsb of !(5 + block_size_lsb + block_address + data) */
489 for (i = 5; i < ROMLOAD_BLOCK_HDR_LEN + dnload.block_payload_size; i++)
490 block_checksum += dnload.block[i];
492 /* checksum is lsb of !(sum of LSBs of all block checksums) */
493 printf(" block checksum is 0x%02x \n", ~(block_checksum) & 0xff);
494 dnload.romload_dl_checksum += ~(block_checksum) & 0xff;
496 /* initialize block pointer to start of block */
497 dnload.block_ptr = dnload.block;
499 dnload.block_number++;
500 dnload.serial_fd.when = BSC_FD_READ | BSC_FD_WRITE;
504 static int handle_write_block(void)
506 int bytes_left, write_len, rc;
508 printf("handle_write_block(): ");
510 if (dnload.block_ptr >= dnload.block + dnload.block_len) {
511 printf("Block %i finished\n", dnload.block_number);
512 dnload.write_ptr = dnload.data;
513 dnload.serial_fd.when &= ~BSC_FD_WRITE;
514 if (dnload.romload_state == SENDING_LAST_BLOCK) {
515 dnload.romload_state = LAST_BLOCK_SENT;
516 printf("Finished, sent %i blocks in total\n",
517 dnload.block_number);
519 dnload.romload_state = WAITING_BLOCK_ACK;
525 /* try to write a maximum of block_len bytes */
526 bytes_left = (dnload.block + dnload.block_len) - dnload.block_ptr;
527 write_len = dnload.block_len;
528 if (bytes_left < dnload.block_len)
529 write_len = bytes_left;
531 rc = write(dnload.serial_fd.fd, dnload.block_ptr, write_len);
533 perror("Error during write");
537 dnload.block_ptr += rc;
539 printf("%u bytes (%tu/%u)\n", rc, dnload.block_ptr - dnload.block,
545 #define WRITE_BLOCK 4096
547 static int handle_write_dnload(void)
549 int bytes_left, write_len, rc;
550 uint8_t xor_init = 0x02;
552 printf("handle_write(): ");
553 if (dnload.write_ptr == dnload.data) {
554 /* no bytes have been transferred yet */
555 switch (dnload.mode) {
559 rc = write(dnload.serial_fd.fd, &xor_init, 1);
564 } else if (dnload.write_ptr >= dnload.data + dnload.data_len) {
565 printf("finished\n");
566 dnload.write_ptr = dnload.data;
567 dnload.serial_fd.when &= ~BSC_FD_WRITE;
571 /* try to write a maximum of WRITE_BLOCK bytes */
572 bytes_left = (dnload.data + dnload.data_len) - dnload.write_ptr;
573 write_len = WRITE_BLOCK;
574 if (bytes_left < WRITE_BLOCK)
575 write_len = bytes_left;
577 rc = write(dnload.serial_fd.fd, dnload.write_ptr, write_len);
579 perror("Error during write");
583 dnload.write_ptr += rc;
585 printf("%u bytes (%tu/%u)\n", rc, dnload.write_ptr - dnload.data,
591 static int handle_sercomm_write(void)
595 if (sercomm_drv_pull(&c) != 0) {
596 if (write(dnload.serial_fd.fd, &c, 1) != 1)
597 perror("short write");
599 dnload.serial_fd.when &= ~BSC_FD_WRITE;
604 static int handle_write(void)
606 if (dnload.mode == MODE_ROMLOAD) {
607 switch (dnload.romload_state) {
609 case SENDING_LAST_BLOCK:
610 return handle_write_block();
612 return handle_sercomm_write();
615 switch (dnload.state) {
617 return handle_write_dnload();
619 return handle_sercomm_write();
626 static uint8_t buffer[sizeof(phone_prompt1)];
627 static uint8_t *bufptr = buffer;
629 static void hdlc_send_to_phone(uint8_t dlci, uint8_t *data, int len)
634 printf("hdlc_send_to_phone(dlci=%u): ", dlci);
638 fprintf(stderr, "Too much data to send. %u\n", len);
642 /* push the message into the stack */
643 msg = sercomm_alloc_msgb(512);
645 fprintf(stderr, "Failed to create data for the frame.\n");
650 dest = msgb_put(msg, len);
651 memcpy(dest, data, len);
653 sercomm_sendmsg(dlci, msg);
655 dnload.serial_fd.when |= BSC_FD_WRITE;
658 static void hdlc_console_cb(uint8_t dlci, struct msgb *msg)
662 rc = write(1, msg->data, msg->len);
666 static void hdlc_tool_cb(uint8_t dlci, struct msgb *msg)
668 struct tool_server *srv = tool_server_for_dlci[dlci];
671 struct tool_connection *con;
674 len = (u_int16_t *) msgb_push(msg, 2);
675 *len = htons(msg->len - sizeof(*len));
677 llist_for_each_entry(con, &srv->connections, entry) {
678 if (write(con->fd.fd, msg->data, msg->len) != msg->len) {
680 "Failed to write msg to the socket..\n");
689 static void print_hdlc(uint8_t *buffer, int length)
693 for (i = 0; i < length; ++i)
694 if (sercomm_drv_rx_char(buffer[i]) == 0)
695 printf("Dropping sample '%c'\n", buffer[i]);
698 static int handle_buffer(int buf_used_len)
700 int nbytes, buf_left;
702 buf_left = buf_used_len - (bufptr - buffer);
704 memmove(buffer, buffer+1, buf_used_len-1);
709 nbytes = read(dnload.serial_fd.fd, bufptr, buf_left);
713 if (!dnload.print_hdlc) {
714 printf("got %i bytes from modem, ", nbytes);
715 printf("data looks like: ");
716 hexdump(bufptr, nbytes);
718 print_hdlc(bufptr, nbytes);
724 /* Compal ramloader */
725 static int handle_read(void)
729 nbytes = handle_buffer(sizeof(buffer));
733 if (!memcmp(buffer, phone_prompt1, sizeof(phone_prompt1))) {
734 printf("Received PROMPT1 from phone, responding with CMD\n");
735 dnload.print_hdlc = 0;
736 dnload.state = WAITING_PROMPT2;
737 rc = write(dnload.serial_fd.fd, dnload_cmd, sizeof(dnload_cmd));
740 rc = read_file(dnload.filename);
742 fprintf(stderr, "read_file(%s) failed with %d\n",
743 dnload.filename, rc);
746 } else if (!memcmp(buffer, phone_prompt2, sizeof(phone_prompt2))) {
747 printf("Received PROMPT2 from phone, starting download\n");
748 dnload.serial_fd.when = BSC_FD_READ | BSC_FD_WRITE;
749 dnload.state = DOWNLOADING;
750 } else if (!memcmp(buffer, phone_ack, sizeof(phone_ack))) {
751 printf("Received DOWNLOAD ACK from phone, your code is running now!\n");
752 dnload.serial_fd.when = BSC_FD_READ;
753 dnload.state = WAITING_PROMPT1;
754 dnload.write_ptr = dnload.data;
755 dnload.print_hdlc = 1;
756 } else if (!memcmp(buffer, phone_nack, sizeof(phone_nack))) {
757 printf("Received DOWNLOAD NACK from phone, something went wrong :(\n");
758 dnload.serial_fd.when = BSC_FD_READ;
759 dnload.state = WAITING_PROMPT1;
760 dnload.write_ptr = dnload.data;
761 } else if (!memcmp(buffer, phone_nack_magic, sizeof(phone_nack_magic))) {
762 printf("Received MAGIC NACK from phone, you need to have \"1003\" at 0x803ce0\n");
763 dnload.serial_fd.when = BSC_FD_READ;
764 dnload.state = WAITING_PROMPT1;
765 dnload.write_ptr = dnload.data;
766 } else if (!memcmp(buffer, ftmtool, sizeof(ftmtool))) {
767 printf("Received FTMTOOL from phone, ramloader has aborted\n");
768 dnload.serial_fd.when = BSC_FD_READ;
769 dnload.state = WAITING_PROMPT1;
770 dnload.write_ptr = dnload.data;
777 /* "Calypso non-secure romloader" */
778 static int handle_read_romload(void)
780 int rc, nbytes, buf_used_len;
782 /* virtually limit buffer length for romloader, since responses
783 * are shorter and vary in length */
785 switch (dnload.romload_state) {
786 case WAITING_PARAM_ACK:
787 buf_used_len = 4; /* ">p" + uint16_t len */
789 case WAITING_CHECKSUM_ACK:
790 buf_used_len = 3; /* ">c" + uint8_t checksum */
793 buf_used_len = sizeof(buffer);
796 buf_used_len = 2; /* ">*" */
799 nbytes = handle_buffer(buf_used_len);
803 switch (dnload.romload_state) {
804 case WAITING_IDENTIFICATION:
805 if (memcmp(buffer, romload_ident_ack,
806 sizeof(romload_ident_ack)))
809 printf("Received ident ack from phone, sending "
810 "parameter sequence\n");
811 dnload.print_hdlc = 1;
812 dnload.romload_state = WAITING_PARAM_ACK;
813 rc = write(dnload.serial_fd.fd, romload_param,
814 sizeof(romload_param));
816 rc = read_file(dnload.filename);
818 fprintf(stderr, "read_file(%s) failed with %d\n",
819 dnload.filename, rc);
823 case WAITING_PARAM_ACK:
824 if (memcmp(buffer, romload_param_ack,
825 sizeof(romload_param_ack)))
828 printf("Received parameter ack from phone, "
829 "starting download\n");
830 serial_set_baudrate(ROMLOAD_DL_BAUDRATE);
831 /* let the target's UART settle after changing baud*/
832 usleep(ROMLOAD_BEACON_INTERVAL*2);
834 /* using the max blocksize the phone tells us */
835 dnload.block_payload_size = ((buffer[3] << 8) + buffer[2]);
836 printf("Used blocksize for download is %i bytes\n",
837 dnload.block_payload_size);
838 dnload.block_payload_size -= ROMLOAD_BLOCK_HDR_LEN;
839 dnload.romload_state = SENDING_BLOCKS;
840 dnload.block_number = 0;
841 romload_prepare_block();
844 case WAITING_BLOCK_ACK:
845 case LAST_BLOCK_SENT:
846 if (!memcmp(buffer, romload_block_ack,
847 sizeof(romload_block_ack))) {
848 printf("Received block ack from phone\n");
849 if (dnload.romload_state == LAST_BLOCK_SENT) {
850 /* send the checksum */
851 uint8_t final_checksum =
852 (~(dnload.romload_dl_checksum) & 0xff);
853 printf("Sending checksum: 0x%02x \n",
855 rc = write(dnload.serial_fd.fd,
856 romload_checksum_cmd,
857 sizeof(romload_checksum_cmd));
858 rc = write(dnload.serial_fd.fd,
860 dnload.romload_state = WAITING_CHECKSUM_ACK;
862 romload_prepare_block();
863 } else if (!memcmp(buffer, romload_block_nack,
864 sizeof(romload_block_nack))) {
865 printf("Received block nack from phone, "
866 "something went wrong, aborting\n");
867 serial_set_baudrate(ROMLOAD_INIT_BAUDRATE);
868 dnload.romload_state = WAITING_IDENTIFICATION;
869 usleep(ROMLOAD_BEACON_INTERVAL*2);
870 reload_beacon_timer();
873 case WAITING_CHECKSUM_ACK:
874 if (!memcmp(buffer, romload_checksum_ack,
875 sizeof(romload_checksum_ack))) {
876 printf("Checksum on phone side matches, "
877 "let's branch to your code\n");
879 uint32_t branch_address_32 = ROMLOAD_ADDRESS;
880 uint8_t branch_address[4];
881 branch_address[0] = (branch_address_32 >> 24) & 0xff;
882 branch_address[1] = (branch_address_32 >> 16) & 0xff;
883 branch_address[2] = (branch_address_32 >> 8) & 0xff;
884 branch_address[3] = branch_address_32 & 0xff;
885 printf("Branching to 0x%08x\n", branch_address_32);
887 rc = write(dnload.serial_fd.fd, romload_branch_cmd,
888 sizeof(romload_branch_cmd));
889 rc = write(dnload.serial_fd.fd, &branch_address, 4);
890 dnload.romload_state = WAITING_BRANCH_ACK;
892 } else if (!memcmp(buffer, romload_checksum_nack,
893 sizeof(romload_checksum_nack))) {
894 printf("Checksum on phone side (0x%02x) doesn't "
895 "match ours, aborting\n", buffer[2]);
896 serial_set_baudrate(ROMLOAD_INIT_BAUDRATE);
897 dnload.romload_state = WAITING_IDENTIFICATION;
898 usleep(ROMLOAD_BEACON_INTERVAL*2);
899 reload_beacon_timer();
903 case WAITING_BRANCH_ACK:
904 if (!memcmp(buffer, romload_branch_ack,
905 sizeof(romload_branch_ack))) {
906 printf("Received branch ack, your code is running now!\n");
907 dnload.serial_fd.when = BSC_FD_READ;
908 dnload.romload_state = FINISHED;
909 dnload.write_ptr = dnload.data;
910 dnload.print_hdlc = 1;
911 } else if (!memcmp(buffer, romload_branch_nack,
912 sizeof(romload_branch_nack))) {
913 printf("Received branch nack, aborting\n");
914 serial_set_baudrate(ROMLOAD_INIT_BAUDRATE);
915 dnload.romload_state = WAITING_IDENTIFICATION;
916 usleep(ROMLOAD_BEACON_INTERVAL*2);
917 reload_beacon_timer();
928 static int serial_read(struct bsc_fd *fd, unsigned int flags)
931 if (flags & BSC_FD_READ) {
932 if (dnload.mode == MODE_ROMLOAD)
933 rc = handle_read_romload();
941 if (flags & BSC_FD_WRITE) {
944 dnload.state = WAITING_PROMPT1;
949 static int parse_mode(const char *arg)
951 if (!strcasecmp(arg, "c123"))
953 else if (!strcasecmp(arg, "c123xor"))
955 else if (!strcasecmp(arg, "c140"))
957 else if (!strcasecmp(arg, "c140xor"))
959 else if (!strcasecmp(arg, "c155"))
961 else if (!strcasecmp(arg, "romload"))
968 "[ -v | -h ] [ -p /dev/ttyXXXX ] [ -s /tmp/osmocom_l2 ]\n" \
969 "\t\t[ -l /tmp/osmocom_loader ]\n" \
970 "\t\t[ -m {c123,c123xor,c140,c140xor,c155,romload} ]\n" \
971 "\t\t file.bin\n\n" \
972 "* Open serial port /dev/ttyXXXX (connected to your phone)\n" \
973 "* Perform handshaking with the ramloader in the phone\n" \
974 "* Download file.bin to the attached phone (base address 0x00800100)\n"
976 static int usage(const char *name)
978 printf("Usage: %s ", name);
983 static int version(const char *name)
985 printf("%s version %s\n", name, PACKAGE_VERSION);
989 static int un_tool_read(struct bsc_fd *fd, unsigned int flags)
992 u_int16_t length = 0xffff;
994 struct tool_connection *con = (struct tool_connection *)fd->data;
998 rc = read(fd->fd, &buf + c, 2 - c);
1004 if(errno == EAGAIN) {
1007 fprintf(stderr, "Err from socket: %s\n", strerror(errno));
1013 length = ntohs(*(u_int16_t*)buf);
1017 rc = read(fd->fd, &buf + c, length - c);
1023 if(errno == EAGAIN) {
1026 fprintf(stderr, "Err from socket: %s\n", strerror(errno));
1032 hdlc_send_to_phone(con->server->dlci, buf, length);
1038 bsc_unregister_fd(fd);
1039 llist_del(&con->entry);
1044 /* accept a new connection */
1045 static int tool_accept(struct bsc_fd *fd, unsigned int flags)
1047 struct tool_server *srv = (struct tool_server *)fd->data;
1048 struct tool_connection *con;
1049 struct sockaddr_un un_addr;
1053 len = sizeof(un_addr);
1054 rc = accept(fd->fd, (struct sockaddr *) &un_addr, &len);
1056 fprintf(stderr, "Failed to accept a new connection.\n");
1060 con = talloc_zero(NULL, struct tool_connection);
1062 fprintf(stderr, "Failed to create tool connection.\n");
1069 con->fd.when = BSC_FD_READ;
1070 con->fd.cb = un_tool_read;
1072 if (bsc_register_fd(&con->fd) != 0) {
1073 fprintf(stderr, "Failed to register the fd.\n");
1077 llist_add(&con->entry, &srv->connections);
1082 * Register and start a tool server
1084 static int register_tool_server(struct tool_server *ts,
1088 struct bsc_fd *bfd = &ts->bfd;
1089 struct sockaddr_un local;
1090 unsigned int namelen;
1093 bfd->fd = socket(AF_UNIX, SOCK_STREAM, 0);
1096 fprintf(stderr, "Failed to create Unix Domain Socket.\n");
1100 local.sun_family = AF_UNIX;
1101 strncpy(local.sun_path, path, sizeof(local.sun_path));
1102 local.sun_path[sizeof(local.sun_path) - 1] = '\0';
1103 unlink(local.sun_path);
1105 /* we use the same magic that X11 uses in Xtranssock.c for
1106 * calculating the proper length of the sockaddr */
1107 #if defined(BSD44SOCKETS) || defined(__UNIXWARE__)
1108 local.sun_len = strlen(local.sun_path);
1110 #if defined(BSD44SOCKETS) || defined(SUN_LEN)
1111 namelen = SUN_LEN(&local);
1113 namelen = strlen(local.sun_path) +
1114 offsetof(struct sockaddr_un, sun_path);
1117 rc = bind(bfd->fd, (struct sockaddr *) &local, namelen);
1119 fprintf(stderr, "Failed to bind the unix domain socket. '%s'\n",
1124 if (listen(bfd->fd, 0) != 0) {
1125 fprintf(stderr, "Failed to listen.\n");
1129 bfd->when = BSC_FD_READ;
1130 bfd->cb = tool_accept;
1134 INIT_LLIST_HEAD(&ts->connections);
1136 tool_server_for_dlci[dlci] = ts;
1138 sercomm_register_rx_cb(dlci, hdlc_tool_cb);
1140 if (bsc_register_fd(bfd) != 0) {
1141 fprintf(stderr, "Failed to register the bfd.\n");
1148 extern void hdlc_tpudbg_cb(uint8_t dlci, struct msgb *msg);
1150 int main(int argc, char **argv)
1153 const char *serial_dev = "/dev/ttyUSB1";
1154 const char *layer2_un_path = "/tmp/osmocom_l2";
1155 const char *loader_un_path = "/tmp/osmocom_loader";
1157 dnload.mode = MODE_C123;
1159 while ((opt = getopt(argc, argv, "hl:p:m:s:v")) != -1) {
1162 serial_dev = optarg;
1165 dnload.mode = parse_mode(optarg);
1166 if (dnload.mode < 0)
1170 layer2_un_path = optarg;
1173 loader_un_path = optarg;
1185 if (argc <= optind) {
1186 fprintf(stderr, "You have to specify the filename\n");
1190 dnload.filename = argv[optind];
1192 dnload.serial_fd.fd = serial_init(serial_dev);
1193 if (dnload.serial_fd.fd < 0) {
1194 fprintf(stderr, "Cannot open serial device %s\n", serial_dev);
1198 if (bsc_register_fd(&dnload.serial_fd) != 0) {
1199 fprintf(stderr, "Failed to register the serial.\n");
1203 /* Set serial socket to non-blocking mode of operation */
1204 flags = fcntl(dnload.serial_fd.fd, F_GETFL);
1205 flags |= O_NONBLOCK;
1206 fcntl(dnload.serial_fd.fd, F_SETFL, flags);
1208 dnload.serial_fd.when = BSC_FD_READ;
1209 dnload.serial_fd.cb = serial_read;
1211 /* initialize the HDLC layer */
1213 sercomm_register_rx_cb(SC_DLCI_CONSOLE, hdlc_console_cb);
1214 sercomm_register_rx_cb(SC_DLCI_DEBUG, hdlc_tpudbg_cb);
1216 /* unix domain socket handling */
1217 if (register_tool_server(&dnload.layer2_server, layer2_un_path,
1218 SC_DLCI_L1A_L23) != 0)
1221 if (register_tool_server(&dnload.loader_server, loader_un_path,
1222 SC_DLCI_LOADER) != 0)
1225 /* if in romload mode, start our beacon timer */
1226 if (dnload.mode == MODE_ROMLOAD) {
1227 serial_set_baudrate(ROMLOAD_INIT_BAUDRATE);
1228 start_beacon_timer();
1234 close(dnload.serial_fd.fd);