Coverage Report

Created: 2026-03-11 06:21

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