diff --git sys/dev/acpica/acpi.c sys/dev/acpica/acpi.c index 941e2bd75aeb..4fed26316547 100644 --- sys/dev/acpica/acpi.c +++ sys/dev/acpica/acpi.c @@ -1923,6 +1923,35 @@ acpi_find_dsd(struct acpi_device *ad) return (AE_NOT_FOUND); } +static ssize_t +acpi_bus_get_prop_phandle(const ACPI_OBJECT *hobj, void *propvalue, size_t size) +{ + ACPI_OBJECT *pobj; + ACPI_HANDLE h; + + if (hobj->Type != ACPI_TYPE_PACKAGE) + goto err; + if (hobj->Package.Count != 1) + goto err; + + pobj = &hobj->Package.Elements[0]; + if (pobj == NULL) + goto err; + if (pobj->Type != ACPI_TYPE_LOCAL_REFERENCE) + goto err; + + h = acpi_GetReference(NULL, pobj); + if (h == NULL) + goto err; + + if (propvalue != NULL && size >= sizeof(ACPI_HANDLE)) + memcpy(propvalue, h, sizeof(ACPI_HANDLE)); + return (sizeof(ACPI_HANDLE)); + +err: + return (-1); +} + static ssize_t acpi_bus_get_prop(device_t bus, device_t child, const char *propname, void *propvalue, size_t size, device_property_type_t type) @@ -1941,6 +1970,8 @@ acpi_bus_get_prop(device_t bus, device_t child, const char *propname, case DEVICE_PROP_UINT32: case DEVICE_PROP_UINT64: break; + case DEVICE_PROP_HANDLE: + return (acpi_bus_get_prop_phandle(obj, propvalue, size)); default: return (-1); } @@ -1972,6 +2003,22 @@ acpi_bus_get_prop(device_t bus, device_t child, const char *propname, MIN(size, obj->Buffer.Length)); return (obj->Buffer.Length); + case ACPI_TYPE_PACKAGE: + if (propvalue != NULL && size >= sizeof(ACPI_OBJECT *)) { + *((ACPI_OBJECT **) propvalue) = + __DECONST(ACPI_OBJECT *, obj); + } + return (sizeof(ACPI_OBJECT *)); + + case ACPI_TYPE_LOCAL_REFERENCE: + if (propvalue != NULL && size >= sizeof(ACPI_HANDLE)) { + ACPI_HANDLE h; + + h = acpi_GetReference(NULL, + __DECONST(ACPI_OBJECT *, obj)); + memcpy(propvalue, h, sizeof(ACPI_HANDLE)); + } + return (sizeof(ACPI_HANDLE)); default: return (0); } diff --git sys/dev/fdt/simplebus.c sys/dev/fdt/simplebus.c index ed472f87b57d..d7c4b416813b 100644 --- sys/dev/fdt/simplebus.c +++ sys/dev/fdt/simplebus.c @@ -357,7 +357,7 @@ static ssize_t simplebus_get_property(device_t bus, device_t child, const char *propname, void *propvalue, size_t size, device_property_type_t type) { - phandle_t node = ofw_bus_get_node(child); + phandle_t node, xref; ssize_t ret, i; uint32_t *buffer; uint64_t val; @@ -367,11 +367,13 @@ simplebus_get_property(device_t bus, device_t child, const char *propname, case DEVICE_PROP_BUFFER: case DEVICE_PROP_UINT32: case DEVICE_PROP_UINT64: + case DEVICE_PROP_HANDLE: break; default: return (-1); } + node = ofw_bus_get_node(child); if (propvalue == NULL || size == 0) return (OF_getproplen(node, propname)); @@ -402,7 +404,20 @@ simplebus_get_property(device_t bus, device_t child, const char *propname, ((uint64_t *)buffer)[i / 2] = val; } return (ret); - } + } + + if (type == DEVICE_PROP_HANDLE) { + if (size < sizeof(node)) + return (-1); + ret = OF_getencprop(node, propname, &xref, sizeof(xref)); + if (ret <= 0) + return (ret); + + node = OF_node_from_xref(xref); + if (propvalue != NULL) + *(uint32_t *)propvalue = node; + return (ret); + } return (OF_getprop(node, propname, propvalue, size)); } diff --git sys/kern/subr_bus.c sys/kern/subr_bus.c index 041e77259313..adf87b564d12 100644 --- sys/kern/subr_bus.c +++ sys/kern/subr_bus.c @@ -2226,6 +2233,7 @@ device_get_property(device_t dev, const char *prop, void *val, size_t sz, switch (type) { case DEVICE_PROP_ANY: case DEVICE_PROP_BUFFER: + case DEVICE_PROP_HANDLE: /* Size checks done in implementation. */ break; case DEVICE_PROP_UINT32: if (sz % 4 != 0) diff --git sys/sys/bus.h sys/sys/bus.h index c363d1ec550e..b5a65a9f8f9e 100644 --- sys/sys/bus.h +++ sys/sys/bus.h @@ -72,6 +72,7 @@ typedef enum device_property_type { DEVICE_PROP_BUFFER = 1, DEVICE_PROP_UINT32 = 2, DEVICE_PROP_UINT64 = 3, + DEVICE_PROP_HANDLE = 4, } device_property_type_t; /** diff --git share/man/man9/device_get_property.9 share/man/man9/device_get_property.9 index d925f5f224db..620f4f11dceb 100644 --- share/man/man9/device_get_property.9 +++ share/man/man9/device_get_property.9 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd February 18, 2022 +.Dd September 28, 2022 .Dt DEVICE_GET_PROPERTY 9 .Os .Sh NAME @@ -49,11 +49,14 @@ The underlying property type is specified with the .Fa type argument. Currently the following types are supported: .Bl -tag -width ".Dv DEVICE_PROP_BUFFER" .It Dv DEVICE_PROP_BUFFER The underlying property is a string of bytes. .It Dv DEVICE_PROP_ANY Wildcard property type. +.It Dv DEVICE_PROP_HANDLE +Following a reference the underlying property is a handle of the +respective bus. .It Dv DEVICE_PROP_UINT32 The underlying property is an array of unsigned 32 bit integers. The