All of lore.kernel.org
 help / color / mirror / Atom feed
From: Patrick Delaunay <patrick.delaunay@st.com>
To: u-boot@lists.denx.de
Subject: [PATCH 04/10] arm: stm32mp: bsec: add permanent lock support in bsec driver
Date: Wed, 12 Feb 2020 19:37:38 +0100	[thread overview]
Message-ID: <20200212183744.5309-5-patrick.delaunay@st.com> (raw)
In-Reply-To: <20200212183744.5309-1-patrick.delaunay@st.com>

Add BSEC lock access (read / write) at 0xC0000000 offset of misc driver.
The write access only available for Trusted boot mode, based on new
SMC STM32_SMC_WRLOCK_OTP.

With the fuse command, the permanent lock status is accessed with
0x10000000 offset (0xC0000000 - 0x8000000 for OTP sense/program
divided by u32 size), for example:

Read lock status of fuse 57 (0x39)

  STM32MP> fuse sense 0 0x10000039 1

  Sensing bank 0:

  Word 0x10000039: 00000000

Set permanent lock of fuse 57 (0x39)

  STM32MP> fuse prog 0 0x10000039 1

  Sensing bank 0:

  Word 0x10000039: 00000000

WARNING: the OTP lock is updated only after reboot

WARING: Programming lock or fuses is an irreversible operation!
        This may brick your system.

Signed-off-by: Patrick Delaunay <patrick.delaunay@st.com>
---

 arch/arm/mach-stm32mp/bsec.c                  | 88 +++++++++++++------
 arch/arm/mach-stm32mp/cpu.c                   |  6 --
 arch/arm/mach-stm32mp/include/mach/stm32.h    |  9 +-
 .../mach-stm32mp/include/mach/stm32mp1_smc.h  |  1 +
 doc/board/st/stm32mp1.rst                     | 34 ++++---
 5 files changed, 95 insertions(+), 43 deletions(-)

diff --git a/arch/arm/mach-stm32mp/bsec.c b/arch/arm/mach-stm32mp/bsec.c
index 1d904caae1..3b923f088e 100644
--- a/arch/arm/mach-stm32mp/bsec.c
+++ b/arch/arm/mach-stm32mp/bsec.c
@@ -12,8 +12,6 @@
 #include <linux/iopoll.h>
 
 #define BSEC_OTP_MAX_VALUE		95
-
-#ifndef CONFIG_STM32MP1_TRUSTED
 #define BSEC_TIMEOUT_US			10000
 
 /* BSEC REGISTER OFFSET (base relative) */
@@ -24,9 +22,10 @@
 #define BSEC_OTP_LOCK_OFF		0x010
 #define BSEC_DISTURBED_OFF		0x01C
 #define BSEC_ERROR_OFF			0x034
-#define BSEC_SPLOCK_OFF			0x064 /* Program safmem sticky lock */
-#define BSEC_SWLOCK_OFF			0x07C /* write in OTP sticky lock */
-#define BSEC_SRLOCK_OFF			0x094 /* shadowing sticky lock */
+#define BSEC_WRLOCK_OFF			0x04C /* OTP write permananet lock */
+#define BSEC_SPLOCK_OFF			0x064 /* OTP write sticky lock */
+#define BSEC_SWLOCK_OFF			0x07C /* shadow write sticky lock */
+#define BSEC_SRLOCK_OFF			0x094 /* shadow read sticky lock */
 #define BSEC_OTP_DATA_OFF		0x200
 
 /* BSEC_CONFIGURATION Register MASK */
@@ -53,12 +52,12 @@
 #define BSEC_LOCK_PROGRAM		0x04
 
 /**
- * bsec_check_error() - Check status of one otp
- * @base: base address of bsec IP
+ * bsec_lock() - manage lock for each type SR/SP/SW
+ * @address: address of bsec IP register
  * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
- * Return: 0 if no error, -EAGAIN or -ENOTSUPP
+ * Return: true if locked else false
  */
-static u32 bsec_check_error(u32 base, u32 otp)
+static bool bsec_read_lock(u32 address, u32 otp)
 {
 	u32 bit;
 	u32 bank;
@@ -66,21 +65,17 @@ static u32 bsec_check_error(u32 base, u32 otp)
 	bit = 1 << (otp & OTP_LOCK_MASK);
 	bank = ((otp >> OTP_LOCK_BANK_SHIFT) & OTP_LOCK_MASK) * sizeof(u32);
 
-	if (readl(base + BSEC_DISTURBED_OFF + bank) & bit)
-		return -EAGAIN;
-	else if (readl(base + BSEC_ERROR_OFF + bank) & bit)
-		return -ENOTSUPP;
-
-	return 0;
+	return !!(readl(address + bank) & bit);
 }
 
+#ifndef CONFIG_STM32MP1_TRUSTED
 /**
- * bsec_lock() - manage lock for each type SR/SP/SW
- * @address: address of bsec IP register
+ * bsec_check_error() - Check status of one otp
+ * @base: base address of bsec IP
  * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
- * Return: true if locked else false
+ * Return: 0 if no error, -EAGAIN or -ENOTSUPP
  */
-static bool bsec_read_lock(u32 address, u32 otp)
+static u32 bsec_check_error(u32 base, u32 otp)
 {
 	u32 bit;
 	u32 bank;
@@ -88,7 +83,12 @@ static bool bsec_read_lock(u32 address, u32 otp)
 	bit = 1 << (otp & OTP_LOCK_MASK);
 	bank = ((otp >> OTP_LOCK_BANK_SHIFT) & OTP_LOCK_MASK) * sizeof(u32);
 
-	return !!(readl(address + bank) & bit);
+	if (readl(base + BSEC_DISTURBED_OFF + bank) & bit)
+		return -EAGAIN;
+	else if (readl(base + BSEC_ERROR_OFF + bank) & bit)
+		return -ENOTSUPP;
+
+	return 0;
 }
 
 /**
@@ -324,6 +324,16 @@ static int stm32mp_bsec_read_shadow(struct udevice *dev, u32 *val, u32 otp)
 #endif
 }
 
+static int stm32mp_bsec_read_lock(struct udevice *dev, u32 *val, u32 otp)
+{
+	struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
+
+	/* return OTP permanent write lock status */
+	*val = bsec_read_lock(plat->base + BSEC_WRLOCK_OFF, otp);
+
+	return 0;
+}
+
 static int stm32mp_bsec_write_otp(struct udevice *dev, u32 val, u32 otp)
 {
 #ifdef CONFIG_STM32MP1_TRUSTED
@@ -350,17 +360,36 @@ static int stm32mp_bsec_write_shadow(struct udevice *dev, u32 val, u32 otp)
 #endif
 }
 
+static int stm32mp_bsec_write_lock(struct udevice *dev, u32 val, u32 otp)
+{
+#ifdef CONFIG_STM32MP1_TRUSTED
+	if (val == 1)
+		return stm32_smc_exec(STM32_SMC_BSEC,
+				      STM32_SMC_WRLOCK_OTP,
+				      otp, 0);
+	if (val == 0)
+		return 0; /* nothing to do */
+
+	return -EINVAL;
+#else
+	return -ENOTSUPP;
+#endif
+}
+
 static int stm32mp_bsec_read(struct udevice *dev, int offset,
 			     void *buf, int size)
 {
 	int ret;
 	int i;
-	bool shadow = true;
+	bool shadow = true, lock = false;
 	int nb_otp = size / sizeof(u32);
 	int otp;
 	unsigned int offs = offset;
 
-	if (offs >= STM32_BSEC_OTP_OFFSET) {
+	if (offs >= STM32_BSEC_LOCK_OFFSET) {
+		offs -= STM32_BSEC_LOCK_OFFSET;
+		lock = true;
+	} else if (offs >= STM32_BSEC_OTP_OFFSET) {
 		offs -= STM32_BSEC_OTP_OFFSET;
 		shadow = false;
 	}
@@ -373,7 +402,9 @@ static int stm32mp_bsec_read(struct udevice *dev, int offset,
 	for (i = otp; i < (otp + nb_otp) && i <= BSEC_OTP_MAX_VALUE; i++) {
 		u32 *addr = &((u32 *)buf)[i - otp];
 
-		if (shadow)
+		if (lock)
+			ret = stm32mp_bsec_read_lock(dev, addr, i);
+		else if (shadow)
 			ret = stm32mp_bsec_read_shadow(dev, addr, i);
 		else
 			ret = stm32mp_bsec_read_otp(dev, addr, i);
@@ -392,12 +423,15 @@ static int stm32mp_bsec_write(struct udevice *dev, int offset,
 {
 	int ret = 0;
 	int i;
-	bool shadow = true;
+	bool shadow = true, lock = false;
 	int nb_otp = size / sizeof(u32);
 	int otp;
 	unsigned int offs = offset;
 
-	if (offs >= STM32_BSEC_OTP_OFFSET) {
+	if (offs >= STM32_BSEC_LOCK_OFFSET) {
+		offs -= STM32_BSEC_LOCK_OFFSET;
+		lock = true;
+	} else if (offs >= STM32_BSEC_OTP_OFFSET) {
 		offs -= STM32_BSEC_OTP_OFFSET;
 		shadow = false;
 	}
@@ -410,7 +444,9 @@ static int stm32mp_bsec_write(struct udevice *dev, int offset,
 	for (i = otp; i < otp + nb_otp && i <= BSEC_OTP_MAX_VALUE; i++) {
 		u32 *val = &((u32 *)buf)[i - otp];
 
-		if (shadow)
+		if (lock)
+			ret = stm32mp_bsec_write_lock(dev, *val, i);
+		else if (shadow)
 			ret = stm32mp_bsec_write_shadow(dev, *val, i);
 		else
 			ret = stm32mp_bsec_write_otp(dev, *val, i);
diff --git a/arch/arm/mach-stm32mp/cpu.c b/arch/arm/mach-stm32mp/cpu.c
index ea0bd94605..5febed735c 100644
--- a/arch/arm/mach-stm32mp/cpu.c
+++ b/arch/arm/mach-stm32mp/cpu.c
@@ -61,12 +61,6 @@
 #define BOOTROM_INSTANCE_MASK	 GENMASK(31, 16)
 #define BOOTROM_INSTANCE_SHIFT	16
 
-/* BSEC OTP index */
-#define BSEC_OTP_RPN	1
-#define BSEC_OTP_SERIAL	13
-#define BSEC_OTP_PKG	16
-#define BSEC_OTP_MAC	57
-
 /* Device Part Number (RPN) = OTP_DATA1 lower 8 bits */
 #define RPN_SHIFT	0
 #define RPN_MASK	GENMASK(7, 0)
diff --git a/arch/arm/mach-stm32mp/include/mach/stm32.h b/arch/arm/mach-stm32mp/include/mach/stm32.h
index f0636005e5..6daf9f7121 100644
--- a/arch/arm/mach-stm32mp/include/mach/stm32.h
+++ b/arch/arm/mach-stm32mp/include/mach/stm32.h
@@ -119,7 +119,14 @@ enum forced_boot_mode {
 #define STM32_BSEC_SHADOW(id)		(STM32_BSEC_SHADOW_OFFSET + (id) * 4)
 #define STM32_BSEC_OTP_OFFSET		0x80000000
 #define STM32_BSEC_OTP(id)		(STM32_BSEC_OTP_OFFSET + (id) * 4)
-
+#define STM32_BSEC_LOCK_OFFSET		0xC0000000
+#define STM32_BSEC_LOCK(id)		(STM32_BSEC_LOCK_OFFSET + (id) * 4)
+
+/* BSEC OTP index */
+#define BSEC_OTP_RPN	1
+#define BSEC_OTP_SERIAL	13
+#define BSEC_OTP_PKG	16
+#define BSEC_OTP_MAC	57
 #define BSEC_OTP_BOARD	59
 
 #endif /* __ASSEMBLY__*/
diff --git a/arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h b/arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h
index 8130546b27..7b9167c356 100644
--- a/arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h
+++ b/arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h
@@ -27,6 +27,7 @@
 #define STM32_SMC_READ_OTP		0x04
 #define STM32_SMC_READ_ALL		0x05
 #define STM32_SMC_WRITE_ALL		0x06
+#define STM32_SMC_WRLOCK_OTP		0x07
 
 /* SMC error codes */
 #define STM32_SMC_OK			0x0
diff --git a/doc/board/st/stm32mp1.rst b/doc/board/st/stm32mp1.rst
index 131f4902a3..274f8d9710 100644
--- a/doc/board/st/stm32mp1.rst
+++ b/doc/board/st/stm32mp1.rst
@@ -402,20 +402,26 @@ For STMicroelectonics board, it is retrieved in STM32MP15x OTP :
  - OTP_58[15:0] = MAC_ADDR[47:32]
 
 To program a MAC address on virgin OTP words above, you can use the fuse command
-on bank 0 to access to internal OTP:
+on bank 0 to access to internal OTP and lock them:
 
 Prerequisite: check if a MAC address isn't yet programmed in OTP
 
-1) check OTP: their value must be equal to 0
+1) check OTP: their value must be equal to 0::
 
-   STM32MP> fuse sense 0 57 2
-   Sensing bank 0:
-   Word 0x00000039: 00000000 00000000
+    STM32MP> fuse sense 0 57 2
+    Sensing bank 0:
+    Word 0x00000039: 00000000 00000000
+
+2) check environment variable::
+
+    STM32MP> env print ethaddr
+    ## Error: "ethaddr" not defined
 
-2) check environment variable
+3) check lock status of fuse 57 & 58 (at 0x39, 0=unlocked, 1=locked)::
 
-   STM32MP> env print ethaddr
-   ## Error: "ethaddr" not defined
+    STM32MP> fuse sense 0 0x10000039 2
+    Sensing bank 0:
+       Word 0x10000039: 00000000 00000000
 
 Example to set mac address "12:34:56:78:9a:bc"
 
@@ -429,11 +435,19 @@ Example to set mac address "12:34:56:78:9a:bc"
     Sensing bank 0:
     Word 0x00000039: 78563412 0000bc9a
 
-3) next REBOOT, in the trace::
+3) Lock OTP::
+
+    STM32MP> fuse prog 0 0x10000039 1 1
+
+    STM32MP> fuse sense 0 0x10000039 2
+    Sensing bank 0:
+       Word 0x10000039: 00000001 00000001
+
+4) next REBOOT, in the trace::
 
     ### Setting environment from OTP MAC address = "12:34:56:78:9a:bc"
 
-4) check env update::
+5) check env update::
 
     STM32MP> env print ethaddr
     ethaddr=12:34:56:78:9a:bc
-- 
2.17.1

  parent reply	other threads:[~2020-02-12 18:37 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-02-12 18:37 [PATCH 00/10] stm32mp1: board and SOC identifications Patrick Delaunay
2020-02-12 18:37 ` [PATCH 01/10] board: stm32mp1: update command stboard on misc_write result Patrick Delaunay
2020-03-18 10:04   ` [Uboot-stm32] " Patrice CHOTARD
2020-03-24  8:32   ` Patrick DELAUNAY
2020-02-12 18:37 ` [PATCH 02/10] board: stm32mp1: read OTP in command stboard Patrick Delaunay
2020-03-18 10:05   ` [Uboot-stm32] " Patrice CHOTARD
2020-03-24  8:33   ` Patrick DELAUNAY
2020-02-12 18:37 ` [PATCH 03/10] arm: stm32mp: bsec: remove unneeded test Patrick Delaunay
2020-03-18 10:04   ` Patrice CHOTARD
2020-04-24 14:24     ` Patrick DELAUNAY
2020-03-24  8:34   ` Patrick DELAUNAY
2020-02-12 18:37 ` Patrick Delaunay [this message]
2020-03-18 10:07   ` [PATCH 04/10] arm: stm32mp: bsec: add permanent lock support in bsec driver Patrice CHOTARD
2020-03-24  8:35   ` Patrick DELAUNAY
2020-02-12 18:37 ` [PATCH 05/10] board: stm32mp1: stboard: lock the OTP after programming Patrick Delaunay
2020-03-18 10:10   ` [Uboot-stm32] " Patrice CHOTARD
2020-03-24  8:36   ` Patrick DELAUNAY
2020-02-12 18:37 ` [PATCH 06/10] arm: stm32mp: improve the error message for smc Patrick Delaunay
2020-03-18 10:10   ` Patrice CHOTARD
2020-03-24  8:36   ` Patrick DELAUNAY
2020-02-12 18:37 ` [PATCH 07/10] board: stm32mp1: add finished good in board identifier OTP Patrick Delaunay
2020-03-18 10:13   ` [Uboot-stm32] " Patrice CHOTARD
2020-03-18 10:44   ` Wolfgang Denk
2020-03-19  8:57     ` Patrick DELAUNAY
2020-03-19  9:13       ` Wolfgang Denk
2020-03-23  8:59         ` Patrick DELAUNAY
2020-02-12 18:37 ` [PATCH 08/10] board: stm32mp1: display reference only for STMicroelectronics board Patrick Delaunay
2020-03-18 10:15   ` [Uboot-stm32] " Patrice CHOTARD
2020-03-24  8:37   ` Patrick DELAUNAY
2020-02-12 18:37 ` [PATCH 09/10] arm: stm32mp: add function get_soc_name Patrick Delaunay
2020-03-18 10:16   ` Patrice CHOTARD
2020-03-24  8:37   ` Patrick DELAUNAY
2020-02-12 18:37 ` [PATCH 10/10] arm: stm32mp: fdt: update kernel device tree according the part number Patrick Delaunay
2020-03-18 10:16   ` Patrice CHOTARD
2020-03-24  8:37   ` Patrick DELAUNAY

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200212183744.5309-5-patrick.delaunay@st.com \
    --to=patrick.delaunay@st.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.