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