diff options
| author | Toomas Soome <tsoome@me.com> | 2019-03-01 15:46:11 +0200 |
|---|---|---|
| committer | Toomas Soome <tsoome@me.com> | 2019-03-21 17:43:45 +0200 |
| commit | a2f10c447c8cfe20ac08f6c287fe67307f2a5175 (patch) | |
| tree | 4706cc1eab73ca7fabb7d5e275faeb91c0273490 | |
| parent | c83793e8beca1f638b19f9fba9570ee705f7a494 (diff) | |
| download | illumos-joyent-a2f10c447c8cfe20ac08f6c287fe67307f2a5175.tar.gz | |
10481 loader.efi: comconsole needs to identify the port handle better
Reviewed by: John Levon <john.levon@joyent.com>
Reviewed by: Andy Fiddaman <andy@omniosce.org>
Reviewed by: Gergő Doma <domag02@gmail.com>
Approved by: Dan McDonald <danmcd@joyent.com>
| -rw-r--r-- | usr/src/boot/Makefile.version | 2 | ||||
| -rw-r--r-- | usr/src/boot/sys/boot/efi/loader/comconsole.c | 94 |
2 files changed, 79 insertions, 17 deletions
diff --git a/usr/src/boot/Makefile.version b/usr/src/boot/Makefile.version index 646545a76c..205b3d6065 100644 --- a/usr/src/boot/Makefile.version +++ b/usr/src/boot/Makefile.version @@ -33,4 +33,4 @@ LOADER_VERSION = 1.1 # Use date like formatting here, YYYY.MM.DD.XX, without leading zeroes. # The version is processed from left to right, the version number can only # be increased. -BOOT_VERSION = $(LOADER_VERSION)-2019.03.07.1 +BOOT_VERSION = $(LOADER_VERSION)-2019.03.07.2 diff --git a/usr/src/boot/sys/boot/efi/loader/comconsole.c b/usr/src/boot/sys/boot/efi/loader/comconsole.c index 6f3eed7aa1..2399d37760 100644 --- a/usr/src/boot/sys/boot/efi/loader/comconsole.c +++ b/usr/src/boot/sys/boot/efi/loader/comconsole.c @@ -43,6 +43,8 @@ static EFI_GUID serial = SERIAL_IO_PROTOCOL; #define COMSPEED 9600 #endif +#define PNP0501 0x501 /* 16550A-compatible COM port */ + struct serial { uint64_t baudrate; uint8_t databits; @@ -119,7 +121,7 @@ struct console ttyd = { .c_private = NULL }; -EFI_STATUS +static EFI_STATUS efi_serial_init(EFI_HANDLE **handlep, int *nhandles) { UINTN bufsz = 0; @@ -138,7 +140,7 @@ efi_serial_init(EFI_HANDLE **handlep, int *nhandles) if ((handles = malloc(bufsz)) == NULL) return (ENOMEM); - *nhandles = (int)(bufsz/sizeof (EFI_HANDLE)); + *nhandles = (int)(bufsz / sizeof (EFI_HANDLE)); /* * get handle array */ @@ -151,28 +153,91 @@ efi_serial_init(EFI_HANDLE **handlep, int *nhandles) return (status); } +/* + * Find serial device number from device path. + * Return -1 if not found. + */ +static int +efi_serial_get_index(EFI_DEVICE_PATH *devpath) +{ + ACPI_HID_DEVICE_PATH *acpi; + + while (!IsDevicePathEnd(devpath)) { + if (DevicePathType(devpath) == ACPI_DEVICE_PATH && + DevicePathSubType(devpath) == ACPI_DP) { + + acpi = (ACPI_HID_DEVICE_PATH *)devpath; + if (acpi->HID == EISA_PNP_ID(PNP0501)) { + return (acpi->UID); + } + } + + devpath = NextDevicePathNode(devpath); + } + return (-1); +} + +/* + * The order of handles from LocateHandle() is not known, we need to + * iterate handles, pick device path for handle, and check the device + * number. + */ +static EFI_HANDLE +efi_serial_get_handle(int port) +{ + EFI_STATUS status; + EFI_HANDLE *handles, handle; + EFI_DEVICE_PATH *devpath; + int index, nhandles; + + if (port == -1) + return (NULL); + + handles = NULL; + nhandles = 0; + status = efi_serial_init(&handles, &nhandles); + if (EFI_ERROR(status)) + return (NULL); + + handle = NULL; + for (index = 0; index < nhandles; index++) { + devpath = efi_lookup_devpath(handles[index]); + if (port == efi_serial_get_index(devpath)) { + handle = (handles[index]); + break; + } + } + + /* + * In case we did fail to identify the device by path, use port as + * array index. Note, we did check port == -1 above. + */ + if (port < nhandles && handle == NULL) + handle = handles[port]; + + free(handles); + return (handle); +} + static void comc_probe(struct console *cp) { EFI_STATUS status; + EFI_HANDLE handle; struct serial *port; char name[20]; char value[20]; char *env; - EFI_HANDLE *handles = NULL; /* array of handles */ - int nhandles = 0; /* number of handles in array */ /* are we already set up? */ if (cp->c_private != NULL) return; - /* make sure the handles are available */ - status = efi_serial_init(&handles, &nhandles); - cp->c_private = malloc(sizeof (struct serial)); port = cp->c_private; port->baudrate = COMSPEED; + port->ioaddr = -1; /* invalid port */ if (strcmp(cp->c_name, "ttya") == 0) port->ioaddr = 0; else if (strcmp(cp->c_name, "ttyb") == 0) @@ -182,9 +247,6 @@ comc_probe(struct console *cp) else if (strcmp(cp->c_name, "ttyd") == 0) port->ioaddr = 3; - if (port->ioaddr >= nhandles) - port->ioaddr = -1; /* invalid port */ - port->databits = 8; /* 8,n,1 */ port->parity = NoParity; /* 8,n,1 */ port->stopbits = OneStopBit; /* 8,n,1 */ @@ -192,16 +254,16 @@ comc_probe(struct console *cp) port->rtsdtr_off = 0; /* rts-dtr is on */ port->sio = NULL; - if (port->ioaddr != -1) { - status = BS->OpenProtocol(handles[port->ioaddr], - &serial, (void**)&port->sio, IH, NULL, + handle = efi_serial_get_handle(port->ioaddr); + + if (handle != NULL) { + status = BS->OpenProtocol(handle, &serial, + (void**)&port->sio, IH, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); if (EFI_ERROR(status)) - port->ioaddr = -1; /* invalid port */ + port->sio = NULL; } - if (handles != NULL) - free(handles); snprintf(name, sizeof (name), "%s-mode", cp->c_name); env = getenv(name); |
