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

Reply via email to