1 /* 2 * Copyright (c) 1998 Michael Smith (msmith@freebsd.org) 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26 #include <sys/cdefs.h> 27 28 #include <stand.h> 29 #include <sys/errno.h> 30 #include <bootstrap.h> 31 #include <stdbool.h> 32 33 #include <efi.h> 34 #include <efilib.h> 35 #include <efidevp.h> 36 #include <Protocol/SerialIo.h> 37 #include <Protocol/SuperIo.h> 38 #include <Protocol/IsaIo.h> 39 40 EFI_GUID gEfiSerialIoProtocolGuid = SERIAL_IO_PROTOCOL; 41 EFI_GUID gEfiSerialTerminalDeviceTypeGuid = \ 42 EFI_SERIAL_TERMINAL_DEVICE_TYPE_GUID; 43 EFI_GUID gEfiSioProtocolGuid = EFI_SIO_PROTOCOL_GUID; 44 45 #define COMC_TXWAIT 0x40000 /* transmit timeout */ 46 #define COM1_IOADDR 0x3f8 47 #define COM2_IOADDR 0x2f8 48 #define COM3_IOADDR 0x3e8 49 #define COM4_IOADDR 0x2e8 50 51 #define PNP0501 0x501 /* 16550A-compatible COM port */ 52 53 /* List of serial ports, set up by efi_serial_ini() */ 54 serial_list_t serials = STAILQ_HEAD_INITIALIZER(serials); 55 56 static void efi_serial_probe(struct console *); 57 static int efi_serial_init(struct console *, int); 58 static void efi_serial_putchar(struct console *, int); 59 static int efi_serial_getchar(struct console *); 60 static int efi_serial_ischar(struct console *); 61 static int efi_serial_ioctl(struct console *, int, void *); 62 static void efi_serial_devinfo(struct console *); 63 static bool efi_serial_setup(struct console *); 64 static char *efi_serial_asprint_mode(struct serial *); 65 static int efi_serial_parse_mode(struct serial *, const char *); 66 static int efi_serial_mode_set(struct env_var *, int, const void *); 67 static int efi_serial_cd_set(struct env_var *, int, const void *); 68 static int efi_serial_rtsdtr_set(struct env_var *, int, const void *); 69 70 extern struct console efi_console; 71 72 static bool 73 efi_serial_should_append(struct serial *port) 74 { 75 EFI_DEVICE_PATH *node, *dev; 76 EFI_STATUS status; 77 const char *name; 78 char *buf; 79 size_t sz; 80 bool rv = true; 81 82 if (port->currdev == NULL) 83 return (rv); 84 85 buf = NULL; 86 sz = 0; 87 name = "ConOut"; 88 status = efi_global_getenv(name, buf, &sz); 89 /* Some systems do not provide ConOut, also check ConIn */ 90 if (EFI_ERROR(status) && status != EFI_BUFFER_TOO_SMALL) { 91 name = "ConIn"; 92 status = efi_global_getenv(name, buf, &sz); 93 } 94 if (status == EFI_BUFFER_TOO_SMALL) { 95 buf = malloc(sz); 96 if (buf == NULL) 97 return (rv); 98 status = efi_global_getenv(name, buf, &sz); 99 } 100 if (EFI_ERROR(status)) { 101 free(buf); 102 return (rv); 103 } 104 105 dev = efi_lookup_devpath(port->currdev); 106 if (dev == NULL) { 107 free(buf); 108 return (rv); 109 } 110 111 node = (EFI_DEVICE_PATH *)buf; 112 /* 113 * We only need to know if this port is first in list. 114 * This is only important when "os_console" is not set. 115 */ 116 if (!IsDevicePathEnd(node) && efi_devpath_is_prefix(dev, node)) 117 rv = false; 118 119 efi_close_devpath(dev); 120 free(buf); 121 return (rv); 122 } 123 124 static void 125 efi_serial_setup_env(struct console *tty) 126 { 127 struct serial *port = tty->c_private; 128 char name[20]; 129 char value[20]; 130 char *env; 131 132 (void) snprintf(name, sizeof (name), "%s-mode", tty->c_name); 133 env = getenv(name); 134 if (env != NULL) 135 (void) efi_serial_parse_mode(port, env); 136 env = efi_serial_asprint_mode(port); 137 if (env != NULL) { 138 (void) unsetenv(name); 139 (void) env_setenv(name, EV_VOLATILE, env, efi_serial_mode_set, 140 env_nounset); 141 if (port->is_efi_console) { 142 (void) snprintf(name, sizeof (name), "%s-spcr-mode", 143 tty->c_name); 144 (void) setenv(name, env, 1); 145 free(env); 146 147 /* Add us to console list. */ 148 (void) snprintf(name, sizeof (name), "console"); 149 env = getenv(name); 150 if (env == NULL) { 151 (void) setenv(name, tty->c_name, 1); 152 } else { 153 char *ptr; 154 int rv; 155 156 /* 157 * we have "text" already in place, 158 * check if we need to add 159 * serial console before or after. 160 */ 161 if (efi_serial_should_append(port)) 162 rv = asprintf(&ptr, "%s,%s", env, 163 tty->c_name); 164 else 165 rv = asprintf(&ptr, "%s,%s", 166 tty->c_name, env); 167 if (rv > 0) { 168 (void) setenv(name, ptr, 1); 169 free(ptr); 170 } else { 171 printf("%s: %s\n", __func__, 172 strerror(ENOMEM)); 173 } 174 } 175 } else { 176 free(env); 177 } 178 } 179 180 (void) snprintf(name, sizeof (name), "%s-ignore-cd", tty->c_name); 181 env = getenv(name); 182 if (env != NULL) { 183 if (strcmp(env, "true") == 0) 184 port->ignore_cd = 1; 185 else if (strcmp(env, "false") == 0) 186 port->ignore_cd = 0; 187 } 188 189 (void) snprintf(value, sizeof (value), "%s", 190 port->ignore_cd? "true" : "false"); 191 (void) unsetenv(name); 192 (void) env_setenv(name, EV_VOLATILE, value, efi_serial_cd_set, 193 env_nounset); 194 195 (void) snprintf(name, sizeof (name), "%s-rts-dtr-off", tty->c_name); 196 env = getenv(name); 197 if (env != NULL) { 198 if (strcmp(env, "true") == 0) 199 port->rtsdtr_off = 1; 200 else if (strcmp(env, "false") == 0) 201 port->rtsdtr_off = 0; 202 } 203 204 (void) snprintf(value, sizeof (value), "%s", 205 port->rtsdtr_off? "true" : "false"); 206 (void) unsetenv(name); 207 (void) env_setenv(name, EV_VOLATILE, value, efi_serial_rtsdtr_set, 208 env_nounset); 209 } 210 211 static void 212 efi_check_and_set_condev(struct serial *port, const char *name) 213 { 214 EFI_DEVICE_PATH *node, *dev; 215 EFI_STATUS status; 216 char *buf; 217 size_t sz; 218 219 if (port->currdev == NULL) 220 return; 221 222 buf = NULL; 223 sz = 0; 224 status = efi_global_getenv(name, buf, &sz); 225 if (status == EFI_BUFFER_TOO_SMALL) { 226 buf = malloc(sz); 227 if (buf == NULL) 228 return; 229 status = efi_global_getenv(name, buf, &sz); 230 } 231 if (EFI_ERROR(status)) { 232 free(buf); 233 return; 234 } 235 236 dev = efi_lookup_devpath(port->currdev); 237 if (dev == NULL) { 238 free(buf); 239 return; 240 } 241 242 node = (EFI_DEVICE_PATH *)buf; 243 while (!IsDevicePathEnd(node)) { 244 /* Sanity check the node before moving to the next node. */ 245 if (DevicePathNodeLength(node) < sizeof (*node)) 246 break; 247 248 if (efi_devpath_is_prefix(dev, node)) { 249 port->is_efi_console = true; 250 break; 251 } 252 253 node = efi_devpath_next_instance(node); 254 } 255 256 efi_close_devpath(dev); 257 free(buf); 258 } 259 260 /* 261 * Get list of super io handles, get device path and check if this 262 * sio device path is parent of serial io device. 263 */ 264 static EFI_STATUS 265 efi_get_io_handle(EFI_HANDLE *handles, uint_t nhandles, EFI_DEVICE_PATH *dp, 266 EFI_HANDLE *hp) 267 { 268 EFI_HANDLE h; 269 EFI_DEVICE_PATH *parent; 270 271 h = NULL; 272 for (uint_t i = 0; i < nhandles; i++) { 273 parent = efi_lookup_devpath(handles[i]); 274 if (parent == NULL) 275 continue; 276 if (efi_devpath_is_prefix(parent, dp)) { 277 h = handles[i]; 278 efi_close_devpath(h); 279 break; 280 } 281 efi_close_devpath(handles[i]); 282 } 283 284 if (h == NULL) 285 return (EFI_NOT_FOUND); 286 *hp = h; 287 return (EFI_SUCCESS); 288 } 289 290 /* 291 * Use this super io protocol instance to identify serial port. 292 */ 293 static EFI_STATUS 294 efi_get_sio_serial_name(EFI_HANDLE handle, char *id) 295 { 296 EFI_STATUS status; 297 EFI_SIO_PROTOCOL *sio; 298 ACPI_RESOURCE_HEADER_PTR rl; 299 EFI_ACPI_IO_PORT_DESCRIPTOR *io; 300 EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR *fixedio; 301 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *as; 302 UINT64 base_address = 0; 303 char name; 304 305 status = BS->OpenProtocol(handle, &gEfiSioProtocolGuid, 306 (void **)&sio, IH, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); 307 if (!EFI_ERROR(status)) { 308 status = sio->GetResources(sio, &rl); 309 (void) BS->CloseProtocol(handle, &gEfiSioProtocolGuid, 310 IH, NULL); 311 } 312 313 if (EFI_ERROR(status)) { 314 return (status); 315 } 316 317 while (rl.SmallHeader->Byte != ACPI_END_TAG_DESCRIPTOR && 318 base_address == 0) { 319 switch (rl.SmallHeader->Byte) { 320 case ACPI_IO_PORT_DESCRIPTOR: 321 io = (EFI_ACPI_IO_PORT_DESCRIPTOR *)rl.SmallHeader; 322 if (io->Length != 0) 323 base_address = io->BaseAddressMin; 324 break; 325 326 case ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR: 327 fixedio = 328 (EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR *) 329 rl.SmallHeader; 330 if (fixedio->Length != 0) 331 base_address = fixedio->BaseAddress; 332 break; 333 334 case ACPI_ADDRESS_SPACE_DESCRIPTOR: 335 as = (void *)rl.SmallHeader; 336 if (as->AddrLen != 0) 337 base_address = as->AddrRangeMin; 338 break; 339 } 340 341 if (rl.SmallHeader->Bits.Type == 0) { 342 rl.SmallHeader = (ACPI_SMALL_RESOURCE_HEADER *) 343 ((UINT8 *)rl.SmallHeader + 344 rl.SmallHeader->Bits.Length + 345 sizeof (rl.SmallHeader)); 346 } else { 347 rl.LargeHeader = (ACPI_LARGE_RESOURCE_HEADER *) 348 ((UINT8 *)rl.LargeHeader + 349 rl.LargeHeader->Length + 350 sizeof (rl.LargeHeader)); 351 } 352 } 353 354 /* 355 * On x86, we name COM1-COM4 as ttya-ttyd. 356 */ 357 switch (base_address) { 358 case COM1_IOADDR: 359 name = 'a'; 360 break; 361 362 case COM2_IOADDR: 363 name = 'b'; 364 break; 365 366 case COM3_IOADDR: 367 name = 'c'; 368 break; 369 370 case COM4_IOADDR: 371 name = 'd'; 372 break; 373 374 default: 375 return (EFI_NOT_FOUND); 376 } 377 378 *id = name; 379 return (status); 380 } 381 382 /* 383 * Use this ISA io protocol instance to identify serial port. 384 */ 385 static EFI_STATUS 386 efi_get_isaio_serial_name(EFI_HANDLE handle, char *id) 387 { 388 EFI_STATUS status; 389 EFI_ISA_IO_PROTOCOL *io; 390 UINT32 StartRange = 0; 391 char name; 392 393 status = BS->OpenProtocol(handle, &gEfiIsaIoProtocolGuid, 394 (void **)&io, IH, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); 395 if (EFI_ERROR(status)) 396 return (status); 397 398 for (uint_t i = 0; 399 io->ResourceList->ResourceItem[i].Type != 400 EfiIsaAcpiResourceEndOfList; 401 i++) { 402 switch (io->ResourceList->ResourceItem[i].Type) { 403 case EfiIsaAcpiResourceIo: 404 StartRange = 405 io->ResourceList->ResourceItem[i].StartRange; 406 break; 407 default: 408 break; 409 } 410 } 411 (void) BS->CloseProtocol(handle, &gEfiIsaIoProtocolGuid, IH, NULL); 412 413 switch (StartRange) { 414 case COM1_IOADDR: 415 name = 'a'; 416 break; 417 418 case COM2_IOADDR: 419 name = 'b'; 420 break; 421 422 case COM3_IOADDR: 423 name = 'c'; 424 break; 425 426 case COM4_IOADDR: 427 name = 'd'; 428 break; 429 430 default: 431 return (EFI_NOT_FOUND); 432 } 433 434 *id = name; 435 return (status); 436 } 437 438 /* 439 * Return UID from ACPI_EXTENDED_HID_DEVICE_PATH. 440 */ 441 uint32_t 442 efi_get_acpiex_uid(ACPI_EXTENDED_HID_DEVICE_PATH *acpiex) 443 { 444 char *_HIDSTR, *_UIDSTR; 445 unsigned long tmp; 446 char *end; 447 448 _HIDSTR = (char *)acpiex + 16; 449 _UIDSTR = _HIDSTR + strlen(_HIDSTR) + 1; 450 451 if (*_UIDSTR != '\0') { 452 errno = 0; 453 tmp = strtoul(_UIDSTR, &end, 0); 454 if (errno == 0) { 455 return (tmp); 456 } 457 /* 458 * in case of error, we have option to panic 459 * or return UID. There is no screen output yet. 460 */ 461 } 462 463 return (acpiex->UID); 464 } 465 466 /* 467 * walk device path and check each node. 468 * if node is ACPI dp for serial port, use UID to set name. 469 */ 470 static EFI_STATUS 471 efi_get_acpi_name(EFI_DEVICE_PATH *dp, char *id) 472 { 473 ACPI_HID_DEVICE_PATH *acpi; 474 ACPI_EXTENDED_HID_DEVICE_PATH *acpiex; 475 EFI_STATUS status; 476 char *_HIDSTR; 477 478 status = EFI_NOT_FOUND; 479 acpiex = NULL; 480 _HIDSTR = NULL; 481 482 while (!IsDevicePathEnd(dp)) { 483 if (DevicePathType(dp) == ACPI_DEVICE_PATH) { 484 acpi = (ACPI_HID_DEVICE_PATH *)dp; 485 if (DevicePathSubType(dp) == ACPI_DP && 486 acpi->HID == EISA_PNP_ID(PNP0501)) { 487 *id = 'a' + acpi->UID; 488 status = EFI_SUCCESS; 489 break; 490 } 491 492 acpiex = (ACPI_EXTENDED_HID_DEVICE_PATH *)dp; 493 /* 494 * acpi extended structure may additionally have 495 * _HIDSTR, _UIDSTR, _CIDSTR string data, 496 * if present, they override HID, UID and CID 497 * fields. Either HID or _HIDSTR must be present. 498 */ 499 _HIDSTR = (char *)dp + 16; 500 /* 501 * From note in ACPICA source (AcpiNsRepair_HID()), 502 * there are many machines with ID starting with 503 * asterisk. We use same approach here as in acpica. 504 * Note: I have no idea if UEFI device path creation 505 * already handles this, but lets play safe. 506 */ 507 if (*_HIDSTR == '*') 508 _HIDSTR++; 509 510 if (DevicePathSubType(dp) == ACPI_EXTENDED_DP && 511 (acpiex->HID == EISA_PNP_ID(PNP0501) || 512 acpiex->CID == EISA_PNP_ID(PNP0501) || 513 strncmp(_HIDSTR, "UART", 4) == 0)) { 514 *id = 'a' + efi_get_acpiex_uid(acpiex); 515 status = EFI_SUCCESS; 516 break; 517 } 518 } 519 dp = NextDevicePathNode(dp); 520 } 521 522 return (status); 523 } 524 525 /* 526 * SERIAL IO protocol is abstraction on top of actual device 527 */ 528 static void 529 efi_set_serial_name(struct console *tty) 530 { 531 struct serial *p, *port = tty->c_private; 532 EFI_DEVICE_PATH *dp; 533 EFI_STATUS status; 534 EFI_HANDLE *handles, handle; 535 uint_t nhandles; 536 537 dp = efi_lookup_devpath(port->currdev); 538 if (dp != NULL) { 539 /* Try to detect actual IO protocol */ 540 status = efi_get_protocol_handles(&gEfiSioProtocolGuid, 541 &nhandles, &handles); 542 if (!EFI_ERROR(status)) { 543 status = efi_get_io_handle(handles, nhandles, 544 dp, &handle); 545 free(handles); 546 if (!EFI_ERROR(status)) { 547 port->iodev = handle; 548 status = efi_get_sio_serial_name(handle, 549 &port->name); 550 /* It is SIO serial device, we are done. */ 551 goto done; 552 } 553 } 554 555 status = efi_get_protocol_handles(&gEfiIsaIoProtocolGuid, 556 &nhandles, &handles); 557 if (!EFI_ERROR(status)) { 558 status = efi_get_io_handle(handles, nhandles, 559 dp, &handle); 560 free(handles); 561 if (!EFI_ERROR(status)) { 562 port->iodev = handle; 563 status = efi_get_isaio_serial_name(handle, 564 &port->name); 565 /* It is ISAIO serial device, we are done. */ 566 goto done; 567 } 568 } 569 570 /* 571 * Still nothing? check, if we have ACPI device path. 572 */ 573 status = efi_get_acpi_name(dp, &port->name); 574 done: 575 if (EFI_ERROR(status)) { 576 /* 577 * We have serial port but unknown hw driver. 578 * If we do not have serial ports registered, 579 * start from ttya, otherwise from tty0. 580 * Other option would be to do this only in case of 581 * VenHw device path. 582 */ 583 if (STAILQ_EMPTY(&serials)) 584 port->name = 'a'; 585 else 586 port->name = '0'; 587 588 STAILQ_FOREACH(p, &serials, next) { 589 if (p->name == port->name) 590 port->name++; 591 } 592 } 593 efi_close_devpath(dp); 594 } 595 596 (void) asprintf(&tty->c_name, "tty%c", port->name); 597 (void) asprintf(&tty->c_desc, "serial port %c", port->name); 598 } 599 600 static uint_t 601 efi_serial_create_port(uint_t c, EFI_HANDLE handle) 602 { 603 struct console *tty; 604 struct serial *port; 605 EFI_STATUS status; 606 607 tty = calloc(1, sizeof (*tty)); 608 if (tty == NULL) { 609 /* Out of memory?! can not continue */ 610 consoles[c] = tty; 611 return (c); 612 } 613 port = calloc(1, sizeof (*port)); 614 if (port == NULL) { 615 free(tty); 616 consoles[c] = NULL; 617 return (c); 618 } 619 620 /* Set up port descriptor */ 621 port->currdev = handle; 622 status = BS->OpenProtocol(handle, &gEfiSerialIoProtocolGuid, 623 (void **)&port->io.sio, IH, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); 624 if (EFI_ERROR(status)) { 625 free(tty); 626 free(port); 627 consoles[c] = NULL; 628 return (c); 629 } 630 631 port->guid = &gEfiSerialIoProtocolGuid; 632 port->baudrate = port->io.sio->Mode->BaudRate; 633 port->timeout = port->io.sio->Mode->Timeout; 634 port->receivefifodepth = port->io.sio->Mode->ReceiveFifoDepth; 635 port->databits = port->io.sio->Mode->DataBits; 636 port->parity = port->io.sio->Mode->Parity; 637 port->stopbits = port->io.sio->Mode->StopBits; 638 port->ignore_cd = true; /* ignore cd */ 639 port->rtsdtr_off = false; /* rts-dtr is on */ 640 641 /* Set up serial device descriptor */ 642 tty->c_private = port; 643 efi_set_serial_name(tty); 644 tty->c_flags = C_PRESENTIN | C_PRESENTOUT; 645 tty->c_probe = efi_serial_probe; 646 tty->c_init = efi_serial_init; 647 tty->c_out = efi_serial_putchar; 648 tty->c_in = efi_serial_getchar; 649 tty->c_ready = efi_serial_ischar; 650 tty->c_ioctl = efi_serial_ioctl; 651 tty->c_devinfo = efi_serial_devinfo; 652 STAILQ_INSERT_TAIL(&serials, port, next); 653 consoles[c++] = tty; 654 consoles[c] = NULL; 655 656 /* Reset terminal to initial normal settings with ESC [ 0 m */ 657 efi_serial_putchar(tty, 0x1b); 658 efi_serial_putchar(tty, '['); 659 efi_serial_putchar(tty, '0'); 660 efi_serial_putchar(tty, 'm'); 661 /* drain input from random data */ 662 while (efi_serial_getchar(tty) != -1) 663 ; 664 665 /* check if we are listed in ConIn */ 666 efi_check_and_set_condev(port, "ConIn"); 667 efi_serial_setup_env(tty); 668 return (c); 669 } 670 671 /* 672 * Set up list of possible serial consoles. 673 * This function is run very early, so we do not expect to 674 * run out of memory, and on error, we can not print output. 675 */ 676 void 677 efi_serial_ini(void) 678 { 679 EFI_STATUS status; 680 EFI_HANDLE *handles; 681 uint_t c, n, index, nhandles; 682 struct console **tmp; 683 684 status = efi_get_protocol_handles(&gEfiSerialIoProtocolGuid, &nhandles, 685 &handles); 686 if (EFI_ERROR(status)) 687 return; 688 689 if (nhandles == 0) 690 return; 691 692 n = nhandles; 693 c = cons_array_size(); 694 if (c == 0) 695 n++; /* For NULL pointer */ 696 697 tmp = realloc(consoles, (c + n) * sizeof (*consoles)); 698 if (tmp == NULL) { 699 free(handles); 700 return; 701 } 702 consoles = tmp; 703 if (c > 0) 704 c--; 705 706 for (index = 0; index < nhandles; index++) { 707 c = efi_serial_create_port(c, handles[index]); 708 } 709 free(handles); 710 } 711 712 static void 713 efi_serial_probe(struct console *cp) 714 { 715 cp->c_flags = C_PRESENTIN | C_PRESENTOUT; 716 } 717 718 static int 719 efi_serial_init(struct console *cp, int arg __unused) 720 { 721 722 if (efi_serial_setup(cp)) 723 return (CMD_OK); 724 725 cp->c_flags = 0; 726 return (CMD_ERROR); 727 } 728 729 static void 730 efi_serial_putchar(struct console *cp, int c) 731 { 732 int wait; 733 EFI_STATUS status; 734 UINTN bufsz = 1; 735 char cb = c; 736 struct serial *sp = cp->c_private; 737 738 if (sp->io.sio == NULL) 739 return; 740 741 for (wait = COMC_TXWAIT; wait > 0; wait--) { 742 status = sp->io.sio->Write(sp->io.sio, &bufsz, &cb); 743 if (status != EFI_TIMEOUT) 744 break; 745 } 746 } 747 748 static int 749 efi_serial_getchar(struct console *cp) 750 { 751 EFI_STATUS status; 752 UINTN bufsz = 1; 753 char c; 754 struct serial *sp = cp->c_private; 755 756 /* 757 * if this device is also used as ConIn, some firmwares 758 * fail to return all input via SIO protocol. 759 */ 760 if (sp->is_efi_console) { 761 return (efi_console.c_in(&efi_console)); 762 } 763 764 if (sp->io.sio == NULL || !efi_serial_ischar(cp)) 765 return (-1); 766 767 status = sp->io.sio->Read(sp->io.sio, &bufsz, &c); 768 if (EFI_ERROR(status) || bufsz == 0) 769 return (-1); 770 771 return (c); 772 } 773 774 static int 775 efi_serial_ischar(struct console *cp) 776 { 777 EFI_STATUS status; 778 uint32_t control; 779 struct serial *sp = cp->c_private; 780 781 /* 782 * if this device is also used as ConIn, some firmwares 783 * fail to return all input via SIO protocol. 784 */ 785 if (sp->is_efi_console) { 786 return (efi_console.c_ready(&efi_console)); 787 } 788 789 if (sp->io.sio == NULL) 790 return (0); 791 792 status = sp->io.sio->GetControl(sp->io.sio, &control); 793 if (EFI_ERROR(status)) 794 return (0); 795 796 return (!(control & EFI_SERIAL_INPUT_BUFFER_EMPTY)); 797 } 798 799 static int 800 efi_serial_ioctl(struct console *cp __unused, int cmd __unused, 801 void *data __unused) 802 { 803 return (ENOTTY); 804 } 805 806 static void 807 efi_serial_devinfo(struct console *cp) 808 { 809 struct serial *port = cp->c_private; 810 EFI_DEVICE_PATH *dp; 811 CHAR16 *text; 812 813 if (port->currdev == NULL) { 814 printf("\tdevice is not present"); 815 return; 816 } 817 818 dp = efi_lookup_devpath(port->currdev); 819 if (dp == NULL) 820 return; 821 822 text = efi_devpath_name(dp); 823 if (text == NULL) 824 return; 825 826 printf("\t%S", text); 827 efi_free_devpath_name(text); 828 efi_close_devpath(port->currdev); 829 } 830 831 static char * 832 efi_serial_asprint_mode(struct serial *sp) 833 { 834 char par, *buf; 835 char *stop; 836 837 if (sp == NULL) 838 return (NULL); 839 840 switch (sp->parity) { 841 case NoParity: 842 par = 'n'; 843 break; 844 case EvenParity: 845 par = 'e'; 846 break; 847 case OddParity: 848 par = 'o'; 849 break; 850 case MarkParity: 851 par = 'm'; 852 break; 853 case SpaceParity: 854 par = 's'; 855 break; 856 default: 857 par = 'n'; 858 break; 859 } 860 861 switch (sp->stopbits) { 862 case OneStopBit: 863 stop = "1"; 864 break; 865 case TwoStopBits: 866 stop = "2"; 867 break; 868 case OneFiveStopBits: 869 stop = "1.5"; 870 break; 871 default: 872 stop = "1"; 873 break; 874 } 875 876 (void) asprintf(&buf, "%ju,%d,%c,%s,-", sp->baudrate, sp->databits, 877 par, stop); 878 return (buf); 879 } 880 881 static int 882 efi_serial_parse_mode(struct serial *sp, const char *value) 883 { 884 unsigned long n; 885 uint64_t baudrate; 886 uint8_t databits = 8; 887 int parity = NoParity; 888 int stopbits = OneStopBit; 889 char *ep; 890 891 if (value == NULL || *value == '\0') 892 return (CMD_ERROR); 893 894 errno = 0; 895 n = strtoul(value, &ep, 10); 896 if (errno != 0 || *ep != ',') 897 return (CMD_ERROR); 898 baudrate = n; 899 900 ep++; 901 n = strtoul(ep, &ep, 10); 902 if (errno != 0 || *ep != ',') 903 return (CMD_ERROR); 904 905 switch (n) { 906 case 5: databits = 5; 907 break; 908 case 6: databits = 6; 909 break; 910 case 7: databits = 7; 911 break; 912 case 8: databits = 8; 913 break; 914 default: 915 return (CMD_ERROR); 916 } 917 918 ep++; 919 switch (*ep++) { 920 case 'n': parity = NoParity; 921 break; 922 case 'e': parity = EvenParity; 923 break; 924 case 'o': parity = OddParity; 925 break; 926 case 'm': parity = MarkParity; 927 break; 928 case 's': parity = SpaceParity; 929 break; 930 default: 931 return (CMD_ERROR); 932 } 933 934 if (*ep == ',') 935 ep++; 936 else 937 return (CMD_ERROR); 938 939 switch (*ep++) { 940 case '1': stopbits = OneStopBit; 941 if (ep[0] == '.' && ep[1] == '5') { 942 ep += 2; 943 stopbits = OneFiveStopBits; 944 } 945 break; 946 case '2': stopbits = TwoStopBits; 947 break; 948 default: 949 return (CMD_ERROR); 950 } 951 952 /* handshake is ignored, but we check syntax anyhow */ 953 if (*ep == ',') 954 ep++; 955 else 956 return (CMD_ERROR); 957 958 switch (*ep++) { 959 case '-': 960 case 'h': 961 case 's': 962 break; 963 default: 964 return (CMD_ERROR); 965 } 966 967 if (*ep != '\0') 968 return (CMD_ERROR); 969 970 sp->baudrate = baudrate; 971 sp->databits = databits; 972 sp->parity = parity; 973 sp->stopbits = stopbits; 974 return (CMD_OK); 975 } 976 977 static int 978 efi_serial_mode_set(struct env_var *ev, int flags, const void *value) 979 { 980 struct console *cp; 981 982 if (value == NULL) 983 return (CMD_ERROR); 984 985 if ((cp = cons_get_console(ev->ev_name)) == NULL) 986 return (CMD_ERROR); 987 988 if (efi_serial_parse_mode(cp->c_private, value) == CMD_ERROR) 989 return (CMD_ERROR); 990 991 (void) efi_serial_setup(cp); 992 993 (void) env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL); 994 995 return (CMD_OK); 996 } 997 998 static int 999 efi_serial_cd_set(struct env_var *ev, int flags, const void *value) 1000 { 1001 struct console *cp; 1002 struct serial *sp; 1003 1004 if (value == NULL) 1005 return (CMD_OK); 1006 1007 if ((cp = cons_get_console(ev->ev_name)) == NULL) 1008 return (CMD_OK); 1009 1010 sp = cp->c_private; 1011 if (strcmp(value, "true") == 0) 1012 sp->ignore_cd = true; 1013 else if (strcmp(value, "false") == 0) 1014 sp->ignore_cd = false; 1015 else 1016 return (CMD_OK); 1017 1018 (void) efi_serial_setup(cp); 1019 1020 (void) env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL); 1021 1022 return (CMD_OK); 1023 } 1024 1025 static int 1026 efi_serial_rtsdtr_set(struct env_var *ev, int flags, const void *value) 1027 { 1028 struct console *cp; 1029 struct serial *sp; 1030 1031 if (value == NULL) 1032 return (CMD_OK); 1033 1034 if ((cp = cons_get_console(ev->ev_name)) == NULL) 1035 return (CMD_OK); 1036 1037 sp = cp->c_private; 1038 if (strcmp(value, "true") == 0) 1039 sp->rtsdtr_off = true; 1040 else if (strcmp(value, "false") == 0) 1041 sp->rtsdtr_off = false; 1042 else 1043 return (CMD_OK); 1044 1045 (void) efi_serial_setup(cp); 1046 1047 (void) env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL); 1048 1049 return (CMD_OK); 1050 } 1051 1052 /* 1053 * In case of error, we also reset ACTIVE flags, so the console 1054 * framefork will try alternate consoles. 1055 */ 1056 static bool 1057 efi_serial_setup(struct console *cp) 1058 { 1059 EFI_STATUS status; 1060 UINT32 control, new_control; 1061 struct serial *sp = cp->c_private; 1062 uint64_t baudrate; 1063 uint32_t timeout, receivefifodepth, databits; 1064 EFI_PARITY_TYPE parity; 1065 EFI_STOP_BITS_TYPE stopbits; 1066 bool change = false; 1067 1068 /* port is not usable */ 1069 if (sp->io.sio == NULL) 1070 return (false); 1071 1072 if (sp->io.sio->Reset != NULL) { 1073 status = sp->io.sio->Reset(sp->io.sio); 1074 if (EFI_ERROR(status)) 1075 return (false); 1076 } 1077 1078 if (sp->baudrate == sp->io.sio->Mode->BaudRate) { 1079 baudrate = 0; 1080 } else { 1081 baudrate = sp->baudrate; 1082 change = true; 1083 } 1084 if (sp->receivefifodepth == sp->io.sio->Mode->ReceiveFifoDepth) { 1085 receivefifodepth = 0; 1086 } else { 1087 receivefifodepth = sp->receivefifodepth; 1088 change = true; 1089 } 1090 if (sp->timeout == sp->io.sio->Mode->Timeout) { 1091 timeout = 0; 1092 } else { 1093 timeout = sp->timeout; 1094 change = true; 1095 } 1096 if (sp->parity == sp->io.sio->Mode->Parity) { 1097 parity = DefaultParity; 1098 } else { 1099 parity = sp->parity; 1100 change = true; 1101 } 1102 if (sp->databits == sp->io.sio->Mode->DataBits) { 1103 databits = 0; 1104 } else { 1105 databits = sp->databits; 1106 change = true; 1107 } 1108 if (sp->stopbits == sp->io.sio->Mode->StopBits) { 1109 stopbits = DefaultStopBits; 1110 } else { 1111 stopbits = sp->stopbits; 1112 change = true; 1113 } 1114 1115 if (change && sp->io.sio->SetAttributes != NULL) { 1116 status = sp->io.sio->SetAttributes(sp->io.sio, baudrate, 1117 receivefifodepth, timeout, parity, databits, stopbits); 1118 if (EFI_ERROR(status)) 1119 return (false); 1120 } 1121 1122 /* 1123 * Perform SetControl() only in case there was change in settings. 1124 */ 1125 control = new_control = 0; 1126 status = sp->io.sio->GetControl(sp->io.sio, &control); 1127 if (!EFI_ERROR(status)) { 1128 new_control = control; 1129 if (sp->rtsdtr_off) { 1130 new_control &= ~(EFI_SERIAL_REQUEST_TO_SEND | 1131 EFI_SERIAL_DATA_TERMINAL_READY); 1132 } else { 1133 new_control |= EFI_SERIAL_REQUEST_TO_SEND; 1134 } 1135 } 1136 1137 if (control != new_control) 1138 (void) sp->io.sio->SetControl(sp->io.sio, new_control); 1139 1140 /* Mark this port usable. */ 1141 cp->c_flags |= (C_PRESENTIN | C_PRESENTOUT); 1142 return (true); 1143 } 1144