Hi Patrick On 1/6/23 13:20, Patrick Delaunay wrote: > When OP-TEE is used, the SMC for BSEC management are not available and > the STM32MP BSEC pseudo TA must be used (it is mandatory for STM32MP13 > and it is a new feature for STM32MP15x). > > The BSEC driver try to open a session to this PTA BSEC at probe > and use it for OTP read or write access to fuse or to shadow. > > This patch also adapts the commands stm32key and stboard to handle > the BSEC_LOCK_PERM lock value instead of 1. > > Signed-off-by: Patrick Delaunay <patrick.delau...@foss.st.com> > --- > > arch/arm/mach-stm32mp/bsec.c | 173 +++++++++++++++++++++- > arch/arm/mach-stm32mp/cmd_stm32key.c | 4 +- > arch/arm/mach-stm32mp/include/mach/bsec.h | 7 + > board/st/common/cmd_stboard.c | 5 +- > doc/board/st/stm32mp1.rst | 6 +- > 5 files changed, 183 insertions(+), 12 deletions(-) > > diff --git a/arch/arm/mach-stm32mp/bsec.c b/arch/arm/mach-stm32mp/bsec.c > index 51ccff9aa560..fe79c986f95c 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 278253e472f5..85be8e23bdba 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 252eac3946a4..10ebc535c4b5 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 e12669b8628d..213fb5d30208 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 3759df353ee5..9780ac9768cf 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:: >
Reviewed-by: Patrice Chotard <patrice.chot...@foss.st.com> Thanks Patrice