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 for Android: free password hash cracker in your pocket
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:   Thu, 11 Mar 2021 12:49:40 -0500
From:   Francois Gervais <fgervais@...tech-controls.com>
To:     linux-rtc@...r.kernel.org
Cc:     Alessandro Zummo <a.zummo@...ertech.it>,
        Alexandre Belloni <alexandre.belloni@...tlin.com>,
        Michael McCormick <michael.mccormick@...tel.net>,
        linux-kernel@...r.kernel.org,
        Francois Gervais <fgervais@...tech-controls.com>
Subject: [PATCH 1/1] rtc: pcf85063: add integrity check

Sometimes when the RTC battery is inserted, the voltage will bounce a
bit and we've seen that this can randomly flip configuration bits in
the RTC.

For example, we've seen COF bits flips and then the output clock
frequency would not be the expected one anymore.

To remediate this issue, this adds an optional feature where if the OS
bit it set on boot, it's possibly because the RTC lost power and again
possibly because a new battery has been inserted. In that case, it
reapplies defaults to configuration registers.

Signed-off-by: Francois Gervais <fgervais@...tech-controls.com>
---
 drivers/rtc/rtc-pcf85063.c | 54 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)

diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c
index 463991c74fdd..774cc4cf93d8 100644
--- a/drivers/rtc/rtc-pcf85063.c
+++ b/drivers/rtc/rtc-pcf85063.c
@@ -57,6 +57,10 @@
 #define PCF85063_REG_ALM_S		0x0b
 #define PCF85063_AEN			BIT(7)
 
+static bool integrity_check;
+module_param(integrity_check, bool, 0444);
+MODULE_PARM_DESC(integrity_check, "Set to one to enable the integrity check.");
+
 struct pcf85063_config {
 	struct regmap_config regmap;
 	unsigned has_alarms:1;
@@ -357,6 +361,49 @@ static int pcf85063_load_capacitance(struct pcf85063 *pcf85063,
 				  PCF85063_REG_CTRL1_CAP_SEL, reg);
 }
 
+static int pcf85063_check_integrity(struct pcf85063 *pcf85063)
+{
+	int err;
+	unsigned int val;
+
+	err = regmap_read(pcf85063->regmap, PCF85063_REG_SC, &val);
+	if (err < 0) {
+		dev_warn(&pcf85063->rtc->dev, "failed to read OS bit: %d",
+			 err);
+		return err;
+	}
+
+	if (!(val & PCF85063_REG_SC_OS)) {
+		dev_dbg(&pcf85063->rtc->dev, "integrity is ok\n");
+		return 0;
+	}
+
+	dev_dbg(&pcf85063->rtc->dev, "Power loss detected, restoring defaults\n");
+	err = regmap_update_bits(pcf85063->regmap, PCF85063_REG_CTRL1,
+				 (unsigned int)~PCF85063_REG_CTRL1_CAP_SEL, 0);
+	if (err < 0)
+		goto err_restore;
+
+	err = regmap_write(pcf85063->regmap, PCF85063_REG_CTRL2, 0);
+	if (err < 0)
+		goto err_restore;
+
+	err = regmap_write(pcf85063->regmap, PCF85063_REG_OFFSET, 0);
+	if (err < 0)
+		goto err_restore;
+
+	err = regmap_write(pcf85063->regmap, PCF85063_REG_RAM, 0);
+	if (err < 0)
+		goto err_restore;
+
+	return 0;
+
+
+err_restore:
+	dev_err(&pcf85063->rtc->dev, "failed to restore defaults: %d", err);
+	return err;
+}
+
 #ifdef CONFIG_COMMON_CLK
 /*
  * Handling of the clkout
@@ -558,6 +605,13 @@ static int pcf85063_probe(struct i2c_client *client)
 		dev_warn(&client->dev, "failed to set xtal load capacitance: %d",
 			 err);
 
+	if (integrity_check) {
+		err = pcf85063_check_integrity(pcf85063);
+		if (err < 0)
+			dev_warn(&client->dev, "failed to check integrity: %d",
+				 err);
+	}
+
 	pcf85063->rtc->ops = &pcf85063_rtc_ops;
 	pcf85063->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
 	pcf85063->rtc->range_max = RTC_TIMESTAMP_END_2099;
-- 
2.17.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ