lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250312123055.1735-2-messigoatcr7nop@gmail.com>
Date: Wed, 12 Mar 2025 18:00:22 +0530
From: Subu Dwevedi <messigoatcr7nop@...il.com>
To: 
Cc: Subu Dwevedi <messigoatcr7nop@...il.com>,
	Henrik Rydberg <rydberg@...math.org>,
	Jean Delvare <jdelvare@...e.com>,
	Guenter Roeck <linux@...ck-us.net>,
	linux-hwmon@...r.kernel.org,
	linux-kernel@...r.kernel.org
Subject: [PATCH 1/2] hwmon/applesmc: add MMIO for newer macs

Add basic MMIO support to AppleSMC for T2 Macs,
enabling it only when supported.
This replaces the legacy port-based method for
key reading, writing, and metadata operations
(retrieving keys by index and obtaining key information)

Signed-off-by: Subu Dwevedi <messigoatcr7nop@...il.com>
---
 drivers/hwmon/applesmc.c | 223 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 213 insertions(+), 10 deletions(-)

diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index fc6d6a9053ce..1be4a4026a6e 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -17,6 +17,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/acpi.h>
 #include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/input.h>
@@ -142,7 +143,9 @@ static struct platform_device *pdev;
 static s16 rest_x;
 static s16 rest_y;
 static u8 backlight_state[2];
-
+static u8 *__iomem mmio_base;
+static bool is_mmio;
+static u32 mmio_base_addr, mmio_base_size;
 static struct device *hwmon_dev;
 static struct input_dev *applesmc_idev;
 
@@ -245,7 +248,108 @@ static int send_argument(const char *key)
 	return 0;
 }
 
-static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len)
+/*
+ * MMIO Impliementation
+ */
+
+static void clearArbitration(void)
+{
+	if (ioread8(mmio_base + 0x4005))
+		return iowrite8(0, mmio_base + 0x4005);
+}
+static int waitForKeyDone(void)
+{
+	int i = 1000; //millisecounds
+	u8 status;
+
+	while (i) {
+		msleep(1);
+		i--;
+
+		status = ioread8(mmio_base + 0x4005);
+		if (status & 0x20)
+			return 0;
+	}
+
+	return -EIO;
+}
+static int mmio_read_smc(u8 cmd, const char *key, u8 *buffer, u64 len)
+{
+	u8 i, u = 0;
+
+	clearArbitration();
+	iowrite32(*((u32 *)key), mmio_base + 0x78);
+	iowrite8(0x15, mmio_base + 0x7E);
+	iowrite8(cmd, mmio_base + 0x7F);
+
+	if (waitForKeyDone())
+		return -EIO;
+
+	i = ioread8(mmio_base + 0x7F);
+	if (i)
+		return -EIO;
+	if (cmd == APPLESMC_READ_CMD) {
+		i = ioread8(mmio_base + 0x7D);
+		if (i > len || !i)
+			return -EIO;
+
+		while (u < i) {
+			if ((i - u) < 4) {
+				if ((i - u) < 2) {
+					buffer[u] = ioread8(mmio_base + u);
+					u += 1;
+				} else {
+					*(u16 *)&buffer[u] = ioread16(mmio_base + u);
+					u += 2;
+				}
+			} else {
+				*(u32 *)&buffer[u] = ioread32(mmio_base + u);
+				u += 4;
+			}
+		}
+	} else
+		memcpy_fromio(buffer, mmio_base + 0x0, len);
+
+	return 0;
+}
+static int mmio_write_smc(u8 cmd, const char *key, const u8 *buffer, u8 len)
+{
+	u8 i = 0;
+
+	clearArbitration();
+	iowrite32(*((u32 *)key), mmio_base + 0x78);
+	while (i < len) {
+		if (len - i < 4) {
+			if (len - i < 2) {
+				iowrite8(buffer[i], mmio_base + i);
+				i += 1;
+			} else {
+				iowrite16(*(u16 *)&buffer[i], mmio_base + i);
+				i += 2;
+			}
+		} else {
+			iowrite32(*(u32 *)&buffer[i], mmio_base + i);
+			i += 4;
+		}
+	}
+	iowrite8(len, mmio_base + 0x7D);
+	iowrite8(0x15, mmio_base + 0x7E);
+	iowrite8(cmd, mmio_base + 0x7F);
+	if (waitForKeyDone())
+		return -EIO;
+
+	i = ioread8(mmio_base + 0x7F);
+	if (i)
+		return -EIO;
+
+	return 0;
+}
+
+/*
+ * Port Based IO implementation
+ *
+ */
+static int port_read_smc(u8 cmd, const char *key, u8 *buffer, u8 len)
 {
 	u8 status, data = 0;
 	int i;
@@ -289,7 +393,7 @@ static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len)
 	return wait_status(0, SMC_STATUS_BUSY);
 }
 
-static int write_smc(u8 cmd, const char *key, const u8 *buffer, u8 len)
+static int port_write_smc(u8 cmd, const char *key, const u8 *buffer, u8 len)
 {
 	int i;
 	int ret;
@@ -317,7 +421,23 @@ static int write_smc(u8 cmd, const char *key, const u8 *buffer, u8 len)
 
 	return wait_status(0, SMC_STATUS_BUSY);
 }
+static int write_smc(u8 cmd, const char *key, const u8 *buffer,
+		u8 len)
+{
+	if (is_mmio)
+		return mmio_write_smc(cmd, key, buffer, len);
+
+	return port_write_smc(cmd, key, buffer, len);
+}
 
+static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len)
+{
+	if (is_mmio)
+		return mmio_read_smc(cmd, key, buffer, len);
+
+
+	return port_read_smc(cmd, key, buffer, len);
+}
 static int read_register_count(unsigned int *count)
 {
 	__be32 be;
@@ -379,18 +499,39 @@ static const struct applesmc_entry *applesmc_get_entry_by_index(int index)
 
 	if (cache->valid)
 		goto out;
+
 	be = cpu_to_be32(index);
-	ret = read_smc(APPLESMC_GET_KEY_BY_INDEX_CMD, (u8 *)&be, key, 4);
-	if (ret)
-		goto out;
-	ret = read_smc(APPLESMC_GET_KEY_TYPE_CMD, key, info, 6);
+	ret = read_smc(APPLESMC_GET_KEY_BY_INDEX_CMD, (const char *) &be, (u8 *) key, 4);
 	if (ret)
 		goto out;
 
+	if (is_mmio) {
+		clearArbitration();
+		iowrite32(*((u32 *)key), mmio_base + 0x78);
+		iowrite8(0, mmio_base + 0x7E);
+		iowrite8(APPLESMC_GET_KEY_TYPE_CMD, mmio_base + 0x7F);
+		ret = waitForKeyDone();
+		if (ret)
+			goto out;
+
+		ret = ioread8(mmio_base + 0x7F);
+		if (ret)
+			goto out;
+
+		*(u32 *)cache->type = ioread32(mmio_base + 0x7F);
+		cache->len = ioread8(mmio_base + 5);
+		cache->flags = ioread8(mmio_base + 6);
+
+	} else {
+		ret = read_smc(APPLESMC_GET_KEY_TYPE_CMD, key, info, 6);
+		if (ret)
+			goto out;
+
+		cache->len = info[0];
+		memcpy(cache->type, &info[1], 4);
+		cache->flags = info[5];
+	}
 	memcpy(cache->key, key, 4);
-	cache->len = info[0];
-	memcpy(cache->type, &info[1], 4);
-	cache->flags = info[5];
 	cache->valid = true;
 
 out:
@@ -558,7 +699,64 @@ static int applesmc_init_index(struct applesmc_registers *s)
 
 	return 0;
 }
+/*
+ * applesmc_init_mmio_try - Try to initialize MMIO
+ */
+static int applesmc_init_mmio_try(void)
+{
+	u8 ldkn_version;
+	acpi_status status;
+	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+	struct acpi_device *adev;
+	struct acpi_resource *res;
+
+	adev = acpi_dev_get_first_match_dev("APP0001", NULL, -1);
+	if (!adev)
+		return -ENXIO;
+
+	status = acpi_get_current_resources(adev->handle, &buffer);
+	if (ACPI_FAILURE(status))
+		return -ENXIO;
+
+	res = buffer.pointer;
+	while (res->type != ACPI_RESOURCE_TYPE_END_TAG) {
+		if (res->type == ACPI_RESOURCE_TYPE_FIXED_MEMORY32) {
+			if (res->data.fixed_memory32.address_length < 0x4006)
+				return -ENXIO;
+
+			mmio_base_addr = res->data.fixed_memory32.address;
+			mmio_base_size = res->data.fixed_memory32.address_length;
+			is_mmio = true;
+			break;
+		}
+		res = ACPI_NEXT_RESOURCE(res);
+	}
+	kfree(buffer.pointer);
+	acpi_dev_put(adev);
+
+	if (!is_mmio)
+		return -ENXIO;
+
+	mmio_base = ioremap(mmio_base_addr, mmio_base_size);
+
+	if (!mmio_base)
+		return -ENXIO;
 
+	if (ioread8(mmio_base + 0x4005) == 0xFF)
+		goto out;
+
+	if (read_smc(APPLESMC_READ_CMD, "LDKN", &ldkn_version, 1))
+		goto out;
+
+	if (ldkn_version < 2)
+		goto out;
+
+	return 0;
+out:
+	pr_warn("cannot enable MMIO will use PMIO\n");
+	iounmap(mmio_base);
+	return -ENXIO;
+}
 /*
  * applesmc_init_smcreg_try - Try to initialize register cache. Idempotent.
  */
@@ -1321,6 +1519,8 @@ static int __init applesmc_init(void)
 		ret = -ENXIO;
 		goto out;
 	}
+	if (applesmc_init_mmio_try())
+		is_mmio = false;
 
 	ret = platform_driver_register(&applesmc_driver);
 	if (ret)
@@ -1407,6 +1607,9 @@ static void __exit applesmc_exit(void)
 	applesmc_destroy_smcreg();
 	platform_device_unregister(pdev);
 	platform_driver_unregister(&applesmc_driver);
+	if (is_mmio)
+		iounmap(mmio_base);
+
 	release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS);
 }
 
-- 
2.43.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ