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