diff --git a/stand/efi/loader/arch/amd64/Makefile.inc b/stand/efi/loader/arch/amd64/Makefile.inc index 0d9e2648cb59..bd89044bd6c7 100644 --- a/stand/efi/loader/arch/amd64/Makefile.inc +++ b/stand/efi/loader/arch/amd64/Makefile.inc @@ -5,6 +5,7 @@ SRCS+= amd64_tramp.S \ elf64_freebsd.c \ trap.c \ multiboot2.c \ + efiserialio.c \ exc.S .PATH: ${BOOTSRC}/i386/libi386 diff --git a/stand/efi/loader/bootinfo.c b/stand/efi/loader/bootinfo.c index 939f2cf4c3fe..d79f59343af1 100644 --- a/stand/efi/loader/bootinfo.c +++ b/stand/efi/loader/bootinfo.c @@ -119,10 +119,17 @@ bi_getboothowto(char *kargs) if (tmp != NULL) speed = strtol(tmp, NULL, 0); tmp = getenv("efi_com_port"); - if (tmp == NULL) - tmp = getenv("comconsole_port"); if (tmp != NULL) port = strtol(tmp, NULL, 0); + if (port <= 0) { + tmp = getenv("comconsole_port"); + if (tmp != NULL) + port = strtol(tmp, NULL, 0); + else { + if (port == 0) + port = 0x3f8; + } + } if (speed != -1 && port != -1) { snprintf(buf, sizeof(buf), "io:%d,br:%d", port, speed); diff --git a/stand/efi/loader/conf.c b/stand/efi/loader/conf.c index 863c9188c72c..051e1a3381d1 100644 --- a/stand/efi/loader/conf.c +++ b/stand/efi/loader/conf.c @@ -81,6 +81,9 @@ struct netif_driver *netif_drivers[] = { extern struct console efi_console; extern struct console comconsole; +#if defined(__amd64__) +extern struct console eficomconsole; +#endif #if defined(__amd64__) || defined(__i386__) extern struct console nullconsole; extern struct console spinconsole; @@ -88,6 +91,9 @@ extern struct console spinconsole; struct console *consoles[] = { &efi_console, +#if defined(__amd64__) + &eficomconsole, +#endif &comconsole, #if defined(__amd64__) || defined(__i386__) &nullconsole, diff --git a/stand/efi/loader/efiserialio.c b/stand/efi/loader/efiserialio.c index 375e679d2590..5fbc700f6ac2 100644 --- a/stand/efi/loader/efiserialio.c +++ b/stand/efi/loader/efiserialio.c @@ -69,6 +69,11 @@ static int comc_speed_set(struct env_var *, int, const void *); static struct serial *comc_port; extern struct console efi_console; +bool efi_comconsole_avail = false; + +#if defined(__amd64__) +#define comconsole eficomconsole +#endif struct console comconsole = { .c_name = "comconsole", @@ -254,11 +259,22 @@ comc_probe(struct console *sc) char *env, *buf, *ep; size_t sz; +#if defined(__amd64__) + /* + * For x86-64, don't use this driver if not running in Hyper-V. + */ + env = getenv("smbios.bios.version"); + if (env == NULL || strncmp(env, "Hyper-V", 7) != 0) { + return; + } +#endif + if (comc_port == NULL) { comc_port = calloc(1, sizeof (struct serial)); if (comc_port == NULL) return; } + /* Use defaults from firmware */ comc_port->databits = 8; comc_port->parity = DefaultParity; @@ -308,6 +324,10 @@ comc_probe(struct console *sc) comc_port_set, env_nounset); env = getenv("efi_com_speed"); + if (env == NULL) + /* fallback to comconsole setting */ + env = getenv("comconsole_speed"); + if (comc_parse_intval(env, &val) == CMD_OK) comc_port->baudrate = val; @@ -318,8 +338,13 @@ comc_probe(struct console *sc) comc_speed_set, env_nounset); comconsole.c_flags = 0; - if (comc_setup()) + if (comc_setup()) { sc->c_flags = C_PRESENTIN | C_PRESENTOUT; + efi_comconsole_avail = true; + } else { + /* disable being seen as "comconsole" */ + comconsole.c_name = "efiserialio"; + } } static int @@ -489,6 +514,7 @@ comc_setup(void) { EFI_STATUS status; UINT32 control; + char *ev; /* port is not usable */ if (comc_port->sio == NULL) @@ -498,10 +524,17 @@ comc_setup(void) if (EFI_ERROR(status)) return (false); - status = comc_port->sio->SetAttributes(comc_port->sio, - comc_port->baudrate, comc_port->receivefifodepth, - comc_port->timeout, comc_port->parity, - comc_port->databits, comc_port->stopbits); + ev = getenv("smbios.bios.version"); + if (ev != NULL && strncmp(ev, "Hyper-V", 7) == 0) { + status = comc_port->sio->SetAttributes(comc_port->sio, + 0, 0, 0, DefaultParity, 0, DefaultStopBits); + } else { + status = comc_port->sio->SetAttributes(comc_port->sio, + comc_port->baudrate, comc_port->receivefifodepth, + comc_port->timeout, comc_port->parity, + comc_port->databits, comc_port->stopbits); + } + if (EFI_ERROR(status)) return (false); diff --git a/stand/i386/libi386/comconsole.c b/stand/i386/libi386/comconsole.c index ed1f1aa08ed7..3fbb6a292c19 100644 --- a/stand/i386/libi386/comconsole.c +++ b/stand/i386/libi386/comconsole.c @@ -85,6 +85,20 @@ comc_probe(struct console *cp) int speed, port; uint32_t locator; +#if defined(__amd64__) + extern bool efi_comconsole_avail; + + if (efi_comconsole_avail) { + /* + * If EFI provides serial I/O, then don't use this legacy + * com driver to avoid conflicts with the firmware's driver. + * Change c_name so that it cannot be found in the lookup. + */ + comconsole.c_name = "xcomconsole"; + return; + } +#endif + if (comc_curspeed == 0) { comc_curspeed = COMSPEED; /*