git: b3e602d9ac5e - stable/13 - device_get_property: add a HANDLE case

From: Bjoern A. Zeeb <bz_at_FreeBSD.org>
Date: Wed, 18 Jan 2023 16:24:35 UTC
The branch stable/13 has been updated by bz:

URL: https://cgit.FreeBSD.org/src/commit/?id=b3e602d9ac5e3157874dfe3986dc819971d2142c

commit b3e602d9ac5e3157874dfe3986dc819971d2142c
Author:     Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2022-09-29 12:41:58 +0000
Commit:     Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2023-01-18 13:22:13 +0000

    device_get_property: add a HANDLE case
    
    This will resolve a reference and return the appropriate handle, a node
    on the simplebus or an ACPI_HANDLE for ACPI.  For now we do not try to
    further abstract the return type.
    
    Reviewed by:    mw
    Differential Revision: https://reviews.freebsd.org/D36793
    
    (cherry picked from commit 99e6980fcf5e12654c3e89b97b774de807d740a4)
---
 share/man/man9/device_get_property.9 |  5 +++-
 sys/dev/acpica/acpi.c                | 47 ++++++++++++++++++++++++++++++++++++
 sys/dev/fdt/simplebus.c              | 19 +++++++++++++--
 sys/kern/subr_bus.c                  |  1 +
 sys/sys/bus.h                        |  1 +
 5 files changed, 70 insertions(+), 3 deletions(-)

diff --git a/share/man/man9/device_get_property.9 b/share/man/man9/device_get_property.9
index d925f5f224db..93c01f199477 100644
--- a/share/man/man9/device_get_property.9
+++ b/share/man/man9/device_get_property.9
@@ -25,7 +25,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd February 18, 2022
+.Dd September 29, 2022
 .Dt DEVICE_GET_PROPERTY 9
 .Os
 .Sh NAME
@@ -54,6 +54,9 @@ Currently the following types are supported:
 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
diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
index 9005448ddee9..8f4419a76c58 100644
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -1824,6 +1824,35 @@ acpi_find_dsd(struct acpi_device *ad)
 	return (AE_NOT_FOUND);
 }
 
+static ssize_t
+acpi_bus_get_prop_handle(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))
+		*(ACPI_HANDLE *)propvalue = h;
+	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)
@@ -1842,6 +1871,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_handle(obj, propvalue, size));
 	default:
 		return (-1);
 	}
@@ -1873,6 +1904,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 a/sys/dev/fdt/simplebus.c b/sys/dev/fdt/simplebus.c
index ab7868f245bf..a29b28f2a016 100644
--- a/sys/dev/fdt/simplebus.c
+++ b/sys/dev/fdt/simplebus.c
@@ -359,7 +359,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;
@@ -369,11 +369,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));
 
@@ -404,7 +406,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 a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c
index c70e0e7b5ec1..c1383add7e47 100644
--- a/sys/kern/subr_bus.c
+++ b/sys/kern/subr_bus.c
@@ -2683,6 +2683,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 a/sys/sys/bus.h b/sys/sys/bus.h
index c017f38dcf11..a308810f158f 100644
--- a/sys/sys/bus.h
+++ b/sys/sys/bus.h
@@ -73,6 +73,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;
 
 /**