diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c --- a/sys/dev/acpica/acpi.c +++ b/sys/dev/acpica/acpi.c @@ -958,6 +958,52 @@ if (strcmp(locator, BUS_LOCATOR_ACPI) == 0) return (acpi_get_acpi_device_path(bus, child, locator, sb)); + if (strcmp(locator, BUS_LOCATOR_UEFI) == 0) { + ACPI_DEVICE_INFO *adinfo; + if (!ACPI_FAILURE(AcpiGetObjectInfo(dinfo->ad_handle, &adinfo)) && + dinfo->ad_handle != 0 && (adinfo->Valid & ACPI_VALID_HID)) { + const char *hid = adinfo->HardwareId.String; + u_long uid = (adinfo->Valid & ACPI_VALID_UID) ? + strtoul(adinfo->UniqueId.String, NULL, 10) : 0UL; + u_long hidval; + + /* + * In UEFI Stanard Version 2.6, Section 9.6.1.6 Text + * Device Node Reference, there's an insanely long table + * 98. This implements the relevant bits from that + * table. Newer versions appear to have not required + * anything new. The EDK2 firmware presents both PciRoot + * and PcieRoot as PciRoot. Follow the EDK2 standard. + */ + if (strncmp("PNP", hid, 3) != 0) + goto nomatch; + hidval = strtoul(hid + 3, NULL, 16); + switch (hidval) { + case 0x0301: + sbuf_printf(sb, "Keyboard(0x%lx)", uid); + break; + case 0x0401: + sbuf_printf(sb, "ParallelPort(0x%lx)", uid); + break; + case 0x0501: + sbuf_printf(sb, "Serial(0x%lx)", uid); + break; + case 0x0604: + sbuf_printf(sb, "Floppy(0x%lx)", uid); + break; + case 0x0a03: + case 0x0a08: + sbuf_printf(sb, "PciRoot(0x%lx)", uid); + break; + default: /* Everything else gets a generic encode */ + nomatch: + sbuf_printf(sb, "Acpi(%s,0x%lx)", hid, uid); + break; + } + } + /* Not handled: AcpiAdr... unsure how to know it's one */ + } + /* For the rest, punt to the default handler */ return (bus_generic_get_device_path(bus, child, locator, sb)); } diff --git a/sys/dev/acpica/acpi_pci.c b/sys/dev/acpica/acpi_pci.c --- a/sys/dev/acpica/acpi_pci.c +++ b/sys/dev/acpica/acpi_pci.c @@ -206,8 +206,8 @@ if (strcmp(locator, BUS_LOCATOR_ACPI) == 0) return (acpi_get_acpi_device_path(bus, child, locator, sb)); - /* For the rest, punt to the default handler */ - return (bus_generic_get_device_path(bus, child, locator, sb)); + /* Otherwise follow base class' actions */ + return (pci_get_device_path_method(bus, child, locator, sb)); } /* diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -138,7 +138,6 @@ static int pci_get_id_method(device_t dev, device_t child, enum pci_id_type type, uintptr_t *rid); - static struct pci_devinfo * pci_fill_devinfo(device_t pcib, device_t bus, int d, int b, int s, int f, uint16_t vid, uint16_t did); @@ -177,6 +176,7 @@ DEVMETHOD(bus_child_detached, pci_child_detached), DEVMETHOD(bus_child_pnpinfo, pci_child_pnpinfo_method), DEVMETHOD(bus_child_location, pci_child_location_method), + DEVMETHOD(bus_get_device_path, pci_get_device_path_method), DEVMETHOD(bus_hint_device_unit, pci_hint_device_unit), DEVMETHOD(bus_remap_intr, pci_remap_intr_method), DEVMETHOD(bus_suspend_child, pci_suspend_child), @@ -5917,6 +5917,24 @@ return (0); } +int +pci_get_device_path_method(device_t bus, device_t child, const char *locator, + struct sbuf *sb) +{ + device_t parent = device_get_parent(bus); + int rv; + + if (strcmp(locator, BUS_LOCATOR_UEFI) == 0) { + rv = bus_generic_get_device_path(parent, bus, locator, sb); + if (rv == 0) { + sbuf_printf(sb, "/Pci(0x%x,0x%x)", pci_get_slot(child), + pci_get_function(child)); + } + return (0); + } + return (bus_generic_get_device_path(bus, child, locator, sb)); +} + int pci_assign_interrupt_method(device_t dev, device_t child) { diff --git a/sys/dev/pci/pci_private.h b/sys/dev/pci/pci_private.h --- a/sys/dev/pci/pci_private.h +++ b/sys/dev/pci/pci_private.h @@ -138,6 +138,8 @@ struct sbuf *sb); int pci_child_pnpinfo_method(device_t cbdev, device_t child, struct sbuf *sb); +int pci_get_device_path_method(device_t dev, device_t child, + const char *locator, struct sbuf *sb); int pci_assign_interrupt_method(device_t dev, device_t child); int pci_resume(device_t dev); int pci_resume_child(device_t dev, device_t child); diff --git a/sys/sys/bus.h b/sys/sys/bus.h --- a/sys/sys/bus.h +++ b/sys/sys/bus.h @@ -739,6 +739,7 @@ #define BUS_LOCATOR_ACPI "ACPI" #define BUS_LOCATOR_FREEBSD "FreeBSD" +#define BUS_LOCATOR_UEFI "UEFI" extern int bus_current_pass;