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>] [day] [month] [year] [list]
Message-ID: <20181219065828.GD2843@lambda.inversepath.com>
Date:   Wed, 19 Dec 2018 07:58:28 +0100
From:   Andrea Barisani <andrea@...ersepath.com>
To:     Srinivas Kandagatla <srinivas.kandagatla@...aro.org>,
        <linux-kernel@...r.kernel.org>
CC:     Philipp Zabel <p.zabel@...gutronix.de>
Subject: [PATCH v4.14 1/1]: nvmem: imx-ocotp: account for addressing gaps to
 ensure consistent read/write on i.MX SoCs


The nvmem-imx-ocotp driver does not currently handle addressing gaps between
OTP banks which can be present in i.MX System-on-Chip part numbers.

This leads to inconsistencies between the interpretation of the offset
argument in read and write operations, not only requiring specific
workarounds but also resulting in the impossibility of reading the entire OTP
bank.

Additionally this inconsistency violates the NVMEM subsystem principle of
exposing a userspace binary interface for read/write operations against a
pseudo-file.

This patch accounts for addressing gaps, depending on the specific i.MX model
being addressed.

Signed-off-by: Andrea Barisani <andrea@...ersepath.com>

---
 drivers/nvmem/imx-ocotp.c |   49 ++++++++++++++++++++++++++++++------
 1 file changed, 41 insertions(+), 8 deletions(-)

--- linux-4.14.89/drivers/nvmem/imx-ocotp.c.orig	2018-12-18 10:30:49.363322853 +0100
+++ linux-4.14.89/drivers/nvmem/imx-ocotp.c	2018-12-18 10:31:18.143778980 +0100
@@ -114,6 +114,8 @@ static int imx_ocotp_read(void *context,
 {
 	struct ocotp_priv *priv = context;
 	unsigned int count;
+	unsigned int base_offset;
+	const char *compat;
 	u32 *buf = val;
 	int i, ret;
 	u32 index;
@@ -139,11 +141,42 @@ static int imx_ocotp_read(void *context,
 		goto read_end;
 	}
 
+	compat = of_get_property(priv->dev->of_node, "compatible", NULL);
+
 	for (i = index; i < (index + count); i++) {
-		*buf++ = readl(priv->base + IMX_OCOTP_OFFSET_B0W0 +
-			       i * IMX_OCOTP_OFFSET_PER_WORD);
+		/*
+		 * On specific i.MX P/Ns there are addressing gaps between
+		 * contiguous OTP banks which must be accounted for when
+		 * reading OTP banks from mapped memory.
+		 *
+		 * This is necessary to make the imx_ocotp_read() offset
+		 * interpretation consistent with imx_ocotp_write(), which
+		 * does not require to account for gaps as it uses the offset
+		 * value to derive the bank index and pass it directly to the
+		 * OCOTP controller (rather than being used for mapped memory
+		 * addressing).
+		 */
+		base_offset = IMX_OCOTP_OFFSET_B0W0 + i * IMX_OCOTP_OFFSET_PER_WORD;
+
+		if (strcmp(compat, "fsl,imx6sx-ocotp")) {
+			/* 44.5.43 [IMX6SXRM]
+			 * 256 bytes gap between Bank5 Word7 (21B_C6F0h, offset 0x6f0) and
+			 * Bank10 Word1 (21B_CA10h, offset 0xa10)
+			 */
+			if (base_offset > 0x6f0)
+				base_offset += 0x100;
+		} else if (strcmp(compat, "fsl,imx6ul-ocotp")) {
+			/* 35.5.59 [IMX6ULRM]
+			 * 256 bytes gap between Bank5 Word7 (21B_C6F0h, offset 0x6f0) and
+			 * Bank6 Word0 (21B_C800h, offset 0x800)
+			 */
+			if (base_offset > 0x6f0)
+				base_offset += 0x100;
+		}
+
+		*buf++ = readl(priv->base + base_offset);
 
-		/* 47.3.1.2
+		/* 47.3.1.2 [IMX6SDLRM]
 		 * For "read locked" registers 0xBADABADA will be returned and
 		 * HW_OCOTP_CTRL[ERROR] will be set. It must be cleared by
 		 * software before any new write, read or reload access can be
@@ -205,7 +238,7 @@ static int imx_ocotp_write(void *context
 
 	writel(timing, priv->base + IMX_OCOTP_ADDR_TIMING);
 
-	/* 47.3.1.3.2
+	/* 47.3.1.3.2 [IMX6SDLRM]
 	 * Check that HW_OCOTP_CTRL[BUSY] and HW_OCOTP_CTRL[ERROR] are clear.
 	 * Overlapped accesses are not supported by the controller. Any pending
 	 * write or reload must be completed before a write access can be
@@ -217,7 +250,7 @@ static int imx_ocotp_write(void *context
 		goto write_end;
 	}
 
-	/* 47.3.1.3.3
+	/* 47.3.1.3.3 [IMX6SDLRM]
 	 * Write the requested address to HW_OCOTP_CTRL[ADDR] and program the
 	 * unlock code into HW_OCOTP_CTRL[WR_UNLOCK]. This must be programmed
 	 * for each write access. The lock code is documented in the register
@@ -234,7 +267,7 @@ static int imx_ocotp_write(void *context
 
 	writel(ctrl, priv->base + IMX_OCOTP_ADDR_CTRL);
 
-	/* 47.3.1.3.4
+	/* 47.3.1.3.4 [IMX6SDLRM]
 	 * Write the data to the HW_OCOTP_DATA register. This will automatically
 	 * set HW_OCOTP_CTRL[BUSY] and clear HW_OCOTP_CTRL[WR_UNLOCK]. To
 	 * protect programming same OTP bit twice, before program OCOTP will
@@ -254,7 +287,7 @@ static int imx_ocotp_write(void *context
 	 */
 	writel(*buf, priv->base + IMX_OCOTP_ADDR_DATA);
 
-	/* 47.4.1.4.5
+	/* 47.4.1.4.5 [IMX6SDLRM]
 	 * Once complete, the controller will clear BUSY. A write request to a
 	 * protected or locked region will result in no OTP access and no
 	 * setting of HW_OCOTP_CTRL[BUSY]. In addition HW_OCOTP_CTRL[ERROR] will
@@ -272,7 +305,7 @@ static int imx_ocotp_write(void *context
 		goto write_end;
 	}
 
-	/* 47.3.1.4
+	/* 47.3.1.4 [IMX6SDLRM]
 	 * Write Postamble: Due to internal electrical characteristics of the
 	 * OTP during writes, all OTP operations following a write must be
 	 * separated by 2 us after the clearing of HW_OCOTP_CTRL_BUSY following

-- 
Andrea Barisani     Head of Hardware Security |     F-Secure
                                      Founder | Inverse Path

https://www.f-secure.com             https://inversepath.com
0x864C9B9E 0A76 074A 02CD E989 CE7F AC3F DA47 578E 864C 9B9E
       "Pluralitas non est ponenda sine necessitate"

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ