Merge tag 'mmc-2021-4-6' of https://source.denx.de/u-boot/custodians/u-boot-mmc
[platform/kernel/u-boot.git] / cmd / optee_rpmb.c
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
16 static struct udevice *tee;
17 static u32 session;
18
19 static 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
38 static 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
73 static 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                 return -ENOMEM;
92
93         rc = tee_shm_alloc(tee, buffer_size,
94                            TEE_SHM_ALLOC, &shm_buf);
95         if (rc) {
96                 rc = -ENOMEM;
97                 goto free_name;
98         }
99
100         memcpy(shm_name->addr, name, name_size);
101
102         memset(param, 0, sizeof(param));
103         param[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
104         param[0].u.memref.shm = shm_name;
105         param[0].u.memref.size = name_size;
106         param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INOUT;
107         param[1].u.memref.shm = shm_buf;
108         param[1].u.memref.size = buffer_size;
109
110         rc = invoke_func(TA_AVB_CMD_READ_PERSIST_VALUE,
111                          2, param);
112         if (rc)
113                 goto out;
114
115         if (param[1].u.memref.size > buffer_size) {
116                 rc = -EINVAL;
117                 goto out;
118         }
119
120         *out_num_bytes_read = param[1].u.memref.size;
121
122         memcpy(out_buffer, shm_buf->addr, *out_num_bytes_read);
123
124 out:
125         tee_shm_free(shm_buf);
126 free_name:
127         tee_shm_free(shm_name);
128
129         return rc;
130 }
131
132 static int write_persistent_value(const char *name,
133                                   size_t value_size,
134                                   const u8 *value)
135 {
136         int rc = 0;
137         struct tee_shm *shm_name;
138         struct tee_shm *shm_buf;
139         struct tee_param param[2];
140         size_t name_size = strlen(name) + 1;
141
142         if (!tee) {
143                 if (avb_ta_open_session())
144                         return -ENODEV;
145         }
146         if (!value_size)
147                 return -EINVAL;
148
149         rc = tee_shm_alloc(tee, name_size,
150                            TEE_SHM_ALLOC, &shm_name);
151         if (rc)
152                 return -ENOMEM;
153
154         rc = tee_shm_alloc(tee, value_size,
155                            TEE_SHM_ALLOC, &shm_buf);
156         if (rc) {
157                 rc = -ENOMEM;
158                 goto free_name;
159         }
160
161         memcpy(shm_name->addr, name, name_size);
162         memcpy(shm_buf->addr, value, value_size);
163
164         memset(param, 0, sizeof(param));
165         param[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
166         param[0].u.memref.shm = shm_name;
167         param[0].u.memref.size = name_size;
168         param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
169         param[1].u.memref.shm = shm_buf;
170         param[1].u.memref.size = value_size;
171
172         rc = invoke_func(TA_AVB_CMD_WRITE_PERSIST_VALUE,
173                          2, param);
174         if (rc)
175                 goto out;
176
177 out:
178         tee_shm_free(shm_buf);
179 free_name:
180         tee_shm_free(shm_name);
181
182         return rc;
183 }
184
185 int do_optee_rpmb_read(struct cmd_tbl *cmdtp, int flag, int argc,
186                        char * const argv[])
187 {
188         const char *name;
189         size_t bytes;
190         size_t bytes_read;
191         void *buffer;
192         char *endp;
193
194         if (argc != 3)
195                 return CMD_RET_USAGE;
196
197         name = argv[1];
198         bytes = simple_strtoul(argv[2], &endp, 10);
199         if (*endp && *endp != '\n')
200                 return CMD_RET_USAGE;
201
202         buffer = malloc(bytes);
203         if (!buffer)
204                 return CMD_RET_FAILURE;
205
206         if (read_persistent_value(name, bytes, buffer, &bytes_read) == 0) {
207                 printf("Read %zu bytes, value = %s\n", bytes_read,
208                        (char *)buffer);
209                 free(buffer);
210                 return CMD_RET_SUCCESS;
211         }
212
213         printf("Failed to read persistent value\n");
214
215         free(buffer);
216
217         return CMD_RET_FAILURE;
218 }
219
220 int do_optee_rpmb_write(struct cmd_tbl *cmdtp, int flag, int argc,
221                         char * const argv[])
222 {
223         const char *name;
224         const char *value;
225
226         if (argc != 3)
227                 return CMD_RET_USAGE;
228
229         name = argv[1];
230         value = argv[2];
231
232         if (write_persistent_value(name, strlen(value) + 1,
233                                    (const uint8_t *)value) == 0) {
234                 printf("Wrote %zu bytes\n", strlen(value) + 1);
235                 return CMD_RET_SUCCESS;
236         }
237
238         printf("Failed to write persistent value\n");
239
240         return CMD_RET_FAILURE;
241 }
242
243 static struct cmd_tbl cmd_optee_rpmb[] = {
244         U_BOOT_CMD_MKENT(read_pvalue, 3, 0, do_optee_rpmb_read, "", ""),
245         U_BOOT_CMD_MKENT(write_pvalue, 3, 0, do_optee_rpmb_write, "", ""),
246 };
247
248 static int do_optee_rpmb(struct cmd_tbl *cmdtp, int flag, int argc,
249                          char * const argv[])
250 {
251         struct cmd_tbl *cp;
252
253         cp = find_cmd_tbl(argv[1], cmd_optee_rpmb, ARRAY_SIZE(cmd_optee_rpmb));
254
255         argc--;
256         argv++;
257
258         if (!cp || argc > cp->maxargs)
259                 return CMD_RET_USAGE;
260
261         if (flag == CMD_FLAG_REPEAT)
262                 return CMD_RET_FAILURE;
263
264         return cp->cmd(cmdtp, flag, argc, argv);
265 }
266
267 U_BOOT_CMD (
268         optee_rpmb, 29, 0, do_optee_rpmb,
269         "Provides commands for testing secure storage on RPMB on OPTEE",
270         "read_pvalue <name> <bytes> - read a persistent value <name>\n"
271         "optee_rpmb write_pvalue <name> <value> - write a persistent value <name>\n"
272         );