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