1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * OP-TEE STM32MP BSEC PTA interface, used by STM32 ROMEM driver 4 * 5 * Copyright (C) 2022, STMicroelectronics - All Rights Reserved 6 */ 7 8 #include <linux/tee_drv.h> 9 10 #include "stm32-bsec-optee-ta.h" 11 12 /* 13 * Read OTP memory 14 * 15 * [in] value[0].a OTP start offset in byte 16 * [in] value[0].b Access type (0:shadow, 1:fuse, 2:lock) 17 * [out] memref[1].buffer Output buffer to store read values 18 * [out] memref[1].size Size of OTP to be read 19 * 20 * Return codes: 21 * TEE_SUCCESS - Invoke command success 22 * TEE_ERROR_BAD_PARAMETERS - Incorrect input param 23 * TEE_ERROR_ACCESS_DENIED - OTP not accessible by caller 24 */ 25 #define PTA_BSEC_READ_MEM 0x0 26 27 /* 28 * Write OTP memory 29 * 30 * [in] value[0].a OTP start offset in byte 31 * [in] value[0].b Access type (0:shadow, 1:fuse, 2:lock) 32 * [in] memref[1].buffer Input buffer to read values 33 * [in] memref[1].size Size of OTP to be written 34 * 35 * Return codes: 36 * TEE_SUCCESS - Invoke command success 37 * TEE_ERROR_BAD_PARAMETERS - Incorrect input param 38 * TEE_ERROR_ACCESS_DENIED - OTP not accessible by caller 39 */ 40 #define PTA_BSEC_WRITE_MEM 0x1 41 42 /* value of PTA_BSEC access type = value[in] b */ 43 #define SHADOW_ACCESS 0 44 #define FUSE_ACCESS 1 45 #define LOCK_ACCESS 2 46 47 /* Bitfield definition for LOCK status */ 48 #define LOCK_PERM BIT(30) 49 50 /* OP-TEE STM32MP BSEC TA UUID */ 51 static const uuid_t stm32mp_bsec_ta_uuid = 52 UUID_INIT(0x94cf71ad, 0x80e6, 0x40b5, 53 0xa7, 0xc6, 0x3d, 0xc5, 0x01, 0xeb, 0x28, 0x03); 54 55 /* 56 * Check whether this driver supports the BSEC TA in the TEE instance 57 * represented by the params (ver/data) to this function. 58 */ 59 static int stm32_bsec_optee_ta_match(struct tee_ioctl_version_data *ver, 60 const void *data) 61 { 62 /* Currently this driver only supports GP compliant, OP-TEE based TA */ 63 if ((ver->impl_id == TEE_IMPL_ID_OPTEE) && 64 (ver->gen_caps & TEE_GEN_CAP_GP)) 65 return 1; 66 else 67 return 0; 68 } 69 70 /* Open a session to OP-TEE for STM32MP BSEC TA */ 71 static int stm32_bsec_ta_open_session(struct tee_context *ctx, u32 *id) 72 { 73 struct tee_ioctl_open_session_arg sess_arg; 74 int rc; 75 76 memset(&sess_arg, 0, sizeof(sess_arg)); 77 export_uuid(sess_arg.uuid, &stm32mp_bsec_ta_uuid); 78 sess_arg.clnt_login = TEE_IOCTL_LOGIN_REE_KERNEL; 79 sess_arg.num_params = 0; 80 81 rc = tee_client_open_session(ctx, &sess_arg, NULL); 82 if ((rc < 0) || (sess_arg.ret != 0)) { 83 pr_err("%s: tee_client_open_session failed err:%#x, ret:%#x\n", 84 __func__, sess_arg.ret, rc); 85 if (!rc) 86 rc = -EINVAL; 87 } else { 88 *id = sess_arg.session; 89 } 90 91 return rc; 92 } 93 94 /* close a session to OP-TEE for STM32MP BSEC TA */ 95 static void stm32_bsec_ta_close_session(void *ctx, u32 id) 96 { 97 tee_client_close_session(ctx, id); 98 } 99 100 /* stm32_bsec_optee_ta_open() - initialize the STM32MP BSEC TA */ 101 int stm32_bsec_optee_ta_open(struct tee_context **ctx) 102 { 103 struct tee_context *tee_ctx; 104 u32 session_id; 105 int rc; 106 107 /* Open context with TEE driver */ 108 tee_ctx = tee_client_open_context(NULL, stm32_bsec_optee_ta_match, NULL, NULL); 109 if (IS_ERR(tee_ctx)) { 110 rc = PTR_ERR(tee_ctx); 111 if (rc == -ENOENT) 112 return -EPROBE_DEFER; 113 pr_err("%s: tee_client_open_context failed (%d)\n", __func__, rc); 114 115 return rc; 116 } 117 118 /* Check STM32MP BSEC TA presence */ 119 rc = stm32_bsec_ta_open_session(tee_ctx, &session_id); 120 if (rc) { 121 tee_client_close_context(tee_ctx); 122 return rc; 123 } 124 125 stm32_bsec_ta_close_session(tee_ctx, session_id); 126 127 *ctx = tee_ctx; 128 129 return 0; 130 } 131 132 /* stm32_bsec_optee_ta_open() - release the PTA STM32MP BSEC TA */ 133 void stm32_bsec_optee_ta_close(void *ctx) 134 { 135 tee_client_close_context(ctx); 136 } 137 138 /* stm32_bsec_optee_ta_read() - nvmem read access using PTA client driver */ 139 int stm32_bsec_optee_ta_read(struct tee_context *ctx, unsigned int offset, 140 void *buf, size_t bytes) 141 { 142 struct tee_shm *shm; 143 struct tee_ioctl_invoke_arg arg; 144 struct tee_param param[2]; 145 u8 *shm_buf; 146 u32 start, num_bytes; 147 int ret; 148 u32 session_id; 149 150 ret = stm32_bsec_ta_open_session(ctx, &session_id); 151 if (ret) 152 return ret; 153 154 memset(&arg, 0, sizeof(arg)); 155 memset(¶m, 0, sizeof(param)); 156 157 arg.func = PTA_BSEC_READ_MEM; 158 arg.session = session_id; 159 arg.num_params = 2; 160 161 /* align access on 32bits */ 162 start = ALIGN_DOWN(offset, 4); 163 num_bytes = round_up(offset + bytes - start, 4); 164 param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT; 165 param[0].u.value.a = start; 166 param[0].u.value.b = SHADOW_ACCESS; 167 168 shm = tee_shm_alloc_kernel_buf(ctx, num_bytes); 169 if (IS_ERR(shm)) { 170 ret = PTR_ERR(shm); 171 goto out_tee_session; 172 } 173 174 param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT; 175 param[1].u.memref.shm = shm; 176 param[1].u.memref.size = num_bytes; 177 178 ret = tee_client_invoke_func(ctx, &arg, param); 179 if (ret < 0 || arg.ret != 0) { 180 pr_err("TA_BSEC invoke failed TEE err:%#x, ret:%#x\n", 181 arg.ret, ret); 182 if (!ret) 183 ret = -EIO; 184 } 185 if (!ret) { 186 shm_buf = tee_shm_get_va(shm, 0); 187 if (IS_ERR(shm_buf)) { 188 ret = PTR_ERR(shm_buf); 189 pr_err("tee_shm_get_va failed for transmit (%d)\n", ret); 190 } else { 191 /* read data from 32 bits aligned buffer */ 192 memcpy(buf, &shm_buf[offset % 4], bytes); 193 } 194 } 195 196 tee_shm_free(shm); 197 198 out_tee_session: 199 stm32_bsec_ta_close_session(ctx, session_id); 200 201 return ret; 202 } 203 204 /* stm32_bsec_optee_ta_write() - nvmem write access using PTA client driver */ 205 int stm32_bsec_optee_ta_write(struct tee_context *ctx, unsigned int lower, 206 unsigned int offset, void *buf, size_t bytes) 207 { struct tee_shm *shm; 208 struct tee_ioctl_invoke_arg arg; 209 struct tee_param param[2]; 210 u8 *shm_buf; 211 int ret; 212 u32 session_id; 213 214 ret = stm32_bsec_ta_open_session(ctx, &session_id); 215 if (ret) 216 return ret; 217 218 /* Allow only writing complete 32-bits aligned words */ 219 if ((bytes % 4) || (offset % 4)) 220 return -EINVAL; 221 222 memset(&arg, 0, sizeof(arg)); 223 memset(¶m, 0, sizeof(param)); 224 225 arg.func = PTA_BSEC_WRITE_MEM; 226 arg.session = session_id; 227 arg.num_params = 2; 228 229 param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT; 230 param[0].u.value.a = offset; 231 param[0].u.value.b = FUSE_ACCESS; 232 233 shm = tee_shm_alloc_kernel_buf(ctx, bytes); 234 if (IS_ERR(shm)) { 235 ret = PTR_ERR(shm); 236 goto out_tee_session; 237 } 238 239 param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT; 240 param[1].u.memref.shm = shm; 241 param[1].u.memref.size = bytes; 242 243 shm_buf = tee_shm_get_va(shm, 0); 244 if (IS_ERR(shm_buf)) { 245 ret = PTR_ERR(shm_buf); 246 pr_err("tee_shm_get_va failed for transmit (%d)\n", ret); 247 tee_shm_free(shm); 248 249 goto out_tee_session; 250 } 251 252 memcpy(shm_buf, buf, bytes); 253 254 ret = tee_client_invoke_func(ctx, &arg, param); 255 if (ret < 0 || arg.ret != 0) { 256 pr_err("TA_BSEC invoke failed TEE err:%#x, ret:%#x\n", arg.ret, ret); 257 if (!ret) 258 ret = -EIO; 259 } 260 pr_debug("Write OTPs %d to %zu, ret=%d\n", offset / 4, (offset + bytes) / 4, ret); 261 262 /* Lock the upper OTPs with ECC protection, word programming only */ 263 if (!ret && ((offset + bytes) >= (lower * 4))) { 264 u32 start, nb_lock; 265 u32 *lock = (u32 *)shm_buf; 266 int i; 267 268 /* 269 * don't lock the lower OTPs, no ECC protection and incremental 270 * bit programming, a second write is allowed 271 */ 272 start = max_t(u32, offset, lower * 4); 273 nb_lock = (offset + bytes - start) / 4; 274 275 param[0].u.value.a = start; 276 param[0].u.value.b = LOCK_ACCESS; 277 param[1].u.memref.size = nb_lock * 4; 278 279 for (i = 0; i < nb_lock; i++) 280 lock[i] = LOCK_PERM; 281 282 ret = tee_client_invoke_func(ctx, &arg, param); 283 if (ret < 0 || arg.ret != 0) { 284 pr_err("TA_BSEC invoke failed TEE err:%#x, ret:%#x\n", arg.ret, ret); 285 if (!ret) 286 ret = -EIO; 287 } 288 pr_debug("Lock upper OTPs %d to %d, ret=%d\n", 289 start / 4, start / 4 + nb_lock, ret); 290 } 291 292 tee_shm_free(shm); 293 294 out_tee_session: 295 stm32_bsec_ta_close_session(ctx, session_id); 296 297 return ret; 298 } 299