On 3/28/22 19:25, Patrick Delaunay wrote: > When OP-TEE is used, the SMC for BSEC management are not > available and the PTA provisioning for OTP must be used. > > U-Boot opens the session to this PTA and use it for OTP > access. > > Signed-off-by: Patrick Delaunay <[email protected]> > --- > > arch/arm/mach-stm32mp/cmd_stm32prog/Kconfig | 2 +- > .../mach-stm32mp/cmd_stm32prog/stm32prog.c | 145 ++++++++++++++++-- > .../mach-stm32mp/cmd_stm32prog/stm32prog.h | 7 +- > .../cmd_stm32prog/stm32prog_usb.c | 2 +- > 4 files changed, 142 insertions(+), 14 deletions(-) > > diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/Kconfig > b/arch/arm/mach-stm32mp/cmd_stm32prog/Kconfig > index 81d2b87035..8f91db4b46 100644 > --- a/arch/arm/mach-stm32mp/cmd_stm32prog/Kconfig > +++ b/arch/arm/mach-stm32mp/cmd_stm32prog/Kconfig > @@ -35,6 +35,6 @@ config CMD_STM32PROG_SERIAL > config CMD_STM32PROG_OTP > bool "support stm32prog for OTP update" > depends on CMD_STM32PROG > - default y if ARM_SMCCC > + default y if ARM_SMCCC || OPTEE > help > Support the OTP update with the command "stm32prog" for STM32MP > diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c > b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c > index 3e9354b51d..5d53e6146f 100644 > --- a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c > +++ b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c > @@ -10,8 +10,10 @@ > #include <misc.h> > #include <mmc.h> > #include <part.h> > +#include <tee.h> > #include <asm/arch/stm32mp1_smc.h> > #include <asm/global_data.h> > +#include <dm/device_compat.h> > #include <dm/uclass.h> > #include <jffs2/load_kernel.h> > #include <linux/list.h> > @@ -79,8 +81,110 @@ struct fip_toc_header { > u64 flags; > }; > > +#define TA_NVMEM_UUID { 0x1a8342cc, 0x81a5, 0x4512, \ > + { 0x99, 0xfe, 0x9e, 0x2b, 0x3e, 0x37, 0xd6, 0x26 } } > + > +/* > + * Read NVMEM memory for STM32CubeProgrammer > + * > + * [in] value[0].a: Type (0 for OTP access) > + * [out] memref[1].buffer Output buffer to return all read values > + * [out] memref[1].size Size of buffer to be read > + * > + * Return codes: > + * TEE_SUCCESS - Invoke command success > + * TEE_ERROR_BAD_PARAMETERS - Incorrect input param > + */ > +#define TA_NVMEM_READ 0x0 > + > +/* > + * Write NVMEM memory for STM32CubeProgrammer > + * > + * [in] value[0].a Type (0 for OTP access) > + * [in] memref[1].buffer Input buffer with the values to write > + * [in] memref[1].size Size of buffer to be written > + * > + * Return codes: > + * TEE_SUCCESS - Invoke command success > + * TEE_ERROR_BAD_PARAMETERS - Incorrect input param > + */ > +#define TA_NVMEM_WRITE 0x1 > + > +/* value of TA_NVMEM type = value[in] a */ > +#define NVMEM_OTP 0 > + > DECLARE_GLOBAL_DATA_PTR; > > +/* OPTEE TA NVMEM open helper */ > +static int optee_ta_open(struct stm32prog_data *data) > +{ > + const struct tee_optee_ta_uuid uuid = TA_NVMEM_UUID; > + struct tee_open_session_arg arg; > + struct udevice *tee = NULL; > + int rc; > + > + if (data->tee) > + return 0; > + > + tee = tee_find_device(NULL, NULL, NULL, NULL); > + if (!tee) > + return -ENODEV; > + > + memset(&arg, 0, sizeof(arg)); > + tee_optee_ta_uuid_to_octets(arg.uuid, &uuid); > + rc = tee_open_session(tee, &arg, 0, NULL); > + if (rc < 0) > + return -ENODEV; > + > + data->tee = tee; > + data->tee_session = arg.session; > + > + return 0; > +} > + > +/* OPTEE TA NVMEM invoke helper */ > +static int optee_ta_invoke(struct stm32prog_data *data, int cmd, int type, > + void *buff, ulong size) > +{ > + struct tee_invoke_arg arg; > + struct tee_param param[2]; > + struct tee_shm *buff_shm; > + int rc; > + > + rc = tee_shm_register(data->tee, buff, size, 0, &buff_shm); > + if (rc) > + return rc; > + > + memset(&arg, 0, sizeof(arg)); > + arg.func = cmd; > + arg.session = data->tee_session; > + > + memset(param, 0, sizeof(param)); > + param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT; > + param[0].u.value.a = type; > + > + if (cmd == TA_NVMEM_WRITE) > + param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT; > + else > + param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_OUTPUT; > + > + param[1].u.memref.shm = buff_shm; > + param[1].u.memref.size = size; > + > + rc = tee_invoke_func(data->tee, &arg, 2, param); > + if (rc < 0 || arg.ret != 0) { > + dev_err(data->tee, > + "TA_NVMEM invoke failed TEE err: %x, err:%x\n", > + arg.ret, rc); > + if (!rc) > + rc = -EIO; > + } > + > + tee_shm_free(buff_shm); > + > + return rc; > +} > + > /* partition handling routines : CONFIG_CMD_MTDPARTS */ > int mtdparts_init(void); > int find_dev_and_part(const char *id, struct mtd_device **dev, > @@ -1208,7 +1312,11 @@ static int dfu_init_entities(struct stm32prog_data > *data) > ret = stm32prog_alt_add_virt(dfu, "virtual", PHASE_CMD, > CMD_SIZE); > > if (!ret && IS_ENABLED(CONFIG_CMD_STM32PROG_OTP)) { > - ret = stm32prog_alt_add_virt(dfu, "OTP", PHASE_OTP, OTP_SIZE); > + ret = optee_ta_open(data); > + log_debug("optee_ta result %d\n", ret); > + ret = stm32prog_alt_add_virt(dfu, "OTP", PHASE_OTP, > + data->tee ? OTP_SIZE_TA : > OTP_SIZE_SMC); > + } > > if (!ret && CONFIG_IS_ENABLED(DM_PMIC)) > ret = stm32prog_alt_add_virt(dfu, "PMIC", PHASE_PMIC, > PMIC_SIZE); > @@ -1226,6 +1334,7 @@ static int dfu_init_entities(struct stm32prog_data > *data) > int stm32prog_otp_write(struct stm32prog_data *data, u32 offset, u8 *buffer, > long *size) > { > + u32 otp_size = data->tee ? OTP_SIZE_TA : OTP_SIZE_SMC; > log_debug("%s: %x %lx\n", __func__, offset, *size); > > if (!IS_ENABLED(CONFIG_CMD_STM32PROG_OTP)) { > @@ -1233,17 +1342,18 @@ int stm32prog_otp_write(struct stm32prog_data *data, > u32 offset, u8 *buffer, > > return -EOPNOTSUPP; > } > + > if (!data->otp_part) { > - data->otp_part = memalign(CONFIG_SYS_CACHELINE_SIZE, OTP_SIZE); > + data->otp_part = memalign(CONFIG_SYS_CACHELINE_SIZE, otp_size); > if (!data->otp_part) > return -ENOMEM; > } > > if (!offset) > - memset(data->otp_part, 0, OTP_SIZE); > + memset(data->otp_part, 0, otp_size); > > - if (offset + *size > OTP_SIZE) > - *size = OTP_SIZE - offset; > + if (offset + *size > otp_size) > + *size = otp_size - offset; > > memcpy((void *)((u32)data->otp_part + offset), buffer, *size); > > @@ -1253,6 +1363,7 @@ int stm32prog_otp_write(struct stm32prog_data *data, > u32 offset, u8 *buffer, > int stm32prog_otp_read(struct stm32prog_data *data, u32 offset, u8 *buffer, > long *size) > { > + u32 otp_size = data->tee ? OTP_SIZE_TA : OTP_SIZE_SMC; > int result = 0; > > if (!IS_ENABLED(CONFIG_CMD_STM32PROG_OTP)) { > @@ -1266,7 +1377,7 @@ int stm32prog_otp_read(struct stm32prog_data *data, u32 > offset, u8 *buffer, > if (!offset) { > if (!data->otp_part) > data->otp_part = > - memalign(CONFIG_SYS_CACHELINE_SIZE, OTP_SIZE); > + memalign(CONFIG_SYS_CACHELINE_SIZE, otp_size); > > if (!data->otp_part) { > result = -ENOMEM; > @@ -1274,11 +1385,14 @@ int stm32prog_otp_read(struct stm32prog_data *data, > u32 offset, u8 *buffer, > } > > /* init struct with 0 */ > - memset(data->otp_part, 0, OTP_SIZE); > + memset(data->otp_part, 0, otp_size); > > /* call the service */ > result = -EOPNOTSUPP; > - if (IS_ENABLED(CONFIG_ARM_SMCCC)) > + if (data->tee && CONFIG_IS_ENABLED(OPTEE)) > + result = optee_ta_invoke(data, TA_NVMEM_READ, NVMEM_OTP, > + data->otp_part, OTP_SIZE_TA); > + else if (IS_ENABLED(CONFIG_ARM_SMCCC)) > result = stm32_smc_exec(STM32_SMC_BSEC, > STM32_SMC_READ_ALL, > (u32)data->otp_part, 0); > if (result) > @@ -1290,8 +1404,8 @@ int stm32prog_otp_read(struct stm32prog_data *data, u32 > offset, u8 *buffer, > goto end_otp_read; > } > > - if (offset + *size > OTP_SIZE) > - *size = OTP_SIZE - offset; > + if (offset + *size > otp_size) > + *size = otp_size - offset; > memcpy(buffer, (void *)((u32)data->otp_part + offset), *size); > > end_otp_read: > @@ -1317,7 +1431,10 @@ int stm32prog_otp_start(struct stm32prog_data *data) > } > > result = -EOPNOTSUPP; > - if (IS_ENABLED(CONFIG_ARM_SMCCC)) { > + if (data->tee && CONFIG_IS_ENABLED(OPTEE)) { > + result = optee_ta_invoke(data, TA_NVMEM_WRITE, NVMEM_OTP, > + data->otp_part, OTP_SIZE_TA); > + } else if (IS_ENABLED(CONFIG_ARM_SMCCC)) { > arm_smccc_smc(STM32_SMC_BSEC, STM32_SMC_WRITE_ALL, > (u32)data->otp_part, 0, 0, 0, 0, 0, &res); > > @@ -1751,6 +1868,12 @@ void stm32prog_clean(struct stm32prog_data *data) > free(data->part_array); > free(data->otp_part); > free(data->buffer); > + > + if (CONFIG_IS_ENABLED(OPTEE) && data->tee) { > + tee_close_session(data->tee, data->tee_session); > + data->tee = NULL; > + data->tee_session = 0x0; > + } > } > > /* DFU callback: used after serial and direct DFU USB access */ > diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.h > b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.h > index 240c5c44bc..928b7b3a0e 100644 > --- a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.h > +++ b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.h > @@ -20,7 +20,8 @@ > #define DEFAULT_ADDRESS 0xFFFFFFFF > > #define CMD_SIZE 512 > -#define OTP_SIZE 1024 > +#define OTP_SIZE_SMC 1024 > +#define OTP_SIZE_TA 776 > #define PMIC_SIZE 8 > > enum stm32prog_target { > @@ -147,6 +148,10 @@ struct stm32prog_data { > u32 dtb; > u32 initrd; > u32 initrd_size; > + > + /* OPTEE PTA NVMEM */ > + struct udevice *tee; > + u32 tee_session; > }; > > extern struct stm32prog_data *stm32prog_data; > diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog_usb.c > b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog_usb.c > index e8acc302f9..82b702f93b 100644 > --- a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog_usb.c > +++ b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog_usb.c > @@ -181,7 +181,7 @@ int stm32prog_get_medium_size_virt(struct dfu_entity > *dfu, u64 *size) > *size = CMD_SIZE; > break; > case PHASE_OTP: > - *size = OTP_SIZE; > + *size = stm32prog_data->tee ? OTP_SIZE_TA : OTP_SIZE_SMC; > break; > case PHASE_PMIC: > *size = PMIC_SIZE; Applied to u-boot-stm32 Thanks Patrice

