summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorToomas Soome <tsoome@me.com>2019-03-01 15:46:11 +0200
committerToomas Soome <tsoome@me.com>2019-03-21 17:43:45 +0200
commita2f10c447c8cfe20ac08f6c287fe67307f2a5175 (patch)
tree4706cc1eab73ca7fabb7d5e275faeb91c0273490
parentc83793e8beca1f638b19f9fba9570ee705f7a494 (diff)
downloadillumos-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.version2
-rw-r--r--usr/src/boot/sys/boot/efi/loader/comconsole.c94
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);