Index: stand/efi/include/efidevp.h =================================================================== --- stand/efi/include/efidevp.h +++ stand/efi/include/efidevp.h @@ -141,6 +141,9 @@ UINT32 CID; } ACPI_EXTENDED_HID_DEVICE_PATH; +#define ACPI_ADR_DP 0x03 +/* ACPI_ADR_DEVICE_PATH not defined */ + // // EISA ID Macro // EISA ID Definition 32-bits Index: stand/efi/loader/main.c =================================================================== --- stand/efi/loader/main.c +++ stand/efi/loader/main.c @@ -73,6 +73,7 @@ EFI_GUID inputid = SIMPLE_TEXT_INPUT_PROTOCOL; static bool uefi_boot_mgr; +static int com_speed = -1; /* * Number of seconds to wait for a keystroke before exiting with failure @@ -548,12 +549,65 @@ return (howto); } +/* + * Parse ConOut (the list of consoles active) and see if we can find a + * serial port and/or a video port. It would be nice to also walk the + * ACPI name space to map the UID for the serial port to a port. The + * latter is especially hard. + */ +static int +parse_uefi_con_out(void) +{ + int how, rv; + bool vid_seen = false, com_seen = false; + size_t sz; + char buf[4096], *ep; + EFI_DEVICE_PATH *node; + ACPI_HID_DEVICE_PATH *acpi; + UART_DEVICE_PATH *uart; + + how = 0; + sz = sizeof(buf); + rv = efi_global_getenv("ConOut", buf, &sz); + if (rv != EFI_SUCCESS) + goto out; + ep = buf + sz; + node = (EFI_DEVICE_PATH *)buf; + while ((char *)node < ep) { + if (DevicePathType(node) == ACPI_DEVICE_PATH && + DevicePathSubType(node) == ACPI_DP) { + /* Check for Serial node */ + acpi = (void *)node; + if (EISA_ID_TO_NUM(acpi->HID) == 0x501) + com_seen = true; + } else if (DevicePathType(node) == MESSAGING_DEVICE_PATH && + DevicePathSubType(node) == MSG_UART_DP) { + uart = (void *)node; + com_speed = uart->BaudRate; + /* not hw.uart.console -- depends on loader.conf */ + printf("Console speed is %d\n", com_speed); + } else if (DevicePathType(node) == ACPI_DEVICE_PATH && + DevicePathSubType(node) == ACPI_ADR_DP) { + /* Check for AcpiAdr() Node for video */ + vid_seen = true; + } + node = NextDevicePathNode(node); /* Skip the end node */ + } + if (vid_seen && com_seen) + how = RB_MULTIPLE | RB_SERIAL; + else if (com_seen) + how = RB_SERIAL; + else if (vid_seen) + how = RB_RESERVED1; +out: + return (how); +} EFI_STATUS main(int argc, CHAR16 *argv[]) { EFI_GUID *guid; - int howto, i; + int howto, i, uhowto; UINTN k; bool has_kbd, is_last; char *s; @@ -604,21 +658,37 @@ howto = parse_args(argc, argv, has_kbd); - bootenv_set(howto); + uhowto = parse_uefi_con_out(); - /* - * XXX we need fallback to this stuff after looking at the ConIn, ConOut and ConErr variables - */ - if (howto & RB_MULTIPLE) { - if (howto & RB_SERIAL) - setenv("console", "comconsole efi" , 1); - else - setenv("console", "efi comconsole" , 1); - } else if (howto & RB_SERIAL) { - setenv("console", "comconsole" , 1); - } else - setenv("console", "efi", 1); + printf("howto is %#x and uhowto is %#x\n", howto, uhowto); + if (uhowto == 0) { + /* + * Couldn't figure it out from the ConOut env var, so fall back to + * the command line stuff passed in. + */ + bootenv_set(howto); + /* + * If there's no ConOut, then we have to set things, though it's + * not clear how efi would work without it. + */ + if (howto & RB_MULTIPLE) { + if (howto & RB_SERIAL) + setenv("console", "comconsole efi" , 1); + else + setenv("console", "efi comconsole" , 1); + } else if (howto & RB_SERIAL) { + setenv("console", "comconsole" , 1); + } else + setenv("console", "efi", 1); + } else { + /* + * ConOut found something, so blend the command line args with what we found. + */ + uhowto &= ~RB_RESERVED1; + bootenv_set(uhowto | (howto & ~(RB_MULTIPLE | RB_SERIAL))); + setenv("console", "efi", 1); + } if (efi_copy_init()) { printf("failed to allocate staging area\n"); return (EFI_BUFFER_TOO_SMALL); @@ -740,7 +810,6 @@ return (EFI_NOT_FOUND); efi_init_environment(); - setenv("LINES", "24", 1); /* optional */ #if !defined(__arm__) for (k = 0; k < ST->NumberOfTableEntries; k++) {