Merge commit 'f8b2ba7dc850396c5910e8c76875e75d37479d34'
[osmocom-bb.git] / src / host / osmocon / osmocon.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <stdint.h>
6 #include <fcntl.h>
7 #include <errno.h>
8 #include <termios.h>
9 #include <sys/ioctl.h>
10 #include <sys/types.h>
11 #include <sys/socket.h>
12 #include <sys/stat.h>
13 #include <sys/un.h>
14
15 #include <sercomm.h>
16
17 #include <osmocore/linuxlist.h>
18 #include <osmocore/select.h>
19 #include <osmocore/talloc.h>
20
21 #include <arpa/inet.h>
22
23 //#include "version.h"
24
25 #define MODEM_BAUDRATE  B115200
26 #define MAX_DNLOAD_SIZE 0xFFFF
27 #define MAX_HDR_SIZE    128
28
29 struct tool_server *tool_server_for_dlci[256];
30
31 /**
32  * a connection from some other tool
33  */
34 struct tool_connection {
35         struct tool_server *server;
36         struct llist_head entry;
37         struct bsc_fd fd;
38 };
39
40 /**
41  * server for a tool
42  */
43 struct tool_server {
44         struct bsc_fd bfd;
45         uint8_t dlci;
46         struct llist_head connections;
47 };
48
49
50 enum dnload_state {
51         WAITING_PROMPT1,
52         WAITING_PROMPT2,
53         DOWNLOADING,
54 };
55
56 enum dnload_mode {
57         MODE_C123,
58         MODE_C123xor,
59         MODE_C155,
60 };
61
62 struct dnload {
63         enum dnload_state state;
64         enum dnload_mode mode;
65         struct bsc_fd serial_fd;
66         char *filename;
67
68         int print_hdlc;
69
70         /* data to be downloaded */
71         uint8_t *data;
72         int data_len;
73
74         uint8_t *write_ptr;
75
76         struct tool_server layer2_server;
77         struct tool_server loader_server;
78 };
79
80
81 static struct dnload dnload;
82
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" };
90
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 };
94
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:
98   800100:       4778            bx      pc
99   800102:       46c0            nop                     ; (mov r8, r8)
100  */
101 static const uint8_t data_hdr_c155[]    = { 0x78, 0x47, 0xc0, 0x46 };
102
103 static const uint8_t dummy_data[]    = { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde };
104
105 static int serial_init(const char *serial_dev)
106 {
107     struct termios options;
108     int fd, v24;
109
110     fd = open(serial_dev, O_RDWR | O_NOCTTY | O_NDELAY);
111     if (fd < 0)
112         return fd;
113
114     fcntl(fd, F_SETFL, 0);
115
116     /* Configure serial interface */
117     tcgetattr(fd, &options);
118
119     cfsetispeed(&options, MODEM_BAUDRATE);
120     cfsetospeed(&options, MODEM_BAUDRATE);
121
122     /* local read */
123     options.c_cflag &= ~PARENB;
124     options.c_cflag &= ~CSTOPB;
125     options.c_cflag &= ~CSIZE;
126     options.c_cflag |= CS8;
127
128     /* hardware flow control off */
129     options.c_cflag &= ~CRTSCTS;
130
131     /* software flow control off */
132     options.c_iflag &= ~(IXON | IXOFF | IXANY);
133
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);
138
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;
146     
147     tcsetattr(fd, TCSANOW, &options);
148
149     /* set ready to read/write */
150     v24 = TIOCM_DTR | TIOCM_RTS;
151     ioctl(fd, TIOCMBIS, &v24);
152
153     return fd;
154 }
155
156 /* Read the to-be-downloaded file, prepend header and length, append XOR sum */
157 int read_file(const char *filename)
158 {
159         int fd, rc, i;
160         struct stat st;
161         const uint8_t *hdr = NULL;
162         int hdr_len = 0;
163         uint8_t *file_data;
164         uint16_t tot_len;
165         uint8_t nibble;
166         uint8_t running_xor = 0x02;
167
168         fd = open(filename, O_RDONLY);
169         if (fd < 0) {
170                 perror("opening file");
171                 exit(1);
172         }
173
174         rc = fstat(fd, &st);
175         if (st.st_size > MAX_DNLOAD_SIZE) {
176                 fprintf(stderr, "The maximum file size is 64kBytes (%u bytes)\n",
177                         MAX_DNLOAD_SIZE);
178                 return -EFBIG;
179         }
180
181         if (dnload.data) {
182                 free(dnload.data);
183                 dnload.data = NULL;
184         }
185
186         dnload.data = malloc(MAX_HDR_SIZE + st.st_size);
187         if (!dnload.data) {
188                 close(fd);
189                 fprintf(stderr, "No memory\n");
190                 return -ENOMEM;
191         }
192
193         /* copy in the header, if any */
194         switch (dnload.mode) {
195         case MODE_C155:
196                 hdr = data_hdr_c155;
197                 hdr_len = sizeof(data_hdr_c155);
198                 break;
199         case MODE_C123:
200         case MODE_C123xor:
201                 hdr = data_hdr_c123;
202                 hdr_len = sizeof(data_hdr_c123);
203                 break;
204         default:
205                 break;
206         }
207
208         if (hdr && hdr_len)
209                 memcpy(dnload.data, hdr, hdr_len);
210
211         /* 2 bytes for length + header */
212         file_data = dnload.data + 2 + hdr_len;
213
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;
222
223         if (hdr_len && hdr) {
224                 memcpy(dnload.data+2, hdr, hdr_len);
225
226                 for (i = 0; i < hdr_len; i++)
227                         running_xor ^= hdr[i];
228         }
229
230         rc = read(fd, file_data, st.st_size);
231         if (rc < 0) {
232                 perror("error reading file\n");
233                 free(dnload.data);
234                 dnload.data = NULL;
235                 close(fd);
236                 return -EIO;
237         }
238         if (rc < st.st_size) {
239                 free(dnload.data);
240                 dnload.data = NULL;
241                 close(fd);
242                 fprintf(stderr, "Short read of file (%d < %d)\n",
243                         rc, (int)st.st_size);
244                 return -EIO;
245         }
246
247         close(fd);
248
249         dnload.data_len = (file_data+st.st_size) - dnload.data;
250
251         /* calculate XOR sum */
252         for (i = 0; i < st.st_size; i++)
253                 running_xor ^= file_data[i];
254
255         dnload.data[dnload.data_len++] = running_xor;
256
257         /* initialize write pointer to start of data */
258         dnload.write_ptr = dnload.data;
259
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);
262
263         return 0;
264 }
265
266 static void hexdump(const uint8_t *data, unsigned int len)
267 {
268         const uint8_t *bufptr = data;
269         int n;
270
271         for (n=0; bufptr, n < len; n++, bufptr++)
272                 printf("%02x ", *bufptr);
273         printf("\n");
274 }
275
276 #define WRITE_BLOCK     4096
277
278 static int handle_write_dnload(void)
279 {
280         int bytes_left, write_len, rc;
281
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);
289                 } else
290                         usleep(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;
295                 return 1;
296         }
297
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;
303
304         rc = write(dnload.serial_fd.fd, dnload.write_ptr, write_len);
305         if (rc < 0) {
306                 perror("Error during write");
307                 return rc;
308         }
309
310         dnload.write_ptr += rc;
311
312         printf("%u bytes (%tu/%u)\n", rc, dnload.write_ptr - dnload.data, dnload.data_len);
313
314         return 0;
315 }
316
317 static int handle_write(void)
318 {
319         uint8_t c;
320
321         switch (dnload.state) {
322         case DOWNLOADING:
323                 return handle_write_dnload();
324         default:
325                 if (sercomm_drv_pull(&c) != 0) {
326                         if (write(dnload.serial_fd.fd, &c, 1) != 1)
327                                 perror("short write");
328                 } else
329                         dnload.serial_fd.when &= ~BSC_FD_WRITE;
330         }
331
332         return 0;
333 }
334
335 static uint8_t buffer[sizeof(phone_prompt1)];
336 static uint8_t *bufptr = buffer;
337
338 static void hdlc_send_to_phone(uint8_t dlci, uint8_t *data, int len)
339 {
340         struct msgb *msg;
341         uint8_t c, *dest;
342
343         printf("hdlc_send_to_phone(dlci=%u): ", dlci);
344         hexdump(data, len);
345
346         if (len > 512) {
347                 fprintf(stderr, "Too much data to send. %u\n", len);
348                 return;
349         }
350
351         /* push the message into the stack */
352         msg = sercomm_alloc_msgb(512);
353         if (!msg) {
354                 fprintf(stderr, "Failed to create data for the frame.\n");
355                 return;
356         }
357
358         /* copy the data */
359         dest = msgb_put(msg, len);
360         memcpy(dest, data, len);
361
362         sercomm_sendmsg(dlci, msg);
363
364         dnload.serial_fd.when |= BSC_FD_WRITE;
365 }
366
367 static void hdlc_console_cb(uint8_t dlci, struct msgb *msg)
368 {
369         write(1, msg->data, msg->len);
370         msgb_free(msg);
371 }
372
373 static void hdlc_tool_cb(uint8_t dlci, struct msgb *msg)
374 {
375         struct tool_server *srv = tool_server_for_dlci[dlci];
376
377         if(srv) {
378                 struct tool_connection *con;
379                 u_int16_t *len;
380
381                 len = (u_int16_t *) msgb_push(msg, 2);
382                 *len = htons(msg->len - sizeof(*len));
383
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");
387                                 continue;
388                         }
389                 }
390         }
391
392         msgb_free(msg);
393 }
394
395 static void print_hdlc(uint8_t *buffer, int length)
396 {
397         int i;
398
399         for (i = 0; i < length; ++i)
400                 if (sercomm_drv_rx_char(buffer[i]) == 0)
401                         printf("Dropping sample '%c'\n", buffer[i]);
402 }
403
404 static int handle_read(void)
405 {
406         int rc, nbytes, buf_left;
407
408         buf_left = sizeof(buffer) - (bufptr - buffer);
409         if (buf_left <= 0) {
410                 memmove(buffer, buffer+1, sizeof(buffer)-1);
411                 bufptr -= 1;
412                 buf_left = 1;
413         }
414
415         nbytes = read(dnload.serial_fd.fd, bufptr, buf_left);
416         if (nbytes <= 0)
417                 return nbytes;
418
419         if (!dnload.print_hdlc) {
420                 printf("got %i bytes from modem, ", nbytes);
421                 printf("data looks like: ");
422                 hexdump(bufptr, nbytes);
423         } else {
424                 print_hdlc(bufptr, nbytes);
425         }
426
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));
432
433                 /* re-read file */
434                 rc = read_file(dnload.filename);
435                 if (rc < 0) {
436                         fprintf(stderr, "read_file(%s) failed with %d\n", dnload.filename, rc);
437                         exit(1);
438                 }
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;
464         }
465         bufptr += nbytes;
466
467         return nbytes;
468 }
469
470 static int serial_read(struct bsc_fd *fd, unsigned int flags)
471 {
472         int rc;
473
474         if (flags & BSC_FD_READ) {
475                 rc = handle_read();
476                 if (rc == 0)
477                         exit(2);
478         }
479
480         if (flags & BSC_FD_WRITE) {
481                 rc = handle_write();
482                 if (rc == 1)
483                         dnload.state = WAITING_PROMPT1;
484         }
485         return 0;
486 }
487
488 static int parse_mode(const char *arg)
489 {
490         if (!strcasecmp(arg, "c123") ||
491             !strcasecmp(arg, "c140"))
492                 return MODE_C123;
493         else if (!strcasecmp(arg, "c123xor"))
494                 return MODE_C123xor;
495         else if (!strcasecmp(arg, "c155"))
496                 return MODE_C155;
497
498         return -1;
499 }
500
501
502 static int usage(const char *name)
503 {
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");
508         exit(2);
509 }
510
511 static int version(const char *name)
512 {
513         //printf("\n%s version %s\n", name, VERSION);
514         exit(2);
515 }
516
517 static int un_tool_read(struct bsc_fd *fd, unsigned int flags)
518 {
519         int rc, c;
520         u_int16_t length = 0xffff;
521         u_int8_t buf[4096];
522         struct tool_connection *con = (struct tool_connection *)fd->data;
523
524         c = 0;
525         while(c < 2) {
526                 rc = read(fd->fd, &buf + c, 2 - c);
527                 if(rc == 0) {
528                         // disconnect
529                         goto close;
530                 }
531                 if(rc < 0) {
532                         if(errno == EAGAIN) {
533                                 continue;
534                         }
535                         fprintf(stderr, "Err from socket: %s\n", strerror(errno));
536                         goto close;
537                 }
538                 c += rc;
539         }
540
541         length = ntohs(*(u_int16_t*)buf);
542
543         c = 0;
544         while(c < length) {
545                 rc = read(fd->fd, &buf + c, length - c);
546                 if(rc == 0) {
547                         // disconnect
548                         goto close;
549                 }
550                 if(rc < 0) {
551                         if(errno == EAGAIN) {
552                                 continue;
553                         }
554                         fprintf(stderr, "Err from socket: %s\n", strerror(errno));
555                         goto close;
556                 }
557                 c += rc;
558         }
559
560         hdlc_send_to_phone(con->server->dlci, buf, length);
561
562         return 0;
563 close:
564
565         close(fd->fd);
566         bsc_unregister_fd(fd);
567         llist_del(&con->entry);
568         talloc_free(con);
569         return -1;
570 }
571
572 /* accept a new connection */
573 static int tool_accept(struct bsc_fd *fd, unsigned int flags)
574 {
575         struct tool_server *srv = (struct tool_server *)fd->data;
576         struct tool_connection *con;
577         struct sockaddr_un un_addr;
578         socklen_t len;
579         int rc;
580
581         len = sizeof(un_addr);
582         rc = accept(fd->fd, (struct sockaddr *) &un_addr, &len);
583         if (rc < 0) {
584                 fprintf(stderr, "Failed to accept a new connection.\n");
585                 return -1;
586         }
587
588         con = talloc_zero(NULL, struct tool_connection);
589         if (!con) {
590                 fprintf(stderr, "Failed to create tool connection.\n");
591                 return -1;
592         }
593
594         con->server = srv;
595
596         con->fd.fd = rc;
597         con->fd.when = BSC_FD_READ;
598         con->fd.cb = un_tool_read;
599         con->fd.data = con;
600         if (bsc_register_fd(&con->fd) != 0) {
601                 fprintf(stderr, "Failed to register the fd.\n");
602                 return -1;
603         }
604
605         llist_add(&con->entry, &srv->connections);
606         return 0;
607 }
608
609 /*
610  * Register and start a tool server
611  */
612 static int register_tool_server(struct tool_server *ts,
613                                                                 const char *path,
614                                                                 uint8_t dlci)
615 {
616         struct bsc_fd *bfd = &ts->bfd;
617         struct sockaddr_un local;
618         int rc;
619
620         bfd->fd = socket(AF_UNIX, SOCK_STREAM, 0);
621
622         if (bfd->fd < 0) {
623                 fprintf(stderr, "Failed to create Unix Domain Socket.\n");
624                 return -1;
625         }
626
627         local.sun_family = AF_UNIX;
628         strncpy(local.sun_path, path, sizeof(local.sun_path));
629         local.sun_path[sizeof(local.sun_path) - 1] = '\0';
630         unlink(local.sun_path);
631         rc = bind(bfd->fd, (struct sockaddr *) &local,
632                   sizeof(local.sun_family) + strlen(local.sun_path));
633         if (rc != 0) {
634                 fprintf(stderr, "Failed to bind the unix domain socket. '%s'\n",
635                         local.sun_path);
636                 return -1;
637         }
638
639         if (listen(bfd->fd, 0) != 0) {
640                 fprintf(stderr, "Failed to listen.\n");
641                 return -1;
642         }
643
644         bfd->when = BSC_FD_READ;
645         bfd->cb = tool_accept;
646         bfd->data = ts;
647
648         ts->dlci = dlci;
649         INIT_LLIST_HEAD(&ts->connections);
650
651         tool_server_for_dlci[dlci] = ts;
652
653         sercomm_register_rx_cb(dlci, hdlc_tool_cb);
654
655         if (bsc_register_fd(bfd) != 0) {
656                 fprintf(stderr, "Failed to register the bfd.\n");
657                 return -1;
658         }
659
660         return 0;
661 }
662
663 extern void hdlc_tpudbg_cb(uint8_t dlci, struct msgb *msg);
664
665 int main(int argc, char **argv)
666 {
667         int opt, flags;
668         char *serial_dev = "/dev/ttyUSB1";
669         char *layer2_un_path = "/tmp/osmocom_l2";
670         char *loader_un_path = "/tmp/osmocom_loader";
671
672         dnload.mode = MODE_C123;
673
674         while ((opt = getopt(argc, argv, "hl:p:m:s:v")) != -1) {
675                 switch (opt) {
676                 case 'p':
677                         serial_dev = optarg;
678                         break;
679                 case 'm':
680                         dnload.mode = parse_mode(optarg);
681                         if (dnload.mode < 0)
682                                 usage(argv[0]);
683                         break;
684                 case 's':
685                         layer2_un_path = optarg;
686                         break;
687                 case 'l':
688                         loader_un_path = optarg;
689                         break;
690                 case 'v':
691                         version(argv[0]);
692                         break;
693                 case 'h':
694                 default:
695                         usage(argv[0]);
696                         break;
697                 }
698         }
699
700         if (argc <= optind) {
701                 fprintf(stderr, "You have to specify the filename\n");
702                 usage(argv[0]);
703         }
704
705         dnload.filename = argv[optind];
706
707         dnload.serial_fd.fd = serial_init(serial_dev);
708         if (dnload.serial_fd.fd < 0) {
709                 fprintf(stderr, "Cannot open serial device %s\n", serial_dev);
710                 exit(1);
711         }
712
713         if (bsc_register_fd(&dnload.serial_fd) != 0) {
714                 fprintf(stderr, "Failed to register the serial.\n");
715                 exit(1);
716         }
717
718         /* Set serial socket to non-blocking mode of operation */
719         flags = fcntl(dnload.serial_fd.fd, F_GETFL);
720         flags |= O_NONBLOCK;
721         fcntl(dnload.serial_fd.fd, F_SETFL, flags);
722
723         dnload.serial_fd.when = BSC_FD_READ;
724         dnload.serial_fd.cb = serial_read;
725
726         /* initialize the HDLC layer */
727         sercomm_init();
728         sercomm_register_rx_cb(SC_DLCI_CONSOLE, hdlc_console_cb);
729         sercomm_register_rx_cb(SC_DLCI_DEBUG, hdlc_tpudbg_cb);
730
731         /* unix domain socket handling */
732         if (register_tool_server(&dnload.layer2_server, layer2_un_path, SC_DLCI_L1A_L23) != 0) {
733                 exit(1);
734         }
735         if (register_tool_server(&dnload.loader_server, loader_un_path, SC_DLCI_LOADER) != 0) {
736                 exit(1);
737         }
738
739         while (1)
740                 bsc_select_main(0);
741
742         close(dnload.serial_fd.fd);
743
744         exit(0);
745 }