10 #include <sys/types.h>
11 #include <sys/socket.h>
17 #include <osmocore/linuxlist.h>
18 #include <osmocore/select.h>
19 #include <osmocore/talloc.h>
21 #include <arpa/inet.h>
23 //#include "version.h"
25 #define MODEM_BAUDRATE B115200
26 #define MAX_DNLOAD_SIZE 0xFFFF
27 #define MAX_HDR_SIZE 128
29 struct tool_server *tool_server_for_dlci[256];
32 * a connection from some other tool
34 struct tool_connection {
35 struct tool_server *server;
36 struct llist_head entry;
46 struct llist_head connections;
63 enum dnload_state state;
64 enum dnload_mode mode;
65 struct bsc_fd serial_fd;
70 /* data to be downloaded */
76 struct tool_server layer2_server;
77 struct tool_server loader_server;
81 static struct dnload dnload;
83 static const uint8_t phone_prompt1[] = { 0x1b, 0xf6, 0x02, 0x00, 0x41, 0x01, 0x40 };
84 static const uint8_t dnload_cmd[] = { 0x1b, 0xf6, 0x02, 0x00, 0x52, 0x01, 0x53 };
85 static const uint8_t phone_prompt2[] = { 0x1b, 0xf6, 0x02, 0x00, 0x41, 0x02, 0x43 };
86 static const uint8_t phone_ack[] = { 0x1b, 0xf6, 0x02, 0x00, 0x41, 0x03, 0x42 };
87 static const uint8_t phone_nack_magic[]= { 0x1b, 0xf6, 0x02, 0x00, 0x41, 0x03, 0x57 };
88 static const uint8_t phone_nack[] = { 0x1b, 0xf6, 0x02, 0x00, 0x45, 0x53, 0x16 };
89 static const uint8_t ftmtool[] = { "ftmtool" };
91 /* The C123 has a hard-coded check inside the ramloder that requires the following
92 * bytes to be always the first four bytes of the image */
93 static const uint8_t data_hdr_c123[] = { 0xee, 0x4c, 0x9f, 0x63 };
95 /* The C155 doesn't have some strange restriction on what the first four bytes have
96 * to be, but it starts the ramloader in THUMB mode. We use the following four bytes
97 * to switch back to ARM mode:
99 800102: 46c0 nop ; (mov r8, r8)
101 static const uint8_t data_hdr_c155[] = { 0x78, 0x47, 0xc0, 0x46 };
103 static const uint8_t dummy_data[] = { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde };
105 static int serial_init(const char *serial_dev)
107 struct termios options;
110 fd = open(serial_dev, O_RDWR | O_NOCTTY | O_NDELAY);
114 fcntl(fd, F_SETFL, 0);
116 /* Configure serial interface */
117 tcgetattr(fd, &options);
119 cfsetispeed(&options, MODEM_BAUDRATE);
120 cfsetospeed(&options, MODEM_BAUDRATE);
123 options.c_cflag &= ~PARENB;
124 options.c_cflag &= ~CSTOPB;
125 options.c_cflag &= ~CSIZE;
126 options.c_cflag |= CS8;
128 /* hardware flow control off */
129 options.c_cflag &= ~CRTSCTS;
131 /* software flow control off */
132 options.c_iflag &= ~(IXON | IXOFF | IXANY);
134 /* we want raw i/o */
135 options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
136 options.c_iflag &= ~(INLCR | ICRNL | IGNCR);
137 options.c_oflag &= ~(ONLCR);
139 options.c_cc[VMIN] = 1;
140 options.c_cc[VTIME] = 0;
141 options.c_cc[VINTR] = 0;
142 options.c_cc[VQUIT] = 0;
143 options.c_cc[VSTART] = 0;
144 options.c_cc[VSTOP] = 0;
145 options.c_cc[VSUSP] = 0;
147 tcsetattr(fd, TCSANOW, &options);
149 /* set ready to read/write */
150 v24 = TIOCM_DTR | TIOCM_RTS;
151 ioctl(fd, TIOCMBIS, &v24);
156 /* Read the to-be-downloaded file, prepend header and length, append XOR sum */
157 int read_file(const char *filename)
161 const uint8_t *hdr = NULL;
166 uint8_t running_xor = 0x02;
168 fd = open(filename, O_RDONLY);
170 perror("opening file");
175 if (st.st_size > MAX_DNLOAD_SIZE) {
176 fprintf(stderr, "The maximum file size is 64kBytes (%u bytes)\n",
186 dnload.data = malloc(MAX_HDR_SIZE + st.st_size);
189 fprintf(stderr, "No memory\n");
193 /* copy in the header, if any */
194 switch (dnload.mode) {
197 hdr_len = sizeof(data_hdr_c155);
202 hdr_len = sizeof(data_hdr_c123);
209 memcpy(dnload.data, hdr, hdr_len);
211 /* 2 bytes for length + header */
212 file_data = dnload.data + 2 + hdr_len;
214 /* write the length, keep running XOR */
215 tot_len = hdr_len + st.st_size;
216 nibble = tot_len >> 8;
217 dnload.data[0] = nibble;
218 running_xor ^= nibble;
219 nibble = tot_len & 0xff;
220 dnload.data[1] = nibble;
221 running_xor ^= nibble;
223 if (hdr_len && hdr) {
224 memcpy(dnload.data+2, hdr, hdr_len);
226 for (i = 0; i < hdr_len; i++)
227 running_xor ^= hdr[i];
230 rc = read(fd, file_data, st.st_size);
232 perror("error reading file\n");
238 if (rc < st.st_size) {
242 fprintf(stderr, "Short read of file (%d < %d)\n",
243 rc, (int)st.st_size);
249 dnload.data_len = (file_data+st.st_size) - dnload.data;
251 /* calculate XOR sum */
252 for (i = 0; i < st.st_size; i++)
253 running_xor ^= file_data[i];
255 dnload.data[dnload.data_len++] = running_xor;
257 /* initialize write pointer to start of data */
258 dnload.write_ptr = dnload.data;
260 printf("read_file(%s): file_size=%u, hdr_len=%u, dnload_len=%u\n",
261 filename, (int)st.st_size, hdr_len, dnload.data_len);
266 static void hexdump(const uint8_t *data, unsigned int len)
268 const uint8_t *bufptr = data;
271 for (n=0; bufptr, n < len; n++, bufptr++)
272 printf("%02x ", *bufptr);
276 #define WRITE_BLOCK 4096
278 static int handle_write_dnload(void)
280 int bytes_left, write_len, rc;
282 printf("handle_write(): ");
283 if (dnload.write_ptr == dnload.data) {
284 /* no bytes have been transferred yet */
285 if (dnload.mode == MODE_C155 ||
286 dnload.mode == MODE_C123xor) {
287 uint8_t xor_init = 0x02;
288 write(dnload.serial_fd.fd, &xor_init, 1);
291 } else if (dnload.write_ptr >= dnload.data + dnload.data_len) {
292 printf("finished\n");
293 dnload.write_ptr = dnload.data;
294 dnload.serial_fd.when &= ~BSC_FD_WRITE;
298 /* try to write a maximum of WRITE_BLOCK bytes */
299 bytes_left = (dnload.data + dnload.data_len) - dnload.write_ptr;
300 write_len = WRITE_BLOCK;
301 if (bytes_left < WRITE_BLOCK)
302 write_len = bytes_left;
304 rc = write(dnload.serial_fd.fd, dnload.write_ptr, write_len);
306 perror("Error during write");
310 dnload.write_ptr += rc;
312 printf("%u bytes (%tu/%u)\n", rc, dnload.write_ptr - dnload.data, dnload.data_len);
317 static int handle_write(void)
321 switch (dnload.state) {
323 return handle_write_dnload();
325 if (sercomm_drv_pull(&c) != 0) {
326 if (write(dnload.serial_fd.fd, &c, 1) != 1)
327 perror("short write");
329 dnload.serial_fd.when &= ~BSC_FD_WRITE;
335 static uint8_t buffer[sizeof(phone_prompt1)];
336 static uint8_t *bufptr = buffer;
338 static void hdlc_send_to_phone(uint8_t dlci, uint8_t *data, int len)
343 printf("hdlc_send_to_phone(dlci=%u): ", dlci);
347 fprintf(stderr, "Too much data to send. %u\n", len);
351 /* push the message into the stack */
352 msg = sercomm_alloc_msgb(512);
354 fprintf(stderr, "Failed to create data for the frame.\n");
359 dest = msgb_put(msg, len);
360 memcpy(dest, data, len);
362 sercomm_sendmsg(dlci, msg);
364 dnload.serial_fd.when |= BSC_FD_WRITE;
367 static void hdlc_console_cb(uint8_t dlci, struct msgb *msg)
369 write(1, msg->data, msg->len);
373 static void hdlc_tool_cb(uint8_t dlci, struct msgb *msg)
375 struct tool_server *srv = tool_server_for_dlci[dlci];
378 struct tool_connection *con;
381 len = (u_int16_t *) msgb_push(msg, 2);
382 *len = htons(msg->len - sizeof(*len));
384 llist_for_each_entry(con, &srv->connections, entry) {
385 if (write(con->fd.fd, msg->data, msg->len) != msg->len) {
386 fprintf(stderr, "Failed to write msg to the socket..\n");
395 static void print_hdlc(uint8_t *buffer, int length)
399 for (i = 0; i < length; ++i)
400 if (sercomm_drv_rx_char(buffer[i]) == 0)
401 printf("Dropping sample '%c'\n", buffer[i]);
404 static int handle_read(void)
406 int rc, nbytes, buf_left;
408 buf_left = sizeof(buffer) - (bufptr - buffer);
410 memmove(buffer, buffer+1, sizeof(buffer)-1);
415 nbytes = read(dnload.serial_fd.fd, bufptr, buf_left);
419 if (!dnload.print_hdlc) {
420 printf("got %i bytes from modem, ", nbytes);
421 printf("data looks like: ");
422 hexdump(bufptr, nbytes);
424 print_hdlc(bufptr, nbytes);
427 if (!memcmp(buffer, phone_prompt1, sizeof(phone_prompt1))) {
428 printf("Received PROMPT1 from phone, responding with CMD\n");
429 dnload.print_hdlc = 0;
430 dnload.state = WAITING_PROMPT2;
431 rc = write(dnload.serial_fd.fd, dnload_cmd, sizeof(dnload_cmd));
434 rc = read_file(dnload.filename);
436 fprintf(stderr, "read_file(%s) failed with %d\n", dnload.filename, rc);
439 } else if (!memcmp(buffer, phone_prompt2, sizeof(phone_prompt2))) {
440 printf("Received PROMPT2 from phone, starting download\n");
441 dnload.serial_fd.when = BSC_FD_READ | BSC_FD_WRITE;
442 dnload.state = DOWNLOADING;
443 } else if (!memcmp(buffer, phone_ack, sizeof(phone_ack))) {
444 printf("Received DOWNLOAD ACK from phone, your code is running now!\n");
445 dnload.serial_fd.when = BSC_FD_READ;
446 dnload.state = WAITING_PROMPT1;
447 dnload.write_ptr = dnload.data;
448 dnload.print_hdlc = 1;
449 } else if (!memcmp(buffer, phone_nack, sizeof(phone_nack))) {
450 printf("Received DOWNLOAD NACK from phone, something went wrong :(\n");
451 dnload.serial_fd.when = BSC_FD_READ;
452 dnload.state = WAITING_PROMPT1;
453 dnload.write_ptr = dnload.data;
454 } else if (!memcmp(buffer, phone_nack_magic, sizeof(phone_nack_magic))) {
455 printf("Received MAGIC NACK from phone, you need to have \"1003\" at 0x803ce0\n");
456 dnload.serial_fd.when = BSC_FD_READ;
457 dnload.state = WAITING_PROMPT1;
458 dnload.write_ptr = dnload.data;
459 } else if (!memcmp(buffer, ftmtool, sizeof(ftmtool))) {
460 printf("Received FTMTOOL from phone, ramolader has aborted\n");
461 dnload.serial_fd.when = BSC_FD_READ;
462 dnload.state = WAITING_PROMPT1;
463 dnload.write_ptr = dnload.data;
470 static int serial_read(struct bsc_fd *fd, unsigned int flags)
474 if (flags & BSC_FD_READ) {
480 if (flags & BSC_FD_WRITE) {
483 dnload.state = WAITING_PROMPT1;
488 static int parse_mode(const char *arg)
490 if (!strcasecmp(arg, "c123") ||
491 !strcasecmp(arg, "c140"))
493 else if (!strcasecmp(arg, "c123xor"))
495 else if (!strcasecmp(arg, "c155"))
502 static int usage(const char *name)
504 printf("\nUsage: %s [ -v | -h ] [ -p /dev/ttyXXXX ] [ -s /tmp/osmocom_l2 ] [ -l /tmp/osmocom_loader ] [ -m {c123,c123xor,c155} ] file.bin\n", name);
505 printf("\t* Open serial port /dev/ttyXXXX (connected to your phone)\n"
506 "\t* Perform handshaking with the ramloader in the phone\n"
507 "\t* Download file.bin to the attached phone (base address 0x00800100)\n");
511 static int version(const char *name)
513 //printf("\n%s version %s\n", name, VERSION);
517 static int un_tool_read(struct bsc_fd *fd, unsigned int flags)
520 u_int16_t length = 0xffff;
522 struct tool_connection *con = (struct tool_connection *)fd->data;
525 rc = read(fd->fd, &length, sizeof(length));
527 // client disconnected
530 if (rc < 0 || ntohs(length) > 512) {
531 fprintf(stderr, "Unexpected result from socket. rc: %d len: %d\n",
536 rc = read(fd->fd, buf, ntohs(length));
537 if (rc != ntohs(length)) {
538 fprintf(stderr, "Could not read data.\n");
542 hdlc_send_to_phone(con->server->dlci, buf, ntohs(length));
548 bsc_unregister_fd(fd);
549 llist_del(&con->entry);
554 /* accept a new connection */
555 static int tool_accept(struct bsc_fd *fd, unsigned int flags)
557 struct tool_server *srv = (struct tool_server *)fd->data;
558 struct tool_connection *con;
559 struct sockaddr_un un_addr;
563 len = sizeof(un_addr);
564 rc = accept(fd->fd, (struct sockaddr *) &un_addr, &len);
566 fprintf(stderr, "Failed to accept a new connection.\n");
570 con = talloc_zero(NULL, struct tool_connection);
572 fprintf(stderr, "Failed to create tool connection.\n");
579 con->fd.when = BSC_FD_READ;
580 con->fd.cb = un_tool_read;
582 if (bsc_register_fd(&con->fd) != 0) {
583 fprintf(stderr, "Failed to register the fd.\n");
587 llist_add(&con->entry, &srv->connections);
592 * Register and start a tool server
594 static int register_tool_server(struct tool_server *ts,
598 struct bsc_fd *bfd = &ts->bfd;
599 struct sockaddr_un local;
602 bfd->fd = socket(AF_UNIX, SOCK_STREAM, 0);
605 fprintf(stderr, "Failed to create Unix Domain Socket.\n");
609 local.sun_family = AF_UNIX;
610 strncpy(local.sun_path, path, sizeof(local.sun_path));
611 local.sun_path[sizeof(local.sun_path) - 1] = '\0';
612 unlink(local.sun_path);
613 rc = bind(bfd->fd, (struct sockaddr *) &local,
614 sizeof(local.sun_family) + strlen(local.sun_path));
616 fprintf(stderr, "Failed to bind the unix domain socket. '%s'\n",
621 if (listen(bfd->fd, 0) != 0) {
622 fprintf(stderr, "Failed to listen.\n");
626 bfd->when = BSC_FD_READ;
627 bfd->cb = tool_accept;
631 INIT_LLIST_HEAD(&ts->connections);
633 tool_server_for_dlci[dlci] = ts;
635 sercomm_register_rx_cb(dlci, hdlc_tool_cb);
637 if (bsc_register_fd(bfd) != 0) {
638 fprintf(stderr, "Failed to register the bfd.\n");
645 extern void hdlc_tpudbg_cb(uint8_t dlci, struct msgb *msg);
647 int main(int argc, char **argv)
650 char *serial_dev = "/dev/ttyUSB1";
651 char *layer2_un_path = "/tmp/osmocom_l2";
652 char *loader_un_path = "/tmp/osmocom_loader";
654 dnload.mode = MODE_C123;
656 while ((opt = getopt(argc, argv, "hl:p:m:s:v")) != -1) {
662 dnload.mode = parse_mode(optarg);
667 layer2_un_path = optarg;
670 loader_un_path = optarg;
682 if (argc <= optind) {
683 fprintf(stderr, "You have to specify the filename\n");
687 dnload.filename = argv[optind];
689 dnload.serial_fd.fd = serial_init(serial_dev);
690 if (dnload.serial_fd.fd < 0) {
691 fprintf(stderr, "Cannot open serial device %s\n", serial_dev);
695 if (bsc_register_fd(&dnload.serial_fd) != 0) {
696 fprintf(stderr, "Failed to register the serial.\n");
700 /* Set serial socket to non-blocking mode of operation */
701 flags = fcntl(dnload.serial_fd.fd, F_GETFL);
703 fcntl(dnload.serial_fd.fd, F_SETFL, flags);
705 dnload.serial_fd.when = BSC_FD_READ;
706 dnload.serial_fd.cb = serial_read;
708 /* initialize the HDLC layer */
710 sercomm_register_rx_cb(SC_DLCI_CONSOLE, hdlc_console_cb);
711 sercomm_register_rx_cb(SC_DLCI_DEBUG, hdlc_tpudbg_cb);
713 /* unix domain socket handling */
714 if (register_tool_server(&dnload.layer2_server, layer2_un_path, SC_DLCI_L1A_L23) != 0) {
717 if (register_tool_server(&dnload.loader_server, loader_un_path, SC_DLCI_LOADER) != 0) {
724 close(dnload.serial_fd.fd);