1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright 2020 NXP 4 */ 5 6#include <command.h> 7#include <common.h> 8#include <env.h> 9#include <errno.h> 10#include <image.h> 11#include <malloc.h> 12#include <mmc.h> 13#include <tee.h> 14#include <tee/optee_ta_avb.h> 15 16static struct udevice *tee; 17static u32 session; 18 19static int avb_ta_open_session(void) 20{ 21 const struct tee_optee_ta_uuid uuid = TA_AVB_UUID; 22 struct tee_open_session_arg arg; 23 int rc; 24 25 tee = tee_find_device(tee, NULL, NULL, NULL); 26 if (!tee) 27 return -ENODEV; 28 29 memset(&arg, 0, sizeof(arg)); 30 tee_optee_ta_uuid_to_octets(arg.uuid, &uuid); 31 rc = tee_open_session(tee, &arg, 0, NULL); 32 if (!rc) 33 session = arg.session; 34 35 return 0; 36} 37 38static int invoke_func(u32 func, ulong num_param, struct tee_param *param) 39{ 40 struct tee_invoke_arg arg; 41 42 if (!tee) 43 if (avb_ta_open_session()) 44 return -ENODEV; 45 46 memset(&arg, 0, sizeof(arg)); 47 arg.func = func; 48 arg.session = session; 49 50 if (tee_invoke_func(tee, &arg, num_param, param)) 51 return -EFAULT; 52 switch (arg.ret) { 53 case TEE_SUCCESS: 54 return 0; 55 case TEE_ERROR_OUT_OF_MEMORY: 56 case TEE_ERROR_STORAGE_NO_SPACE: 57 return -ENOSPC; 58 case TEE_ERROR_ITEM_NOT_FOUND: 59 return -EIO; 60 case TEE_ERROR_TARGET_DEAD: 61 /* 62 * The TA has paniced, close the session to reload the TA 63 * for the next request. 64 */ 65 tee_close_session(tee, session); 66 tee = NULL; 67 return -EIO; 68 default: 69 return -EIO; 70 } 71} 72 73static int read_persistent_value(const char *name, 74 size_t buffer_size, 75 u8 *out_buffer, 76 size_t *out_num_bytes_read) 77{ 78 int rc = 0; 79 struct tee_shm *shm_name; 80 struct tee_shm *shm_buf; 81 struct tee_param param[2]; 82 size_t name_size = strlen(name) + 1; 83 84 if (!tee) 85 if (avb_ta_open_session()) 86 return -ENODEV; 87 88 rc = tee_shm_alloc(tee, name_size, 89 TEE_SHM_ALLOC, &shm_name); 90 if (rc) { 91 rc = -ENOMEM; 92 goto close_session; 93 } 94 95 rc = tee_shm_alloc(tee, buffer_size, 96 TEE_SHM_ALLOC, &shm_buf); 97 if (rc) { 98 rc = -ENOMEM; 99 goto free_name; 100 } 101 102 memcpy(shm_name->addr, name, name_size); 103 104 memset(param, 0, sizeof(param)); 105 param[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT; 106 param[0].u.memref.shm = shm_name; 107 param[0].u.memref.size = name_size; 108 param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INOUT; 109 param[1].u.memref.shm = shm_buf; 110 param[1].u.memref.size = buffer_size; 111 112 rc = invoke_func(TA_AVB_CMD_READ_PERSIST_VALUE, 113 2, param); 114 if (rc) 115 goto out; 116 117 if (param[1].u.memref.size > buffer_size) { 118 rc = -EINVAL; 119 goto out; 120 } 121 122 *out_num_bytes_read = param[1].u.memref.size; 123 124 memcpy(out_buffer, shm_buf->addr, *out_num_bytes_read); 125 126out: 127 tee_shm_free(shm_buf); 128free_name: 129 tee_shm_free(shm_name); 130close_session: 131 tee_close_session(tee, session); 132 tee = NULL; 133 134 return rc; 135} 136 137static int write_persistent_value(const char *name, 138 size_t value_size, 139 const u8 *value) 140{ 141 int rc = 0; 142 struct tee_shm *shm_name; 143 struct tee_shm *shm_buf; 144 struct tee_param param[2]; 145 size_t name_size = strlen(name) + 1; 146 147 if (!value_size) 148 return -EINVAL; 149 150 if (!tee) { 151 if (avb_ta_open_session()) 152 return -ENODEV; 153 } 154 155 rc = tee_shm_alloc(tee, name_size, 156 TEE_SHM_ALLOC, &shm_name); 157 if (rc) { 158 rc = -ENOMEM; 159 goto close_session; 160 } 161 162 rc = tee_shm_alloc(tee, value_size, 163 TEE_SHM_ALLOC, &shm_buf); 164 if (rc) { 165 rc = -ENOMEM; 166 goto free_name; 167 } 168 169 memcpy(shm_name->addr, name, name_size); 170 memcpy(shm_buf->addr, value, value_size); 171 172 memset(param, 0, sizeof(param)); 173 param[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT; 174 param[0].u.memref.shm = shm_name; 175 param[0].u.memref.size = name_size; 176 param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT; 177 param[1].u.memref.shm = shm_buf; 178 param[1].u.memref.size = value_size; 179 180 rc = invoke_func(TA_AVB_CMD_WRITE_PERSIST_VALUE, 181 2, param); 182 if (rc) 183 goto out; 184 185out: 186 tee_shm_free(shm_buf); 187free_name: 188 tee_shm_free(shm_name); 189close_session: 190 tee_close_session(tee, session); 191 tee = NULL; 192 193 return rc; 194} 195 196int do_optee_rpmb_read(struct cmd_tbl *cmdtp, int flag, int argc, 197 char * const argv[]) 198{ 199 const char *name; 200 size_t bytes; 201 size_t bytes_read; 202 void *buffer; 203 char *endp; 204 205 if (argc != 3) 206 return CMD_RET_USAGE; 207 208 name = argv[1]; 209 bytes = dectoul(argv[2], &endp); 210 if (*endp && *endp != '\n') 211 return CMD_RET_USAGE; 212 213 buffer = malloc(bytes); 214 if (!buffer) 215 return CMD_RET_FAILURE; 216 217 if (read_persistent_value(name, bytes, buffer, &bytes_read) == 0) { 218 printf("Read %zu bytes, value = %s\n", bytes_read, 219 (char *)buffer); 220 free(buffer); 221 return CMD_RET_SUCCESS; 222 } 223 224 printf("Failed to read persistent value\n"); 225 226 free(buffer); 227 228 return CMD_RET_FAILURE; 229} 230 231int do_optee_rpmb_write(struct cmd_tbl *cmdtp, int flag, int argc, 232 char * const argv[]) 233{ 234 const char *name; 235 const char *value; 236 237 if (argc != 3) 238 return CMD_RET_USAGE; 239 240 name = argv[1]; 241 value = argv[2]; 242 243 if (write_persistent_value(name, strlen(value) + 1, 244 (const uint8_t *)value) == 0) { 245 printf("Wrote %zu bytes\n", strlen(value) + 1); 246 return CMD_RET_SUCCESS; 247 } 248 249 printf("Failed to write persistent value\n"); 250 251 return CMD_RET_FAILURE; 252} 253 254static struct cmd_tbl cmd_optee_rpmb[] = { 255 U_BOOT_CMD_MKENT(read_pvalue, 3, 0, do_optee_rpmb_read, "", ""), 256 U_BOOT_CMD_MKENT(write_pvalue, 3, 0, do_optee_rpmb_write, "", ""), 257}; 258 259static int do_optee_rpmb(struct cmd_tbl *cmdtp, int flag, int argc, 260 char * const argv[]) 261{ 262 struct cmd_tbl *cp; 263 264 cp = find_cmd_tbl(argv[1], cmd_optee_rpmb, ARRAY_SIZE(cmd_optee_rpmb)); 265 266 argc--; 267 argv++; 268 269 if (!cp || argc > cp->maxargs) 270 return CMD_RET_USAGE; 271 272 if (flag == CMD_FLAG_REPEAT) 273 return CMD_RET_FAILURE; 274 275 return cp->cmd(cmdtp, flag, argc, argv); 276} 277 278U_BOOT_CMD ( 279 optee_rpmb, 29, 0, do_optee_rpmb, 280 "Provides commands for testing secure storage on RPMB on OPTEE", 281 "read_pvalue <name> <bytes> - read a persistent value <name>\n" 282 "optee_rpmb write_pvalue <name> <value> - write a persistent value <name>\n" 283 ); 284