summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-stm32mp/bsec.c173
-rw-r--r--arch/arm/mach-stm32mp/cmd_stm32key.c4
-rw-r--r--arch/arm/mach-stm32mp/include/mach/bsec.h7
-rw-r--r--board/st/common/cmd_stboard.c5
-rw-r--r--doc/board/st/stm32mp1.rst6
5 files changed, 183 insertions, 12 deletions
diff --git a/arch/arm/mach-stm32mp/bsec.c b/arch/arm/mach-stm32mp/bsec.c
index 51ccff9aa5..fe79c986f9 100644
--- a/arch/arm/mach-stm32mp/bsec.c
+++ b/arch/arm/mach-stm32mp/bsec.c
@@ -10,9 +10,11 @@
#include <dm.h>
#include <log.h>
#include <misc.h>
+#include <tee.h>
#include <asm/io.h>
#include <asm/arch/bsec.h>
#include <asm/arch/stm32mp1_smc.h>
+#include <dm/device.h>
#include <dm/device_compat.h>
#include <linux/arm-smccc.h>
#include <linux/iopoll.h>
@@ -63,10 +65,43 @@
*/
#define BSEC_LOCK_PROGRAM 0x04
+#define PTA_BSEC_UUID { 0x94cf71ad, 0x80e6, 0x40b5, \
+ { 0xa7, 0xc6, 0x3d, 0xc5, 0x01, 0xeb, 0x28, 0x03 } }
+
+/*
+ * Read OTP memory
+ *
+ * [in] value[0].a OTP start offset in byte
+ * [in] value[0].b Access type (0:shadow, 1:fuse, 2:lock)
+ * [out] memref[1].buffer Output buffer to store read values
+ * [out] memref[1].size Size of OTP to be read
+ *
+ * Return codes:
+ * TEE_SUCCESS - Invoke command success
+ * TEE_ERROR_BAD_PARAMETERS - Incorrect input param
+ * TEE_ERROR_ACCESS_DENIED - OTP not accessible by caller
+ */
+#define PTA_BSEC_READ_MEM 0x0
+
/*
- * OTP status: bit 0 permanent lock
+ * Write OTP memory
+ *
+ * [in] value[0].a OTP start offset in byte
+ * [in] value[0].b Access type (0:shadow, 1:fuse, 2:lock)
+ * [in] memref[1].buffer Input buffer to read values
+ * [in] memref[1].size Size of OTP to be written
+ *
+ * Return codes:
+ * TEE_SUCCESS - Invoke command success
+ * TEE_ERROR_BAD_PARAMETERS - Incorrect input param
+ * TEE_ERROR_ACCESS_DENIED - OTP not accessible by caller
*/
-#define BSEC_LOCK_PERM BIT(0)
+#define PTA_BSEC_WRITE_MEM 0x1
+
+/* value of PTA_BSEC access type = value[in] b */
+#define SHADOW_ACCESS 0
+#define FUSE_ACCESS 1
+#define LOCK_ACCESS 2
/**
* bsec_lock() - manage lock for each type SR/SP/SW
@@ -359,6 +394,10 @@ struct stm32mp_bsec_plat {
u32 base;
};
+struct stm32mp_bsec_priv {
+ struct udevice *tee;
+};
+
static int stm32mp_bsec_read_otp(struct udevice *dev, u32 *val, u32 otp)
{
struct stm32mp_bsec_plat *plat;
@@ -470,14 +509,109 @@ static int stm32mp_bsec_write_lock(struct udevice *dev, u32 val, u32 otp)
return bsec_permanent_lock_otp(dev, plat->base, otp);
}
+static int bsec_pta_open_session(struct udevice *tee, u32 *tee_session)
+{
+ const struct tee_optee_ta_uuid uuid = PTA_BSEC_UUID;
+ struct tee_open_session_arg arg;
+ int rc;
+
+ memset(&arg, 0, sizeof(arg));
+ tee_optee_ta_uuid_to_octets(arg.uuid, &uuid);
+ arg.clnt_login = TEE_LOGIN_REE_KERNEL;
+ rc = tee_open_session(tee, &arg, 0, NULL);
+ if (rc < 0)
+ return -ENODEV;
+
+ *tee_session = arg.session;
+
+ return 0;
+}
+
+static int bsec_optee_open(struct udevice *dev)
+{
+ struct stm32mp_bsec_priv *priv = dev_get_priv(dev);
+ struct udevice *tee;
+ u32 tee_session;
+ int rc;
+
+ tee = tee_find_device(NULL, NULL, NULL, NULL);
+ if (!tee)
+ return -ENODEV;
+
+ /* try to open the STM32 BSEC TA */
+ rc = bsec_pta_open_session(tee, &tee_session);
+ if (rc)
+ return rc;
+
+ tee_close_session(tee, tee_session);
+
+ priv->tee = tee;
+
+ return 0;
+}
+
+static int bsec_optee_pta(struct udevice *dev, int cmd, int type, int offset,
+ void *buff, ulong size)
+{
+ struct stm32mp_bsec_priv *priv = dev_get_priv(dev);
+ u32 tee_session;
+ struct tee_invoke_arg arg;
+ struct tee_param param[2];
+ struct tee_shm *fw_shm;
+ int rc;
+
+ rc = bsec_pta_open_session(priv->tee, &tee_session);
+ if (rc)
+ return rc;
+
+ rc = tee_shm_register(priv->tee, buff, size, 0, &fw_shm);
+ if (rc)
+ goto close_session;
+
+ memset(&arg, 0, sizeof(arg));
+ arg.func = cmd;
+ arg.session = tee_session;
+
+ memset(param, 0, sizeof(param));
+
+ param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
+ param[0].u.value.a = offset;
+ param[0].u.value.b = type;
+
+ if (cmd == PTA_BSEC_WRITE_MEM)
+ param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
+ else
+ param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
+
+ param[1].u.memref.shm = fw_shm;
+ param[1].u.memref.size = size;
+
+ rc = tee_invoke_func(priv->tee, &arg, 2, param);
+ if (rc < 0 || arg.ret != 0) {
+ dev_err(priv->tee,
+ "PTA_BSEC invoke failed TEE err: %x, err:%x\n",
+ arg.ret, rc);
+ if (!rc)
+ rc = -EIO;
+ }
+
+ tee_shm_free(fw_shm);
+
+close_session:
+ tee_close_session(priv->tee, tee_session);
+
+ return rc;
+}
+
static int stm32mp_bsec_read(struct udevice *dev, int offset,
void *buf, int size)
{
+ struct stm32mp_bsec_priv *priv = dev_get_priv(dev);
int ret;
int i;
bool shadow = true, lock = false;
int nb_otp = size / sizeof(u32);
- int otp;
+ int otp, cmd;
unsigned int offs = offset;
if (offs >= STM32_BSEC_LOCK_OFFSET) {
@@ -491,6 +625,19 @@ static int stm32mp_bsec_read(struct udevice *dev, int offset,
if ((offs % 4) || (size % 4))
return -EINVAL;
+ if (IS_ENABLED(CONFIG_OPTEE) && priv->tee) {
+ cmd = FUSE_ACCESS;
+ if (shadow)
+ cmd = SHADOW_ACCESS;
+ if (lock)
+ cmd = LOCK_ACCESS;
+ ret = bsec_optee_pta(dev, PTA_BSEC_READ_MEM, cmd, offs, buf, size);
+ if (ret)
+ return ret;
+
+ return size;
+ }
+
otp = offs / sizeof(u32);
for (i = otp; i < (otp + nb_otp) && i <= BSEC_OTP_MAX_VALUE; i++) {
@@ -515,11 +662,12 @@ static int stm32mp_bsec_read(struct udevice *dev, int offset,
static int stm32mp_bsec_write(struct udevice *dev, int offset,
const void *buf, int size)
{
+ struct stm32mp_bsec_priv *priv = dev_get_priv(dev);
int ret = 0;
int i;
bool shadow = true, lock = false;
int nb_otp = size / sizeof(u32);
- int otp;
+ int otp, cmd;
unsigned int offs = offset;
if (offs >= STM32_BSEC_LOCK_OFFSET) {
@@ -533,6 +681,19 @@ static int stm32mp_bsec_write(struct udevice *dev, int offset,
if ((offs % 4) || (size % 4))
return -EINVAL;
+ if (IS_ENABLED(CONFIG_OPTEE) && priv->tee) {
+ cmd = FUSE_ACCESS;
+ if (shadow)
+ cmd = SHADOW_ACCESS;
+ if (lock)
+ cmd = LOCK_ACCESS;
+ ret = bsec_optee_pta(dev, PTA_BSEC_WRITE_MEM, cmd, offs, (void *)buf, size);
+ if (ret)
+ return ret;
+
+ return size;
+ }
+
otp = offs / sizeof(u32);
for (i = otp; i < otp + nb_otp && i <= BSEC_OTP_MAX_VALUE; i++) {
@@ -581,6 +742,9 @@ static int stm32mp_bsec_probe(struct udevice *dev)
return ret;
}
+ if (IS_ENABLED(CONFIG_OPTEE))
+ bsec_optee_open(dev);
+
/*
* update unlocked shadow for OTP cleared by the rom code
* only executed in SPL, it is done in TF-A for TFABOOT
@@ -607,6 +771,7 @@ U_BOOT_DRIVER(stm32mp_bsec) = {
.of_match = stm32mp_bsec_ids,
.of_to_plat = stm32mp_bsec_of_to_plat,
.plat_auto = sizeof(struct stm32mp_bsec_plat),
+ .priv_auto = sizeof(struct stm32mp_bsec_priv),
.ops = &stm32mp_bsec_ops,
.probe = stm32mp_bsec_probe,
};
diff --git a/arch/arm/mach-stm32mp/cmd_stm32key.c b/arch/arm/mach-stm32mp/cmd_stm32key.c
index 278253e472..85be8e23bd 100644
--- a/arch/arm/mach-stm32mp/cmd_stm32key.c
+++ b/arch/arm/mach-stm32mp/cmd_stm32key.c
@@ -8,6 +8,7 @@
#include <console.h>
#include <log.h>
#include <misc.h>
+#include <asm/arch/bsec.h>
#include <dm/device.h>
#include <dm/uclass.h>
@@ -84,9 +85,6 @@ static u32 get_otp_close_mask(void)
return STM32_OTP_STM32MP15x_CLOSE_MASK;
}
-#define BSEC_LOCK_ERROR (-1)
-#define BSEC_LOCK_PERM BIT(0)
-
static int get_misc_dev(struct udevice **dev)
{
int ret;
diff --git a/arch/arm/mach-stm32mp/include/mach/bsec.h b/arch/arm/mach-stm32mp/include/mach/bsec.h
index 252eac3946..10ebc535c4 100644
--- a/arch/arm/mach-stm32mp/include/mach/bsec.h
+++ b/arch/arm/mach-stm32mp/include/mach/bsec.h
@@ -5,3 +5,10 @@
/* check self hosted debug status = BSEC_DENABLE.DBGSWENABLE */
bool bsec_dbgswenable(void);
+
+/* Bitfield definition for LOCK status */
+#define BSEC_LOCK_PERM BIT(30)
+#define BSEC_LOCK_SHADOW_R BIT(29)
+#define BSEC_LOCK_SHADOW_W BIT(28)
+#define BSEC_LOCK_SHADOW_P BIT(27)
+#define BSEC_LOCK_ERROR BIT(26)
diff --git a/board/st/common/cmd_stboard.c b/board/st/common/cmd_stboard.c
index e12669b862..213fb5d302 100644
--- a/board/st/common/cmd_stboard.c
+++ b/board/st/common/cmd_stboard.c
@@ -34,6 +34,7 @@
#include <command.h>
#include <console.h>
#include <misc.h>
+#include <asm/arch/bsec.h>
#include <dm/device.h>
#include <dm/uclass.h>
@@ -109,7 +110,7 @@ static int do_stboard(struct cmd_tbl *cmdtp, int flag, int argc,
else
display_stboard(otp);
printf(" OTP %d %s locked !\n", BSEC_OTP_BOARD,
- lock == 1 ? "" : "NOT");
+ lock & BSEC_LOCK_PERM ? "" : "NOT");
return CMD_RET_SUCCESS;
}
@@ -178,7 +179,7 @@ static int do_stboard(struct cmd_tbl *cmdtp, int flag, int argc,
}
/* write persistent lock */
- otp = 1;
+ otp = BSEC_LOCK_PERM;
ret = misc_write(dev, STM32_BSEC_LOCK(BSEC_OTP_BOARD),
&otp, sizeof(otp));
if (ret != sizeof(otp)) {
diff --git a/doc/board/st/stm32mp1.rst b/doc/board/st/stm32mp1.rst
index 3759df353e..9780ac9768 100644
--- a/doc/board/st/stm32mp1.rst
+++ b/doc/board/st/stm32mp1.rst
@@ -620,7 +620,7 @@ Prerequisite: check if a MAC address isn't yet programmed in OTP
STM32MP> env print ethaddr
## Error: "ethaddr" not defined
-3) check lock status of fuse 57 & 58 (at 0x39, 0=unlocked, 1=locked)::
+3) check lock status of fuse 57 & 58 (at 0x39, 0=unlocked, 0x40000000=locked)::
STM32MP> fuse sense 0 0x10000039 2
Sensing bank 0:
@@ -640,11 +640,11 @@ Example to set mac address "12:34:56:78:9a:bc"
3) Lock OTP::
- STM32MP> fuse prog 0 0x10000039 1 1
+ STM32MP> fuse prog 0 0x10000039 0x40000000 0x40000000
STM32MP> fuse sense 0 0x10000039 2
Sensing bank 0:
- Word 0x10000039: 00000001 00000001
+ Word 0x10000039: 40000000 40000000
4) next REBOOT, in the trace::