amd64 loader: Use efiserialio for Hyper-V booted systems
UEFI provides ConIn/ConOut handles for consoles that it supports, which include the text-video and serial ports. When the serial port is available, use the UEFI driver instead of direct io-port accesses to avoid conflicts between the firmware and direct hardware access, as happens on Hyper-V (Azure) setups. This change enables efiserialio to be built for efi-amd64 and has higher order priority vs comconsole, and only uses efiserialio if the hypervisor is Hyper-V. When efiserialio successfully probes, it will set efi_comconsole_avail=true which will prevent comconsole from probing in this setup. Tested on Hyper-V, ESXi and Azure VMs. PR: 264267 Reviewed by: kevans, whu Tested by: whu Obtained from: Rubicon Communications, LLC (Netgate) MFC after: 2 weeks Sponsored by: Rubicon Communications, LLC (Netgate)
This commit is contained in:
parent
ab3ff87a33
commit
927358dd98
@ -5,6 +5,7 @@ SRCS+= amd64_tramp.S \
|
||||
elf64_freebsd.c \
|
||||
trap.c \
|
||||
multiboot2.c \
|
||||
efiserialio.c \
|
||||
exc.S
|
||||
|
||||
.PATH: ${BOOTSRC}/i386/libi386
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user