1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2012 NetApp, Inc. 5 * Copyright (c) 2013 Neel Natu <neel@freebsd.org> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $FreeBSD$ 30 * 31 */ 32 /* 33 * This file and its contents are supplied under the terms of the 34 * Common Development and Distribution License ("CDDL"), version 1.0. 35 * You may only use this file in accordance with the terms of version 36 * 1.0 of the CDDL. 37 * 38 * A full copy of the text of the CDDL should have accompanied this 39 * source. A copy of the CDDL is also available via the Internet at 40 * http://www.illumos.org/license/CDDL. 41 * 42 * Copyright 2015 Pluribus Networks Inc. 43 * Copyright 2018 Joyent, Inc. 44 */ 45 46 #include <sys/cdefs.h> 47 __FBSDID("$FreeBSD$"); 48 49 #include <sys/types.h> 50 #include <dev/ic/ns16550.h> 51 #ifndef WITHOUT_CAPSICUM 52 #include <sys/capsicum.h> 53 #include <capsicum_helpers.h> 54 #endif 55 56 #include <stdio.h> 57 #include <stdlib.h> 58 #include <assert.h> 59 #include <err.h> 60 #include <errno.h> 61 #include <fcntl.h> 62 #include <termios.h> 63 #include <unistd.h> 64 #include <stdbool.h> 65 #include <string.h> 66 #include <pthread.h> 67 #include <sysexits.h> 68 #ifndef __FreeBSD__ 69 #include <sys/socket.h> 70 #endif 71 72 #include "mevent.h" 73 #include "uart_emul.h" 74 75 #define COM1_BASE 0x3F8 76 #define COM1_IRQ 4 77 #define COM2_BASE 0x2F8 78 #define COM2_IRQ 3 79 80 #define DEFAULT_RCLK 1843200 81 #define DEFAULT_BAUD 9600 82 83 #define FCR_RX_MASK 0xC0 84 85 #define MCR_OUT1 0x04 86 #define MCR_OUT2 0x08 87 88 #define MSR_DELTA_MASK 0x0f 89 90 #ifndef REG_SCR 91 #define REG_SCR com_scr 92 #endif 93 94 #define FIFOSZ 16 95 96 static bool uart_stdio; /* stdio in use for i/o */ 97 static struct termios tio_stdio_orig; 98 99 static struct { 100 int baseaddr; 101 int irq; 102 bool inuse; 103 } uart_lres[] = { 104 { COM1_BASE, COM1_IRQ, false}, 105 { COM2_BASE, COM2_IRQ, false}, 106 }; 107 108 #define UART_NLDEVS (sizeof(uart_lres) / sizeof(uart_lres[0])) 109 110 struct fifo { 111 uint8_t buf[FIFOSZ]; 112 int rindex; /* index to read from */ 113 int windex; /* index to write to */ 114 int num; /* number of characters in the fifo */ 115 int size; /* size of the fifo */ 116 }; 117 118 struct ttyfd { 119 bool opened; 120 int rfd; /* fd for reading */ 121 int wfd; /* fd for writing, may be == rfd */ 122 }; 123 124 struct uart_softc { 125 pthread_mutex_t mtx; /* protects all softc elements */ 126 uint8_t data; /* Data register (R/W) */ 127 uint8_t ier; /* Interrupt enable register (R/W) */ 128 uint8_t lcr; /* Line control register (R/W) */ 129 uint8_t mcr; /* Modem control register (R/W) */ 130 uint8_t lsr; /* Line status register (R/W) */ 131 uint8_t msr; /* Modem status register (R/W) */ 132 uint8_t fcr; /* FIFO control register (W) */ 133 uint8_t scr; /* Scratch register (R/W) */ 134 135 uint8_t dll; /* Baudrate divisor latch LSB */ 136 uint8_t dlh; /* Baudrate divisor latch MSB */ 137 138 struct fifo rxfifo; 139 struct mevent *mev; 140 141 struct ttyfd tty; 142 #ifndef __FreeBSD__ 143 bool sock; 144 struct { 145 int clifd; /* console client unix domain socket */ 146 int servfd; /* console server unix domain socket */ 147 struct mevent *servmev; /* mevent for server socket */ 148 } usc_sock; 149 #endif 150 151 bool thre_int_pending; /* THRE interrupt pending */ 152 153 void *arg; 154 uart_intr_func_t intr_assert; 155 uart_intr_func_t intr_deassert; 156 }; 157 158 static void uart_drain(int fd, enum ev_type ev, void *arg); 159 160 static void 161 ttyclose(void) 162 { 163 164 tcsetattr(STDIN_FILENO, TCSANOW, &tio_stdio_orig); 165 } 166 167 static void 168 ttyopen(struct ttyfd *tf) 169 { 170 struct termios orig, new; 171 172 tcgetattr(tf->rfd, &orig); 173 new = orig; 174 cfmakeraw(&new); 175 new.c_cflag |= CLOCAL; 176 tcsetattr(tf->rfd, TCSANOW, &new); 177 if (uart_stdio) { 178 tio_stdio_orig = orig; 179 atexit(ttyclose); 180 } 181 } 182 183 static int 184 ttyread(struct ttyfd *tf) 185 { 186 unsigned char rb; 187 188 if (read(tf->rfd, &rb, 1) == 1) 189 return (rb); 190 else 191 return (-1); 192 } 193 194 static void 195 ttywrite(struct ttyfd *tf, unsigned char wb) 196 { 197 198 (void)write(tf->wfd, &wb, 1); 199 } 200 201 #ifndef __FreeBSD__ 202 static void 203 sockwrite(struct uart_softc *sc, unsigned char wb) 204 { 205 (void) write(sc->usc_sock.clifd, &wb, 1); 206 } 207 #endif 208 209 static void 210 rxfifo_reset(struct uart_softc *sc, int size) 211 { 212 char flushbuf[32]; 213 struct fifo *fifo; 214 ssize_t nread; 215 int error; 216 217 fifo = &sc->rxfifo; 218 bzero(fifo, sizeof(struct fifo)); 219 fifo->size = size; 220 221 if (sc->tty.opened) { 222 /* 223 * Flush any unread input from the tty buffer. 224 */ 225 while (1) { 226 nread = read(sc->tty.rfd, flushbuf, sizeof(flushbuf)); 227 if (nread != sizeof(flushbuf)) 228 break; 229 } 230 231 /* 232 * Enable mevent to trigger when new characters are available 233 * on the tty fd. 234 */ 235 error = mevent_enable(sc->mev); 236 assert(error == 0); 237 } 238 #ifndef __FreeBSD__ 239 if (sc->sock && sc->usc_sock.clifd != -1) { 240 /* Flush any unread input from the socket buffer. */ 241 do { 242 nread = read(sc->usc_sock.clifd, flushbuf, 243 sizeof (flushbuf)); 244 } while (nread == sizeof (flushbuf)); 245 246 /* Enable mevent to trigger when new data available on sock */ 247 error = mevent_enable(sc->mev); 248 assert(error == 0); 249 } 250 #endif /* __FreeBSD__ */ 251 } 252 253 static int 254 rxfifo_available(struct uart_softc *sc) 255 { 256 struct fifo *fifo; 257 258 fifo = &sc->rxfifo; 259 return (fifo->num < fifo->size); 260 } 261 262 static int 263 rxfifo_putchar(struct uart_softc *sc, uint8_t ch) 264 { 265 struct fifo *fifo; 266 int error; 267 268 fifo = &sc->rxfifo; 269 270 if (fifo->num < fifo->size) { 271 fifo->buf[fifo->windex] = ch; 272 fifo->windex = (fifo->windex + 1) % fifo->size; 273 fifo->num++; 274 if (!rxfifo_available(sc)) { 275 if (sc->tty.opened) { 276 /* 277 * Disable mevent callback if the FIFO is full. 278 */ 279 error = mevent_disable(sc->mev); 280 assert(error == 0); 281 } 282 #ifndef __FreeBSD__ 283 if (sc->sock && sc->usc_sock.clifd != -1) { 284 /* 285 * Disable mevent callback if the FIFO is full. 286 */ 287 error = mevent_disable(sc->mev); 288 assert(error == 0); 289 } 290 #endif /* __FreeBSD__ */ 291 } 292 return (0); 293 } else 294 return (-1); 295 } 296 297 static int 298 rxfifo_getchar(struct uart_softc *sc) 299 { 300 struct fifo *fifo; 301 int c, error, wasfull; 302 303 wasfull = 0; 304 fifo = &sc->rxfifo; 305 if (fifo->num > 0) { 306 if (!rxfifo_available(sc)) 307 wasfull = 1; 308 c = fifo->buf[fifo->rindex]; 309 fifo->rindex = (fifo->rindex + 1) % fifo->size; 310 fifo->num--; 311 if (wasfull) { 312 if (sc->tty.opened) { 313 error = mevent_enable(sc->mev); 314 assert(error == 0); 315 } 316 #ifndef __FreeBSD__ 317 if (sc->sock && sc->usc_sock.clifd != -1) { 318 error = mevent_enable(sc->mev); 319 assert(error == 0); 320 } 321 #endif /* __FreeBSD__ */ 322 } 323 return (c); 324 } else 325 return (-1); 326 } 327 328 static int 329 rxfifo_numchars(struct uart_softc *sc) 330 { 331 struct fifo *fifo = &sc->rxfifo; 332 333 return (fifo->num); 334 } 335 336 static void 337 uart_opentty(struct uart_softc *sc) 338 { 339 340 ttyopen(&sc->tty); 341 sc->mev = mevent_add(sc->tty.rfd, EVF_READ, uart_drain, sc); 342 assert(sc->mev != NULL); 343 } 344 345 static uint8_t 346 modem_status(uint8_t mcr) 347 { 348 uint8_t msr; 349 350 if (mcr & MCR_LOOPBACK) { 351 /* 352 * In the loopback mode certain bits from the MCR are 353 * reflected back into MSR. 354 */ 355 msr = 0; 356 if (mcr & MCR_RTS) 357 msr |= MSR_CTS; 358 if (mcr & MCR_DTR) 359 msr |= MSR_DSR; 360 if (mcr & MCR_OUT1) 361 msr |= MSR_RI; 362 if (mcr & MCR_OUT2) 363 msr |= MSR_DCD; 364 } else { 365 /* 366 * Always assert DCD and DSR so tty open doesn't block 367 * even if CLOCAL is turned off. 368 */ 369 msr = MSR_DCD | MSR_DSR; 370 } 371 assert((msr & MSR_DELTA_MASK) == 0); 372 373 return (msr); 374 } 375 376 /* 377 * The IIR returns a prioritized interrupt reason: 378 * - receive data available 379 * - transmit holding register empty 380 * - modem status change 381 * 382 * Return an interrupt reason if one is available. 383 */ 384 static int 385 uart_intr_reason(struct uart_softc *sc) 386 { 387 388 if ((sc->lsr & LSR_OE) != 0 && (sc->ier & IER_ERLS) != 0) 389 return (IIR_RLS); 390 else if (rxfifo_numchars(sc) > 0 && (sc->ier & IER_ERXRDY) != 0) 391 return (IIR_RXTOUT); 392 else if (sc->thre_int_pending && (sc->ier & IER_ETXRDY) != 0) 393 return (IIR_TXRDY); 394 else if ((sc->msr & MSR_DELTA_MASK) != 0 && (sc->ier & IER_EMSC) != 0) 395 return (IIR_MLSC); 396 else 397 return (IIR_NOPEND); 398 } 399 400 static void 401 uart_reset(struct uart_softc *sc) 402 { 403 uint16_t divisor; 404 405 divisor = DEFAULT_RCLK / DEFAULT_BAUD / 16; 406 sc->dll = divisor; 407 #ifndef __FreeBSD__ 408 sc->dlh = 0; 409 #else 410 sc->dlh = divisor >> 16; 411 #endif 412 sc->msr = modem_status(sc->mcr); 413 414 rxfifo_reset(sc, 1); /* no fifo until enabled by software */ 415 } 416 417 /* 418 * Toggle the COM port's intr pin depending on whether or not we have an 419 * interrupt condition to report to the processor. 420 */ 421 static void 422 uart_toggle_intr(struct uart_softc *sc) 423 { 424 uint8_t intr_reason; 425 426 intr_reason = uart_intr_reason(sc); 427 428 if (intr_reason == IIR_NOPEND) 429 (*sc->intr_deassert)(sc->arg); 430 else 431 (*sc->intr_assert)(sc->arg); 432 } 433 434 static void 435 uart_drain(int fd, enum ev_type ev, void *arg) 436 { 437 struct uart_softc *sc; 438 int ch; 439 440 sc = arg; 441 442 assert(fd == sc->tty.rfd); 443 assert(ev == EVF_READ); 444 445 /* 446 * This routine is called in the context of the mevent thread 447 * to take out the softc lock to protect against concurrent 448 * access from a vCPU i/o exit 449 */ 450 pthread_mutex_lock(&sc->mtx); 451 452 if ((sc->mcr & MCR_LOOPBACK) != 0) { 453 (void) ttyread(&sc->tty); 454 } else { 455 while (rxfifo_available(sc) && 456 ((ch = ttyread(&sc->tty)) != -1)) { 457 rxfifo_putchar(sc, ch); 458 } 459 uart_toggle_intr(sc); 460 } 461 462 pthread_mutex_unlock(&sc->mtx); 463 } 464 465 void 466 uart_write(struct uart_softc *sc, int offset, uint8_t value) 467 { 468 int fifosz; 469 uint8_t msr; 470 471 pthread_mutex_lock(&sc->mtx); 472 473 /* 474 * Take care of the special case DLAB accesses first 475 */ 476 if ((sc->lcr & LCR_DLAB) != 0) { 477 if (offset == REG_DLL) { 478 sc->dll = value; 479 goto done; 480 } 481 482 if (offset == REG_DLH) { 483 sc->dlh = value; 484 goto done; 485 } 486 } 487 488 switch (offset) { 489 case REG_DATA: 490 if (sc->mcr & MCR_LOOPBACK) { 491 if (rxfifo_putchar(sc, value) != 0) 492 sc->lsr |= LSR_OE; 493 } else if (sc->tty.opened) { 494 ttywrite(&sc->tty, value); 495 #ifndef __FreeBSD__ 496 } else if (sc->sock) { 497 sockwrite(sc, value); 498 #endif 499 } /* else drop on floor */ 500 sc->thre_int_pending = true; 501 break; 502 case REG_IER: 503 /* Set pending when IER_ETXRDY is raised (edge-triggered). */ 504 if ((sc->ier & IER_ETXRDY) == 0 && (value & IER_ETXRDY) != 0) 505 sc->thre_int_pending = true; 506 /* 507 * Apply mask so that bits 4-7 are 0 508 * Also enables bits 0-3 only if they're 1 509 */ 510 sc->ier = value & 0x0F; 511 break; 512 case REG_FCR: 513 /* 514 * When moving from FIFO and 16450 mode and vice versa, 515 * the FIFO contents are reset. 516 */ 517 if ((sc->fcr & FCR_ENABLE) ^ (value & FCR_ENABLE)) { 518 fifosz = (value & FCR_ENABLE) ? FIFOSZ : 1; 519 rxfifo_reset(sc, fifosz); 520 } 521 522 /* 523 * The FCR_ENABLE bit must be '1' for the programming 524 * of other FCR bits to be effective. 525 */ 526 if ((value & FCR_ENABLE) == 0) { 527 sc->fcr = 0; 528 } else { 529 if ((value & FCR_RCV_RST) != 0) 530 rxfifo_reset(sc, FIFOSZ); 531 532 sc->fcr = value & 533 (FCR_ENABLE | FCR_DMA | FCR_RX_MASK); 534 } 535 break; 536 case REG_LCR: 537 sc->lcr = value; 538 break; 539 case REG_MCR: 540 /* Apply mask so that bits 5-7 are 0 */ 541 sc->mcr = value & 0x1F; 542 msr = modem_status(sc->mcr); 543 544 /* 545 * Detect if there has been any change between the 546 * previous and the new value of MSR. If there is 547 * then assert the appropriate MSR delta bit. 548 */ 549 if ((msr & MSR_CTS) ^ (sc->msr & MSR_CTS)) 550 sc->msr |= MSR_DCTS; 551 if ((msr & MSR_DSR) ^ (sc->msr & MSR_DSR)) 552 sc->msr |= MSR_DDSR; 553 if ((msr & MSR_DCD) ^ (sc->msr & MSR_DCD)) 554 sc->msr |= MSR_DDCD; 555 if ((sc->msr & MSR_RI) != 0 && (msr & MSR_RI) == 0) 556 sc->msr |= MSR_TERI; 557 558 /* 559 * Update the value of MSR while retaining the delta 560 * bits. 561 */ 562 sc->msr &= MSR_DELTA_MASK; 563 sc->msr |= msr; 564 break; 565 case REG_LSR: 566 /* 567 * Line status register is not meant to be written to 568 * during normal operation. 569 */ 570 break; 571 case REG_MSR: 572 /* 573 * As far as I can tell MSR is a read-only register. 574 */ 575 break; 576 case REG_SCR: 577 sc->scr = value; 578 break; 579 default: 580 break; 581 } 582 583 done: 584 uart_toggle_intr(sc); 585 pthread_mutex_unlock(&sc->mtx); 586 } 587 588 uint8_t 589 uart_read(struct uart_softc *sc, int offset) 590 { 591 uint8_t iir, intr_reason, reg; 592 593 pthread_mutex_lock(&sc->mtx); 594 595 /* 596 * Take care of the special case DLAB accesses first 597 */ 598 if ((sc->lcr & LCR_DLAB) != 0) { 599 if (offset == REG_DLL) { 600 reg = sc->dll; 601 goto done; 602 } 603 604 if (offset == REG_DLH) { 605 reg = sc->dlh; 606 goto done; 607 } 608 } 609 610 switch (offset) { 611 case REG_DATA: 612 reg = rxfifo_getchar(sc); 613 break; 614 case REG_IER: 615 reg = sc->ier; 616 break; 617 case REG_IIR: 618 iir = (sc->fcr & FCR_ENABLE) ? IIR_FIFO_MASK : 0; 619 620 intr_reason = uart_intr_reason(sc); 621 622 /* 623 * Deal with side effects of reading the IIR register 624 */ 625 if (intr_reason == IIR_TXRDY) 626 sc->thre_int_pending = false; 627 628 iir |= intr_reason; 629 630 reg = iir; 631 break; 632 case REG_LCR: 633 reg = sc->lcr; 634 break; 635 case REG_MCR: 636 reg = sc->mcr; 637 break; 638 case REG_LSR: 639 /* Transmitter is always ready for more data */ 640 sc->lsr |= LSR_TEMT | LSR_THRE; 641 642 /* Check for new receive data */ 643 if (rxfifo_numchars(sc) > 0) 644 sc->lsr |= LSR_RXRDY; 645 else 646 sc->lsr &= ~LSR_RXRDY; 647 648 reg = sc->lsr; 649 650 /* The LSR_OE bit is cleared on LSR read */ 651 sc->lsr &= ~LSR_OE; 652 break; 653 case REG_MSR: 654 /* 655 * MSR delta bits are cleared on read 656 */ 657 reg = sc->msr; 658 sc->msr &= ~MSR_DELTA_MASK; 659 break; 660 case REG_SCR: 661 reg = sc->scr; 662 break; 663 default: 664 reg = 0xFF; 665 break; 666 } 667 668 done: 669 uart_toggle_intr(sc); 670 pthread_mutex_unlock(&sc->mtx); 671 672 return (reg); 673 } 674 675 #ifndef __FreeBSD__ 676 static void 677 uart_sock_drain(int fd, enum ev_type ev, void *arg) 678 { 679 struct uart_softc *sc = arg; 680 char ch; 681 682 /* 683 * Take the softc lock to protect against concurrent 684 * access from a vCPU i/o exit 685 */ 686 pthread_mutex_lock(&sc->mtx); 687 688 if ((sc->mcr & MCR_LOOPBACK) != 0) { 689 (void) read(sc->usc_sock.clifd, &ch, 1); 690 } else { 691 bool err_close = false; 692 693 while (rxfifo_available(sc)) { 694 int res; 695 696 res = read(sc->usc_sock.clifd, &ch, 1); 697 if (res == 0) { 698 err_close = true; 699 break; 700 } else if (res == -1) { 701 if (errno != EAGAIN && errno != EINTR) { 702 err_close = true; 703 } 704 break; 705 } 706 707 rxfifo_putchar(sc, ch); 708 } 709 uart_toggle_intr(sc); 710 711 if (err_close) { 712 (void) fprintf(stderr, "uart: closing client conn\n"); 713 (void) shutdown(sc->usc_sock.clifd, SHUT_RDWR); 714 mevent_delete_close(sc->mev); 715 sc->mev = NULL; 716 sc->usc_sock.clifd = -1; 717 } 718 } 719 720 pthread_mutex_unlock(&sc->mtx); 721 } 722 723 static void 724 uart_sock_accept(int fd, enum ev_type ev, void *arg) 725 { 726 struct uart_softc *sc = arg; 727 int connfd; 728 729 connfd = accept(sc->usc_sock.servfd, NULL, NULL); 730 if (connfd == -1) { 731 return; 732 } 733 734 /* 735 * Do client connection management under protection of the softc lock 736 * to avoid racing with concurrent UART events. 737 */ 738 pthread_mutex_lock(&sc->mtx); 739 740 if (sc->usc_sock.clifd != -1) { 741 /* we're already handling a client */ 742 (void) fprintf(stderr, "uart: unexpected client conn\n"); 743 (void) shutdown(connfd, SHUT_RDWR); 744 (void) close(connfd); 745 } else { 746 if (fcntl(connfd, F_SETFL, O_NONBLOCK) < 0) { 747 perror("uart: fcntl(O_NONBLOCK)"); 748 (void) shutdown(connfd, SHUT_RDWR); 749 (void) close(connfd); 750 } else { 751 sc->usc_sock.clifd = connfd; 752 sc->mev = mevent_add(sc->usc_sock.clifd, EVF_READ, 753 uart_sock_drain, sc); 754 } 755 } 756 757 pthread_mutex_unlock(&sc->mtx); 758 } 759 760 static int 761 init_sock(const char *path) 762 { 763 int servfd; 764 struct sockaddr_un servaddr; 765 766 bzero(&servaddr, sizeof (servaddr)); 767 servaddr.sun_family = AF_UNIX; 768 769 if (strlcpy(servaddr.sun_path, path, sizeof (servaddr.sun_path)) >= 770 sizeof (servaddr.sun_path)) { 771 (void) fprintf(stderr, "uart: path '%s' too long\n", 772 path); 773 return (-1); 774 } 775 776 if ((servfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { 777 (void) fprintf(stderr, "uart: socket() error - %s\n", 778 strerror(errno)); 779 return (-1); 780 } 781 (void) unlink(servaddr.sun_path); 782 783 if (bind(servfd, (struct sockaddr *)&servaddr, 784 sizeof (servaddr)) == -1) { 785 (void) fprintf(stderr, "uart: bind() error - %s\n", 786 strerror(errno)); 787 goto out; 788 } 789 790 if (listen(servfd, 1) == -1) { 791 (void) fprintf(stderr, "uart: listen() error - %s\n", 792 strerror(errno)); 793 goto out; 794 } 795 return (servfd); 796 797 out: 798 (void) unlink(servaddr.sun_path); 799 (void) close(servfd); 800 return (-1); 801 } 802 #endif /* not __FreeBSD__ */ 803 804 int 805 uart_legacy_alloc(int which, int *baseaddr, int *irq) 806 { 807 808 if (which < 0 || which >= UART_NLDEVS || uart_lres[which].inuse) 809 return (-1); 810 811 uart_lres[which].inuse = true; 812 *baseaddr = uart_lres[which].baseaddr; 813 *irq = uart_lres[which].irq; 814 815 return (0); 816 } 817 818 struct uart_softc * 819 uart_init(uart_intr_func_t intr_assert, uart_intr_func_t intr_deassert, 820 void *arg) 821 { 822 struct uart_softc *sc; 823 824 sc = calloc(1, sizeof(struct uart_softc)); 825 826 sc->arg = arg; 827 sc->intr_assert = intr_assert; 828 sc->intr_deassert = intr_deassert; 829 830 pthread_mutex_init(&sc->mtx, NULL); 831 832 uart_reset(sc); 833 834 return (sc); 835 } 836 837 #ifndef __FreeBSD__ 838 static int 839 uart_sock_backend(struct uart_softc *sc, const char *inopts) 840 { 841 char *opts; 842 char *opt; 843 char *nextopt; 844 char *path = NULL; 845 846 if (strncmp(inopts, "socket,", 7) != 0) { 847 return (-1); 848 } 849 if ((opts = strdup(inopts + 7)) == NULL) { 850 return (-1); 851 } 852 853 nextopt = opts; 854 for (opt = strsep(&nextopt, ","); opt != NULL; 855 opt = strsep(&nextopt, ",")) { 856 if (path == NULL && *opt == '/') { 857 path = opt; 858 continue; 859 } 860 /* 861 * XXX check for server and client options here. For now, 862 * everything is a server 863 */ 864 free(opts); 865 return (-1); 866 } 867 868 sc->usc_sock.clifd = -1; 869 if ((sc->usc_sock.servfd = init_sock(path)) == -1) { 870 free(opts); 871 return (-1); 872 } 873 sc->sock = true; 874 sc->tty.rfd = sc->tty.wfd = -1; 875 sc->usc_sock.servmev = mevent_add(sc->usc_sock.servfd, EVF_READ, 876 uart_sock_accept, sc); 877 assert(sc->usc_sock.servmev != NULL); 878 879 return (0); 880 } 881 #endif /* not __FreeBSD__ */ 882 883 static int 884 uart_stdio_backend(struct uart_softc *sc) 885 { 886 #ifndef WITHOUT_CAPSICUM 887 cap_rights_t rights; 888 cap_ioctl_t cmds[] = { TIOCGETA, TIOCSETA, TIOCGWINSZ }; 889 #endif 890 891 if (uart_stdio) 892 return (-1); 893 894 sc->tty.rfd = STDIN_FILENO; 895 sc->tty.wfd = STDOUT_FILENO; 896 sc->tty.opened = true; 897 898 if (fcntl(sc->tty.rfd, F_SETFL, O_NONBLOCK) != 0) 899 return (-1); 900 if (fcntl(sc->tty.wfd, F_SETFL, O_NONBLOCK) != 0) 901 return (-1); 902 903 #ifndef WITHOUT_CAPSICUM 904 cap_rights_init(&rights, CAP_EVENT, CAP_IOCTL, CAP_READ); 905 if (caph_rights_limit(sc->tty.rfd, &rights) == -1) 906 errx(EX_OSERR, "Unable to apply rights for sandbox"); 907 if (caph_ioctls_limit(sc->tty.rfd, cmds, nitems(cmds)) == -1) 908 errx(EX_OSERR, "Unable to apply rights for sandbox"); 909 #endif 910 911 uart_stdio = true; 912 913 return (0); 914 } 915 916 static int 917 uart_tty_backend(struct uart_softc *sc, const char *opts) 918 { 919 #ifndef WITHOUT_CAPSICUM 920 cap_rights_t rights; 921 cap_ioctl_t cmds[] = { TIOCGETA, TIOCSETA, TIOCGWINSZ }; 922 #endif 923 int fd; 924 925 fd = open(opts, O_RDWR | O_NONBLOCK); 926 if (fd < 0) 927 return (-1); 928 929 if (!isatty(fd)) { 930 close(fd); 931 return (-1); 932 } 933 934 sc->tty.rfd = sc->tty.wfd = fd; 935 sc->tty.opened = true; 936 937 #ifndef WITHOUT_CAPSICUM 938 cap_rights_init(&rights, CAP_EVENT, CAP_IOCTL, CAP_READ, CAP_WRITE); 939 if (caph_rights_limit(fd, &rights) == -1) 940 errx(EX_OSERR, "Unable to apply rights for sandbox"); 941 if (caph_ioctls_limit(fd, cmds, nitems(cmds)) == -1) 942 errx(EX_OSERR, "Unable to apply rights for sandbox"); 943 #endif 944 945 return (0); 946 } 947 948 int 949 uart_set_backend(struct uart_softc *sc, const char *opts) 950 { 951 int retval; 952 953 if (opts == NULL) 954 return (0); 955 956 #ifndef __FreeBSD__ 957 if (strncmp("socket,", opts, 7) == 0) 958 return (uart_sock_backend(sc, opts)); 959 #endif 960 if (strcmp("stdio", opts) == 0) 961 retval = uart_stdio_backend(sc); 962 else 963 retval = uart_tty_backend(sc, opts); 964 if (retval == 0) 965 uart_opentty(sc); 966 967 return (retval); 968 } 969