Index: stand/i386/boot2/sio.S =================================================================== --- stand/i386/boot2/sio.S +++ stand/i386/boot2/sio.S @@ -15,9 +15,12 @@ * $FreeBSD$ */ - .set SIO_PRT,SIOPRT # Base port .set SIO_FMT,SIOFMT # 8N1 +/* int sio_port */ +sio_port: .long SIOPRT # Base port + + .globl sio_port .globl sio_init .globl sio_flush .globl sio_putc @@ -27,13 +30,15 @@ /* int sio_init(int div) */ sio_init: pushl %eax - movw $SIO_PRT+0x3,%dx # Data format reg + movl (sio_port),%edx + addl $0x3,%edx # Data format reg movb $SIO_FMT|0x80,%al # Set format outb %al,(%dx) # and DLAB subb $0x3,%dl # Divisor latch reg popl %eax outw %ax,(%dx) # BPS - movw $SIO_PRT+0x3,%dx # Data format reg + movl (sio_port),%edx + addl $0x3,%edx # Data format reg movb $SIO_FMT,%al # Clear outb %al,(%dx) # DLAB incl %edx # Modem control reg @@ -55,7 +60,8 @@ /* void sio_putc(int c) */ sio_putc: pushl %eax - movw $SIO_PRT+0x5,%dx # Line status reg + movl (sio_port),%edx + addl $0x5,%edx # Line status reg xor %ecx,%ecx # Timeout movb $0x40,%ch # counter sio_putc.1: inb (%dx),%al # Transmitter @@ -77,7 +83,8 @@ /* int sio_ischar(void) */ -sio_ischar: movw $SIO_PRT+0x5,%dx # Line status register +sio_ischar: movl (sio_port),%edx + addl $0x5,%edx # Line status register xorl %eax,%eax # Zero inb (%dx),%al # Received data andb $0x1,%al # ready? 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,93 @@ #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(xsdt->TableOffsetEntry[0]); + 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(rsdt->TableOffsetEntry[0]); + 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 +183,7 @@ setenv("hint.acpi.0.xsdt_length", buf, 1); setenv("acpi.xsdt_length", buf, 1); } + biosacpi_setup_spcr(find_spcr(rsdp)); } /* Index: stand/i386/zfsboot/zfsboot.c =================================================================== --- stand/i386/zfsboot/zfsboot.c +++ stand/i386/zfsboot/zfsboot.c @@ -106,6 +106,8 @@ static const unsigned char dev_maj[NDEV] = {30, 4, 2}; +extern int sio_port; + static struct i386_devdesc *bdev; static char cmd[512]; static char cmddup[512]; @@ -169,6 +171,7 @@ unsigned i; int auto_boot, fd, nextboot = 0; struct disk_devdesc devdesc; + char *ptr; bios_getmem(); @@ -182,6 +185,27 @@ } 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(); + ptr = getenv("console"); + if (ptr != NULL && strcmp(ptr, "comconsole") == 0) { + ioctrl = IO_SERIAL; + + ptr = getenv("comconsole_port"); + if (ptr != NULL) + sio_port = strtoul(ptr, NULL, 0); + + ptr = getenv("comconsole_speed"); + if (ptr != NULL) { + comspeed = strtoul(ptr, NULL, 0); + if (sio_init(115200 / comspeed) != 0) + ioctrl |= IO_KEYBOARD; + } + } + /* * Initialise the block cache. Set the upper limit. */