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
efi_serial_should_append(struct serial * port)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
efi_serial_setup_env(struct console * tty)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
efi_check_and_set_condev(struct serial * port,const char * name)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
efi_get_io_handle(EFI_HANDLE * handles,uint_t nhandles,EFI_DEVICE_PATH * dp,EFI_HANDLE * hp)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
efi_get_sio_serial_name(EFI_HANDLE handle,char * id)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
efi_get_isaio_serial_name(EFI_HANDLE handle,char * id)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
efi_get_acpiex_uid(ACPI_EXTENDED_HID_DEVICE_PATH * acpiex)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
efi_get_acpi_name(EFI_DEVICE_PATH * dp,char * id)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
efi_set_serial_name(struct console * tty)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
efi_serial_create_port(uint_t c,EFI_HANDLE handle)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
efi_serial_ini(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
efi_serial_probe(struct console * cp)713 efi_serial_probe(struct console *cp)
714 {
715 cp->c_flags = C_PRESENTIN | C_PRESENTOUT;
716 }
717
718 static int
efi_serial_init(struct console * cp,int arg __unused)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
efi_serial_putchar(struct console * cp,int c)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
efi_serial_getchar(struct console * cp)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
efi_serial_ischar(struct console * cp)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
efi_serial_ioctl(struct console * cp __unused,int cmd __unused,void * data __unused)800 efi_serial_ioctl(struct console *cp __unused, int cmd __unused,
801 void *data __unused)
802 {
803 return (ENOTTY);
804 }
805
806 static void
efi_serial_devinfo(struct console * cp)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 *
efi_serial_asprint_mode(struct serial * sp)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
efi_serial_parse_mode(struct serial * sp,const char * value)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
efi_serial_mode_set(struct env_var * ev,int flags,const void * value)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
efi_serial_cd_set(struct env_var * ev,int flags,const void * value)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
efi_serial_rtsdtr_set(struct env_var * ev,int flags,const void * value)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
efi_serial_setup(struct console * cp)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