blob: b3cafd924108fa417bc483b843bf42514c2be14a [file] [log] [blame]
Ruchika Gupta1a994352020-10-23 13:39:33 +05301// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright 2020 NXP
4 */
5
6#include <command.h>
Tom Riniabb9a042024-05-18 20:20:43 -06007#include <common.h>
Ruchika Gupta1a994352020-10-23 13:39:33 +05308#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);
Igor Opaniuk3db69742024-04-04 15:19:48 +020090 if (rc) {
91 rc = -ENOMEM;
92 goto close_session;
93 }
Ruchika Gupta1a994352020-10-23 13:39:33 +053094
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);
Igor Opaniuk3db69742024-04-04 15:19:48 +0200130close_session:
131 tee_close_session(tee, session);
132 tee = NULL;
Ruchika Gupta1a994352020-10-23 13:39:33 +0530133
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
Igor Opaniuk3db69742024-04-04 15:19:48 +0200147 if (!value_size)
148 return -EINVAL;
149
Ruchika Gupta1a994352020-10-23 13:39:33 +0530150 if (!tee) {
151 if (avb_ta_open_session())
152 return -ENODEV;
153 }
Ruchika Gupta1a994352020-10-23 13:39:33 +0530154
155 rc = tee_shm_alloc(tee, name_size,
156 TEE_SHM_ALLOC, &shm_name);
Igor Opaniuk3db69742024-04-04 15:19:48 +0200157 if (rc) {
158 rc = -ENOMEM;
159 goto close_session;
160 }
Ruchika Gupta1a994352020-10-23 13:39:33 +0530161
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);
Igor Opaniuk3db69742024-04-04 15:19:48 +0200189close_session:
190 tee_close_session(tee, session);
191 tee = NULL;
Ruchika Gupta1a994352020-10-23 13:39:33 +0530192
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];
Simon Glassff9b9032021-07-24 09:03:30 -0600209 bytes = dectoul(argv[2], &endp);
Ruchika Gupta1a994352020-10-23 13:39:33 +0530210 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 );