Index: stand/i386/libi386/biosacpi.c =================================================================== --- stand/i386/libi386/biosacpi.c +++ stand/i386/libi386/biosacpi.c @@ -38,6 +38,7 @@ #define ACPI_SYSTEM_XFACE #include "actypes.h" #include "actbl.h" +#include "actbl3.h" /* * Detect ACPI and export information about the ACPI BIOS into the @@ -49,6 +50,94 @@ #define RSDP_CHECKSUM_LENGTH 20 +static ACPI_TABLE_SPCR * +find_spcr(ACPI_TABLE_RSDP *rsdp) +{ + unsigned count, i; + ACPI_TABLE_XSDT *xsdt; + ACPI_TABLE_RSDT *rsdt; + void *ptr; + + if (rsdp->Revision >= 2 && rsdp->XsdtPhysicalAddress != 0) { + xsdt = (ACPI_TABLE_XSDT *)PTOV(rsdp->XsdtPhysicalAddress); + + count = xsdt->Header.Length - sizeof(ACPI_TABLE_HEADER); + count /= sizeof(UINT64); + for (i = 0; i < count; i++) { + ptr = PTOV(xsdt->TableOffsetEntry[i]); + if (memcmp(ptr, ACPI_SIG_SPCR, + sizeof(ACPI_SIG_SPCR) - 1) == 0) { + return (ptr); + } + } + } + if (rsdp->RsdtPhysicalAddress != 0) { + + rsdt = (ACPI_TABLE_RSDT *)PTOV(rsdp->RsdtPhysicalAddress); + + count = rsdt->Header.Length - sizeof(ACPI_TABLE_HEADER); + count /= sizeof(UINT32); + for (i = 0; i < count; i++) { + ptr = PTOV(rsdt->TableOffsetEntry[i]); + if (memcmp(ptr, ACPI_SIG_SPCR, + sizeof(ACPI_SIG_SPCR) - 1) == 0) { + return (ptr); + } + } + } + return (NULL); +} + +/* + * Find and parse SPCR table to set up serial console. + */ +static void +biosacpi_setup_spcr(ACPI_TABLE_SPCR *spcr) +{ + unsigned baudrate; + char value[21]; + + if (spcr == NULL) + return; + + switch (spcr->BaudRate) { + case 0: + baudrate = 0; + break; + case 3: + baudrate = 9600; + break; + case 4: + baudrate = 19200; + break; + case 6: + baudrate = 57600; + break; + case 7: + baudrate = 115200; + break; + default: + return; + } + + switch (spcr->SerialPort.SpaceId) { + case ACPI_ADR_SPACE_SYSTEM_IO: + setenv("console", "comconsole", 1); + snprintf(value, sizeof(value), "%ju", + (uintmax_t)spcr->SerialPort.Address); + setenv("comconsole_port", value, 1); + break; + default: + /* XXX not implemented. */ + return; + } + + if (baudrate > 0) { + snprintf(value, sizeof(value), "%u", baudrate); + setenv("comconsole_speed", value, 1); + } +} + void biosacpi_detect(void) { @@ -95,6 +184,7 @@ setenv("hint.acpi.0.xsdt_length", buf, 1); setenv("acpi.xsdt_length", buf, 1); } + biosacpi_setup_spcr(find_spcr(rsdp)); } /* Index: stand/i386/loader/main.c =================================================================== --- stand/i386/loader/main.c +++ stand/i386/loader/main.c @@ -128,6 +128,12 @@ setheap(heap_bottom, heap_top); /* + * detect ACPI for future reference. This may set console to comconsole + * if we do have ACPI SPCR table. + */ + biosacpi_detect(); + + /* * XXX Chicken-and-egg problem; we want to have console output early, but some * console attributes may depend on reading from eg. the boot device, which we * can't do yet. @@ -232,9 +238,6 @@ initial_bootinfo->bi_basemem = bios_basemem / 1024; initial_bootinfo->bi_extmem = bios_extmem / 1024; } - - /* detect ACPI for future reference */ - biosacpi_detect(); /* detect SMBIOS for future reference */ smbios_detect(NULL);