Subject: [PATCH] nvmem: ocotp: add support to revoke keys
From: Denis Osterland-Heim <[email-masked]>
To: [email-masked]
Date: Thu, 11 Mar 2021 18:04:03 +0100

From: Denis Osterland-Heim <[email-masked]>

Add device tree property 'barebox,key-revoke' with the syntax:
< key_phandle fuse_offset mask >

An example:
	signature {
		key1: key-img1 { ... };
		key2: key-srk1 { ... };
	};
};
&ocotp {
	barebox,key-revoke = <
		&key1 0x660 1
		&key2 0x6f0 1
	>;
};

Signed-off-by: Denis Osterland-Heim <[email-masked]>
---
 .../bindings/misc/fsl,imx-ocotp.rst           |  4 ++
 drivers/nvmem/ocotp.c                         | 37 ++++++++++++++++++-
 2 files changed, 39 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/misc/fsl,imx-ocotp.rst b/Documentation/devicetree/bindings/misc/fsl,imx-ocotp.rst
index 202bb3aa0..63a6f5331 100644
--- a/Documentation/devicetree/bindings/misc/fsl,imx-ocotp.rst
+++ b/Documentation/devicetree/bindings/misc/fsl,imx-ocotp.rst
@@ -12,6 +12,9 @@ Optional properties:
   can be multiple entries in the form <&phandle regofs> to assign a MAC
   address to an Ethernet device.
 
+* ``barebox,key-revoke``: Revoke (remove) key if bit is set. This can be multiple
+  entries in the form <&phandle regofs mask> to revoke a key if bit is set.
+
 Example:
 
 .. code-block:: none
@@ -20,4 +23,5 @@ Example:
   	compatible = "fsl,imx6q-ocotp";
   	reg = <0x021bc000 0x4000>;
   	barebox,provide-mac-address = <&fec 0x620>;
+  	barebox,key-revoke = <&/signature/key-img1 0x6f0 1>;
   };
diff --git a/drivers/nvmem/ocotp.c b/drivers/nvmem/ocotp.c
index cee50955e..00ee6cd06 100644
--- a/drivers/nvmem/ocotp.c
+++ b/drivers/nvmem/ocotp.c
@@ -641,7 +641,7 @@ static struct regmap_bus imx_ocotp_regmap_bus = {
 	.reg_read = imx_ocotp_reg_read,
 };
 
-static void imx_ocotp_init_dt(struct ocotp_priv *priv)
+static void imx_ocotp_init_mac_dt(struct ocotp_priv *priv)
 {
 	char mac[MAC_BYTES];
 	const __be32 *prop;
@@ -673,6 +673,38 @@ static void imx_ocotp_init_dt(struct ocotp_priv *priv)
 	}
 }
 
+static void imx_ocotp_init_key_dt(struct ocotp_priv *priv)
+{
+	const __be32 *prop;
+	struct device_node *node = priv->dev.parent->device_node;
+	int len;
+
+	if (!node)
+		return;
+
+	prop = of_get_property(node, "barebox,key-revoke", &len);
+	if (!prop)
+		return;
+
+	for (; len >= 3; len -= 3) {
+		struct device_node *rnode;
+		uint32_t phandle, offset, mask;
+		unsigned val;
+
+		phandle = be32_to_cpup(prop++);
+
+		rnode = of_find_node_by_phandle(phandle);
+		offset = be32_to_cpup(prop++);
+		mask = be32_to_cpup(prop++);
+
+		if (imx6_ocotp_read_one_u32(priv, OCOTP_OFFSET_TO_INDEX(offset), &val))
+			continue;
+
+		if (val & mask)
+			of_delete_node(rnode);
+	}
+}
+
 static int imx_ocotp_write(struct device_d *dev, const int offset,
 			    const void *val, int bytes)
 {
@@ -790,7 +822,8 @@ static int imx_ocotp_probe(struct device_d *dev)
 	if (IS_ENABLED(CONFIG_MACHINE_ID))
 		imx_ocotp_set_unique_machine_id();
 
-	imx_ocotp_init_dt(priv);
+	imx_ocotp_init_mac_dt(priv);
+	imx_ocotp_init_key_dt(priv);
 
 	dev_add_param_bool(&(priv->dev), "sense_enable", NULL, NULL, &priv->sense_enable, priv);
 
-- 
2.30.2