git: 455fa56ad4fe - stable/14 - LinuxKPI: Add acpi_dev_present() function.

From: Vladimir Kondratyev <wulf_at_FreeBSD.org>
Date: Sat, 17 Feb 2024 21:33:17 UTC
The branch stable/14 has been updated by wulf:

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

commit 455fa56ad4fecadeb8bf099c883d64d7a6bf9988
Author:     Vladimir Kondratyev <wulf@FreeBSD.org>
AuthorDate: 2023-12-24 08:20:00 +0000
Commit:     Vladimir Kondratyev <wulf@FreeBSD.org>
CommitDate: 2024-02-17 20:58:39 +0000

    LinuxKPI: Add acpi_dev_present() function.
    
    acpi_dev_present detects that a given ACPI device is present based on
    Hardware ID, Unique ID and Hardware Revision of the device.
    
    Sponsored by:   Serenity Cyber Security, LLC
    Reviewed by:    manu
    MFC after:      1 week
    Differential Revision:  https://reviews.freebsd.org/D42823
    
    (cherry picked from commit 04952a9456e226460d1d95c42ea53861b1133b1a)
---
 sys/compat/linuxkpi/common/include/acpi/acpi_bus.h |  4 ++
 sys/compat/linuxkpi/common/src/linux_acpi.c        | 79 ++++++++++++++++++++++
 2 files changed, 83 insertions(+)

diff --git a/sys/compat/linuxkpi/common/include/acpi/acpi_bus.h b/sys/compat/linuxkpi/common/include/acpi/acpi_bus.h
index 3db8e7df58f4..f107902a26ad 100644
--- a/sys/compat/linuxkpi/common/include/acpi/acpi_bus.h
+++ b/sys/compat/linuxkpi/common/include/acpi/acpi_bus.h
@@ -37,6 +37,8 @@ struct acpi_bus_event {
 	uint32_t data;
 };
 
+#define	acpi_dev_present(...)	lkpi_acpi_dev_present(__VA_ARGS__)
+
 ACPI_HANDLE	bsd_acpi_get_handle(device_t bsddev);
 bool		acpi_check_dsm(ACPI_HANDLE handle, const char *uuid, int rev,
 		    uint64_t funcs);
@@ -46,5 +48,7 @@ ACPI_OBJECT *	acpi_evaluate_dsm_typed(ACPI_HANDLE handle, const char *uuid,
 int		register_acpi_notifier(struct notifier_block *nb);
 int		unregister_acpi_notifier(struct notifier_block *nb);
 uint32_t	acpi_target_system_state(void);
+bool		lkpi_acpi_dev_present(const char *hid, const char *uid,
+		    int64_t hrv);
 
 #endif /* _LINUXKPI_ACPI_ACPI_BUS_H_ */
diff --git a/sys/compat/linuxkpi/common/src/linux_acpi.c b/sys/compat/linuxkpi/common/src/linux_acpi.c
index 6e342c8e2caa..e7b6854ecf13 100644
--- a/sys/compat/linuxkpi/common/src/linux_acpi.c
+++ b/sys/compat/linuxkpi/common/src/linux_acpi.c
@@ -174,6 +174,79 @@ acpi_target_system_state(void)
 	return (linux_acpi_target_sleep_state);
 }
 
+struct acpi_dev_present_ctx {
+	const char *hid;
+	const char *uid;
+	int64_t hrv;
+};
+
+static ACPI_STATUS
+acpi_dev_present_cb(ACPI_HANDLE handle, UINT32 level, void *context,
+    void **result)
+{
+	ACPI_DEVICE_INFO *devinfo;
+	struct acpi_dev_present_ctx *match = context;
+	bool present = false;
+	UINT32 sta, hrv;
+	int i;
+
+	if (handle == NULL)
+		return (AE_OK);
+
+	if (!ACPI_FAILURE(acpi_GetInteger(handle, "_STA", &sta)) &&
+	    !ACPI_DEVICE_PRESENT(sta))
+		return (AE_OK);
+
+	if (ACPI_FAILURE(AcpiGetObjectInfo(handle, &devinfo)))
+		return (AE_OK);
+
+	if ((devinfo->Valid & ACPI_VALID_HID) != 0 &&
+	    strcmp(match->hid, devinfo->HardwareId.String) == 0) {
+		present = true;
+	} else if ((devinfo->Valid & ACPI_VALID_CID) != 0) {
+		for (i = 0; i < devinfo->CompatibleIdList.Count; i++) {
+			if (strcmp(match->hid,
+			    devinfo->CompatibleIdList.Ids[i].String) == 0) {
+				present = true;
+				break;
+			}
+		}
+	}
+	if (present && match->uid != NULL &&
+	    ((devinfo->Valid & ACPI_VALID_UID) == 0 ||
+	      strcmp(match->uid, devinfo->UniqueId.String) != 0))
+		present = false;
+
+	AcpiOsFree(devinfo);
+	if (!present)
+		return (AE_OK);
+
+	if (match->hrv != -1) {
+		if (ACPI_FAILURE(acpi_GetInteger(handle, "_HRV", &hrv)))
+			return (AE_OK);
+		if (hrv != match->hrv)
+			return (AE_OK);
+	}
+
+	return (AE_ERROR);
+}
+
+bool
+lkpi_acpi_dev_present(const char *hid, const char *uid, int64_t hrv)
+{
+	struct acpi_dev_present_ctx match;
+	int rv;
+
+	match.hid = hid;
+	match.uid = uid;
+	match.hrv = hrv;
+
+	rv = AcpiWalkNamespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+	    ACPI_UINT32_MAX, acpi_dev_present_cb, NULL, &match, NULL);
+
+	return (rv == AE_ERROR);
+}
+
 static void
 linux_register_acpi_event_handlers(void *arg __unused)
 {
@@ -241,4 +314,10 @@ acpi_target_system_state(void)
 	return (ACPI_STATE_S0);
 }
 
+bool
+lkpi_acpi_dev_present(const char *hid, const char *uid, int64_t hrv)
+{
+	return (false);
+}
+
 #endif	/* !DEV_ACPI */