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: <20250110061401.358371-7-markus.burri@mt.com>
Date: Fri, 10 Jan 2025 07:14:00 +0100
From: Markus Burri <markus.burri@...com>
To: linux-kernel@...r.kernel.org
Cc: Markus Burri <markus.burri@...com>,
	Alexandre Belloni <alexandre.belloni@...tlin.com>,
	Rob Herring <robh@...nel.org>,
	Krzysztof Kozlowski <krzk+dt@...nel.org>,
	Conor Dooley <conor+dt@...nel.org>,
	Marek Vasut <marex@...x.de>,
	linux-rtc@...r.kernel.org,
	devicetree@...r.kernel.org,
	Manuel Traut <manuel.traut@...com>
Subject: [PATCH v1 6/7] rtc-rv8803: make tamper function configurable via sysfs

Make the following settings via sysfs configurable:
  - For the input pins: input resistor, trigger edge, de-jitter filter.
  - For the buffer: overwrite or inhibit mode for the FIFO.

Signed-off-by: Markus Burri <markus.burri@...com>

---
 drivers/rtc/rtc-rv8803.c | 262 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 262 insertions(+)

diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c
index c479cc7..cc8aa53 100644
--- a/drivers/rtc/rtc-rv8803.c
+++ b/drivers/rtc/rtc-rv8803.c
@@ -681,6 +681,31 @@ static int rv8803_nvram_read(void *priv, unsigned int offset,
 	return 0;
 }
 
+static int cfg2val(const struct cfg_val_txt *cfg, const char *text, u8 *value)
+{
+	if (!value)
+		return -EINVAL;
+
+	do {
+		if (strcasecmp(cfg->txt, text) == 0) {
+			*value = cfg->val;
+			return 0;
+		}
+	} while (++cfg && cfg->txt);
+
+	return -EINVAL;
+}
+
+static char *cfg2txt(const struct cfg_val_txt *cfg, u8 value)
+{
+	do {
+		if (cfg->val == value)
+			return cfg->txt;
+	} while (++cfg && cfg->txt);
+
+	return NULL;
+}
+
 static int rv8803_ts_event_write_evin(int evin, struct rv8803_data *rv8803, int pullup_down,
 				      int trigger, int filter)
 {
@@ -719,6 +744,31 @@ static int rv8803_ts_event_write_evin(int evin, struct rv8803_data *rv8803, int
 	return 0;
 }
 
+static int rv8803_ts_event_read_evin(int evin, struct rv8803_data *rv8803,
+				     int *pullup_down, int *trigger, int *filter)
+
+{
+	int ret;
+	struct i2c_client *client = rv8803->client;
+
+	/* get EVENTx pull-up edge trigger */
+	ret = rv8803_read_reg(client, evin_cfg_reg[evin]);
+	if (ret < 0)
+		return ret;
+
+	*pullup_down = FIELD_GET(RX8901_EVENTx_CFG_PUPD, ret);
+	*trigger = FIELD_GET(RX8901_EVENTx_CFG_POL, ret);
+
+	/* get EVENTx noise filter */
+	ret = rv8803_read_reg(client, evin_flt_reg[evin]);
+	if (ret < 0)
+		return ret;
+
+	*filter = ret;
+
+	return 0;
+}
+
 static ssize_t enable_store(struct device *dev, struct device_attribute *attr, const char *buf,
 			    size_t count)
 {
@@ -968,14 +1018,226 @@ static ssize_t trigger_store(struct device *dev, struct device_attribute *attr,
 	return count;
 }
 
+static ssize_t cfg_evin_available_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	int i;
+	int offset = 0;
+
+	offset += sprintf(buf + offset, "pull-resistor:\n");
+
+	for (i = 0; pull_resistor_txt[i].txt; ++i)
+		if (!pull_resistor_txt[i].hide)
+			offset += sprintf(buf + offset, "  %s\n", cfg2txt(pull_resistor_txt, i));
+	offset += sprintf(buf + offset, "\n");
+
+	offset += sprintf(buf + offset, "trigger:\n");
+	for (i = 0; trigger_txt[i].txt; ++i)
+		if (!trigger_txt[i].hide)
+			offset += sprintf(buf + offset, "  %s\n", cfg2txt(trigger_txt, i));
+	offset += sprintf(buf + offset, "\n");
+
+	offset += sprintf(buf + offset, "filter [ms]:\n");
+	for (i = 0; i <= EVIN_FILTER_MAX; ++i)
+		if (i != 1)
+			offset += sprintf(buf + offset, "  %d\n", EVIN_FILTER_FACTOR * i);
+
+	return offset;
+}
+
+static ssize_t cfg_evin_show(struct device *dev, int event, char *buf)
+{
+	int err;
+	struct rv8803_data *rv8803 = dev_get_drvdata(dev->parent);
+
+	int pullup_down;
+	int trigger;
+	int filter;
+
+	--event;
+	if (event >= NO_OF_EVIN)
+		return -ENOENT;
+
+	guard(mutex)(&rv8803->flags_lock);
+	err = rv8803_ts_event_read_evin(event, rv8803,
+					&pullup_down, &trigger, &filter);
+	if (err)
+		return err;
+
+	return sprintf(buf, "pull-resistor=%s, trigger=%s, filter=%dms\n",
+		       cfg2txt(pull_resistor_txt, pullup_down),
+		       cfg2txt(trigger_txt, trigger),
+		       EVIN_FILTER_FACTOR * filter);
+}
+
+static ssize_t cfg_evin1_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	return cfg_evin_show(dev, 1, buf);
+}
+
+static ssize_t cfg_evin2_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	return cfg_evin_show(dev, 2, buf);
+}
+
+static ssize_t cfg_evin3_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	return cfg_evin_show(dev, 3, buf);
+}
+
+static ssize_t cfg_evin_store(struct device *dev, int event, const char *buf, size_t count)
+{
+	int err;
+	struct rv8803_data *rv8803 = dev_get_drvdata(dev->parent);
+
+	char *buf_cpy;
+	char *token;
+	const char *startptr;
+	int pullup_down = -1;
+	int trigger = -1;
+	int filter = -1;
+	u8 v;
+
+	--event;
+	if (event >= NO_OF_EVIN)
+		return -ENOENT;
+
+	buf_cpy = kmalloc(count + 1, GFP_KERNEL);
+	if (!buf_cpy)
+		return -ENOMEM;
+
+	strscpy(buf_cpy, buf, count);
+	token = buf_cpy;
+	while ((startptr = strsep(&token, " ,\n"))) {
+		if (strstr(startptr, "pull-resistor=") == startptr)
+			if (cfg2val(pull_resistor_txt, strchr(startptr, '=') + 1, &v) == 0)
+				pullup_down = v;
+		if (strstr(startptr, "trigger=") == startptr)
+			if (cfg2val(trigger_txt, strchr(startptr, '=') + 1, &v) == 0)
+				trigger = v;
+		if (strstr(startptr, "filter=") == startptr)
+			filter = strtoul(strchr(startptr, '=') + 1, NULL, 0) / EVIN_FILTER_FACTOR;
+	}
+
+	kfree(buf_cpy);
+
+	guard(mutex)(&rv8803->flags_lock);
+	err = rv8803_ts_event_write_evin(event, rv8803, pullup_down, trigger, filter);
+	if (err)
+		return err;
+
+	return count;
+}
+
+static ssize_t cfg_evin1_store(struct device *dev, struct device_attribute *attr, const char *buf,
+			       size_t count)
+{
+	return cfg_evin_store(dev, 1, buf, count);
+}
+
+static ssize_t cfg_evin2_store(struct device *dev, struct device_attribute *attr, const char *buf,
+			       size_t count)
+{
+	return cfg_evin_store(dev, 2, buf, count);
+}
+
+static ssize_t cfg_evin3_store(struct device *dev, struct device_attribute *attr, const char *buf,
+			       size_t count)
+{
+	return cfg_evin_store(dev, 3, buf, count);
+}
+
+static ssize_t cfg_buf_available_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	int i;
+	int offset = 0;
+
+	offset += sprintf(buf + offset, "mode:\n");
+	for (i = 0; buffer_mode_txt[i].txt; ++i)
+		if (!buffer_mode_txt[i].hide)
+			offset += sprintf(buf + offset, "  %s\n", cfg2txt(buffer_mode_txt, i));
+
+	return offset;
+}
+
+static ssize_t cfg_buf_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	int ret;
+	struct i2c_client *client = to_i2c_client(dev->parent);
+	struct rv8803_data *rv8803 = dev_get_drvdata(dev->parent);
+
+	guard(mutex)(&rv8803->flags_lock);
+
+	ret = rv8803_read_reg(client, RX8901_BUF1_CFG1);
+	if (ret < 0)
+		return ret;
+
+	return sprintf(buf, "mode:%s\n",
+		       cfg2txt(buffer_mode_txt, FIELD_GET(BIT(6), ret)));
+}
+
+static ssize_t cfg_buf_store(struct device *dev, struct device_attribute *attr, const char *buf,
+			     size_t count)
+{
+	int ret;
+	char *buf_cpy;
+	char *token;
+	char *startptr;
+	int mode = -1;
+	u8 v;
+
+	struct i2c_client *client = to_i2c_client(dev->parent);
+	struct rv8803_data *rv8803 = dev_get_drvdata(dev->parent);
+
+	buf_cpy = kmalloc(count + 1, GFP_KERNEL);
+	if (!buf_cpy)
+		return -ENOMEM;
+
+	strscpy(buf_cpy, buf, count);
+	token = buf_cpy;
+	while ((startptr = strsep(&token, " ,\n"))) {
+		if (strstr(startptr, "mode:") == startptr)
+			if (cfg2val(buffer_mode_txt, strchr(startptr, ':') + 1, &v) == 0)
+				mode = v;
+	}
+
+	kfree(buf_cpy);
+
+	if (mode != -1) {
+		guard(mutex)(&rv8803->flags_lock);
+
+		ret = rv8803_read_reg(client, RX8901_BUF1_CFG1);
+		if (ret < 0)
+			return ret;
+
+		ret &= ~BIT(6);
+		ret |= FIELD_PREP(BIT(6), mode);
+		ret = rv8803_write_reg(client, RX8901_BUF1_CFG1, ret);
+		if (ret < 0)
+			return ret;
+	}
+	return count;
+}
+
 static DEVICE_ATTR_WO(enable);
 static DEVICE_ATTR_RO(read);
 static DEVICE_ATTR_WO(trigger);
+static DEVICE_ATTR_RO(cfg_evin_available);
+static DEVICE_ATTR_RO(cfg_buf_available);
+static DEVICE_ATTR_RW(cfg_evin1);
+static DEVICE_ATTR_RW(cfg_evin2);
+static DEVICE_ATTR_RW(cfg_evin3);
+static DEVICE_ATTR_RW(cfg_buf);
 
 static struct attribute *rv8803_rtc_event_attrs[] = {
 	&dev_attr_enable.attr,
 	&dev_attr_read.attr,
 	&dev_attr_trigger.attr,
+	&dev_attr_cfg_evin_available.attr,
+	&dev_attr_cfg_buf_available.attr,
+	&dev_attr_cfg_evin1.attr,
+	&dev_attr_cfg_evin2.attr,
+	&dev_attr_cfg_evin3.attr,
+	&dev_attr_cfg_buf.attr,
 	NULL
 };
 
-- 
2.39.5


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ