blob: cff9117d92f1c1d8a74e24a6625d79f03454ab96 [file] [log] [blame]
Igor Opaniuka14aa592024-02-09 20:20:40 +01001// SPDX-License-Identifier: GPL-2.0+
Igor Opaniuk3af30e42018-06-03 21:56:38 +03002/*
3 * (C) Copyright 2018, Linaro Limited
Igor Opaniuk3af30e42018-06-03 21:56:38 +03004 */
5
6#include <avb_verify.h>
Igor Opaniuke9ee7392018-07-17 14:33:26 +03007#include <blk.h>
Simon Glass1eb69ae2019-11-14 12:57:39 -07008#include <cpu_func.h>
Igor Opaniuk3af30e42018-06-03 21:56:38 +03009#include <image.h>
10#include <malloc.h>
11#include <part.h>
Jens Wiklander6663e072018-09-25 16:40:20 +020012#include <tee.h>
13#include <tee/optee_ta_avb.h>
Igor Opaniuk3af30e42018-06-03 21:56:38 +030014
Eugeniu Rosca55d56d22018-08-14 02:43:06 +020015static const unsigned char avb_root_pub[1032] = {
Igor Opaniuk3af30e42018-06-03 21:56:38 +030016 0x0, 0x0, 0x10, 0x0, 0x55, 0xd9, 0x4, 0xad, 0xd8, 0x4,
17 0xaf, 0xe3, 0xd3, 0x84, 0x6c, 0x7e, 0xd, 0x89, 0x3d, 0xc2,
18 0x8c, 0xd3, 0x12, 0x55, 0xe9, 0x62, 0xc9, 0xf1, 0xf, 0x5e,
19 0xcc, 0x16, 0x72, 0xab, 0x44, 0x7c, 0x2c, 0x65, 0x4a, 0x94,
20 0xb5, 0x16, 0x2b, 0x0, 0xbb, 0x6, 0xef, 0x13, 0x7, 0x53,
21 0x4c, 0xf9, 0x64, 0xb9, 0x28, 0x7a, 0x1b, 0x84, 0x98, 0x88,
22 0xd8, 0x67, 0xa4, 0x23, 0xf9, 0xa7, 0x4b, 0xdc, 0x4a, 0xf,
23 0xf7, 0x3a, 0x18, 0xae, 0x54, 0xa8, 0x15, 0xfe, 0xb0, 0xad,
24 0xac, 0x35, 0xda, 0x3b, 0xad, 0x27, 0xbc, 0xaf, 0xe8, 0xd3,
25 0x2f, 0x37, 0x34, 0xd6, 0x51, 0x2b, 0x6c, 0x5a, 0x27, 0xd7,
26 0x96, 0x6, 0xaf, 0x6b, 0xb8, 0x80, 0xca, 0xfa, 0x30, 0xb4,
27 0xb1, 0x85, 0xb3, 0x4d, 0xaa, 0xaa, 0xc3, 0x16, 0x34, 0x1a,
28 0xb8, 0xe7, 0xc7, 0xfa, 0xf9, 0x9, 0x77, 0xab, 0x97, 0x93,
29 0xeb, 0x44, 0xae, 0xcf, 0x20, 0xbc, 0xf0, 0x80, 0x11, 0xdb,
30 0x23, 0xc, 0x47, 0x71, 0xb9, 0x6d, 0xd6, 0x7b, 0x60, 0x47,
31 0x87, 0x16, 0x56, 0x93, 0xb7, 0xc2, 0x2a, 0x9a, 0xb0, 0x4c,
32 0x1, 0xc, 0x30, 0xd8, 0x93, 0x87, 0xf0, 0xed, 0x6e, 0x8b,
33 0xbe, 0x30, 0x5b, 0xf6, 0xa6, 0xaf, 0xdd, 0x80, 0x7c, 0x45,
34 0x5e, 0x8f, 0x91, 0x93, 0x5e, 0x44, 0xfe, 0xb8, 0x82, 0x7,
35 0xee, 0x79, 0xca, 0xbf, 0x31, 0x73, 0x62, 0x58, 0xe3, 0xcd,
36 0xc4, 0xbc, 0xc2, 0x11, 0x1d, 0xa1, 0x4a, 0xbf, 0xfe, 0x27,
37 0x7d, 0xa1, 0xf6, 0x35, 0xa3, 0x5e, 0xca, 0xdc, 0x57, 0x2f,
38 0x3e, 0xf0, 0xc9, 0x5d, 0x86, 0x6a, 0xf8, 0xaf, 0x66, 0xa7,
39 0xed, 0xcd, 0xb8, 0xed, 0xa1, 0x5f, 0xba, 0x9b, 0x85, 0x1a,
40 0xd5, 0x9, 0xae, 0x94, 0x4e, 0x3b, 0xcf, 0xcb, 0x5c, 0xc9,
41 0x79, 0x80, 0xf7, 0xcc, 0xa6, 0x4a, 0xa8, 0x6a, 0xd8, 0xd3,
42 0x31, 0x11, 0xf9, 0xf6, 0x2, 0x63, 0x2a, 0x1a, 0x2d, 0xd1,
43 0x1a, 0x66, 0x1b, 0x16, 0x41, 0xbd, 0xbd, 0xf7, 0x4d, 0xc0,
44 0x4a, 0xe5, 0x27, 0x49, 0x5f, 0x7f, 0x58, 0xe3, 0x27, 0x2d,
45 0xe5, 0xc9, 0x66, 0xe, 0x52, 0x38, 0x16, 0x38, 0xfb, 0x16,
46 0xeb, 0x53, 0x3f, 0xe6, 0xfd, 0xe9, 0xa2, 0x5e, 0x25, 0x59,
47 0xd8, 0x79, 0x45, 0xff, 0x3, 0x4c, 0x26, 0xa2, 0x0, 0x5a,
48 0x8e, 0xc2, 0x51, 0xa1, 0x15, 0xf9, 0x7b, 0xf4, 0x5c, 0x81,
49 0x9b, 0x18, 0x47, 0x35, 0xd8, 0x2d, 0x5, 0xe9, 0xad, 0xf,
50 0x35, 0x74, 0x15, 0xa3, 0x8e, 0x8b, 0xcc, 0x27, 0xda, 0x7c,
51 0x5d, 0xe4, 0xfa, 0x4, 0xd3, 0x5, 0xb, 0xba, 0x3a, 0xb2,
52 0x49, 0x45, 0x2f, 0x47, 0xc7, 0xd, 0x41, 0x3f, 0x97, 0x80,
53 0x4d, 0x3f, 0xc1, 0xb5, 0xbb, 0x70, 0x5f, 0xa7, 0x37, 0xaf,
54 0x48, 0x22, 0x12, 0x45, 0x2e, 0xf5, 0xf, 0x87, 0x92, 0xe2,
55 0x84, 0x1, 0xf9, 0x12, 0xf, 0x14, 0x15, 0x24, 0xce, 0x89,
56 0x99, 0xee, 0xb9, 0xc4, 0x17, 0x70, 0x70, 0x15, 0xea, 0xbe,
57 0xc6, 0x6c, 0x1f, 0x62, 0xb3, 0xf4, 0x2d, 0x16, 0x87, 0xfb,
58 0x56, 0x1e, 0x45, 0xab, 0xae, 0x32, 0xe4, 0x5e, 0x91, 0xed,
59 0x53, 0x66, 0x5e, 0xbd, 0xed, 0xad, 0xe6, 0x12, 0x39, 0xd,
60 0x83, 0xc9, 0xe8, 0x6b, 0x6c, 0x2d, 0xa5, 0xee, 0xc4, 0x5a,
61 0x66, 0xae, 0x8c, 0x97, 0xd7, 0xd, 0x6c, 0x49, 0xc7, 0xf5,
62 0xc4, 0x92, 0x31, 0x8b, 0x9, 0xee, 0x33, 0xda, 0xa9, 0x37,
63 0xb6, 0x49, 0x18, 0xf8, 0xe, 0x60, 0x45, 0xc8, 0x33, 0x91,
64 0xef, 0x20, 0x57, 0x10, 0xbe, 0x78, 0x2d, 0x83, 0x26, 0xd6,
65 0xca, 0x61, 0xf9, 0x2f, 0xe0, 0xbf, 0x5, 0x30, 0x52, 0x5a,
66 0x12, 0x1c, 0x0, 0xa7, 0x5d, 0xcc, 0x7c, 0x2e, 0xc5, 0x95,
67 0x8b, 0xa3, 0x3b, 0xf0, 0x43, 0x2e, 0x5e, 0xdd, 0x0, 0xdb,
68 0xd, 0xb3, 0x37, 0x99, 0xa9, 0xcd, 0x9c, 0xb7, 0x43, 0xf7,
69 0x35, 0x44, 0x21, 0xc2, 0x82, 0x71, 0xab, 0x8d, 0xaa, 0xb4,
70 0x41, 0x11, 0xec, 0x1e, 0x8d, 0xfc, 0x14, 0x82, 0x92, 0x4e,
71 0x83, 0x6a, 0xa, 0x6b, 0x35, 0x5e, 0x5d, 0xe9, 0x5c, 0xcc,
72 0x8c, 0xde, 0x39, 0xd1, 0x4a, 0x5b, 0x5f, 0x63, 0xa9, 0x64,
73 0xe0, 0xa, 0xcb, 0xb, 0xb8, 0x5a, 0x7c, 0xc3, 0xb, 0xe6,
74 0xbe, 0xfe, 0x8b, 0xf, 0x7d, 0x34, 0x8e, 0x2, 0x66, 0x74,
75 0x1, 0x6c, 0xca, 0x76, 0xac, 0x7c, 0x67, 0x8, 0x2f, 0x3f,
76 0x1a, 0xa6, 0x2c, 0x60, 0xb3, 0xff, 0xda, 0x8d, 0xb8, 0x12,
77 0xc, 0x0, 0x7f, 0xcc, 0x50, 0xa1, 0x5c, 0x64, 0xa1, 0xe2,
78 0x5f, 0x32, 0x65, 0xc9, 0x9c, 0xbe, 0xd6, 0xa, 0x13, 0x87,
79 0x3c, 0x2a, 0x45, 0x47, 0xc, 0xca, 0x42, 0x82, 0xfa, 0x89,
80 0x65, 0xe7, 0x89, 0xb4, 0x8f, 0xf7, 0x1e, 0xe6, 0x23, 0xa5,
81 0xd0, 0x59, 0x37, 0x79, 0x92, 0xd7, 0xce, 0x3d, 0xfd, 0xe3,
82 0xa1, 0xb, 0xcf, 0x6c, 0x85, 0xa0, 0x65, 0xf3, 0x5c, 0xc6,
83 0x4a, 0x63, 0x5f, 0x6e, 0x3a, 0x3a, 0x2a, 0x8b, 0x6a, 0xb6,
84 0x2f, 0xbb, 0xf8, 0xb2, 0x4b, 0x62, 0xbc, 0x1a, 0x91, 0x25,
85 0x66, 0xe3, 0x69, 0xca, 0x60, 0x49, 0xb, 0xf6, 0x8a, 0xbe,
86 0x3e, 0x76, 0x53, 0xc2, 0x7a, 0xa8, 0x4, 0x17, 0x75, 0xf1,
87 0xf3, 0x3, 0x62, 0x1b, 0x85, 0xb2, 0xb0, 0xef, 0x80, 0x15,
88 0xb6, 0xd4, 0x4e, 0xdf, 0x71, 0xac, 0xdb, 0x2a, 0x4, 0xd4,
89 0xb4, 0x21, 0xba, 0x65, 0x56, 0x57, 0xe8, 0xfa, 0x84, 0xa2,
90 0x7d, 0x13, 0xe, 0xaf, 0xd7, 0x9a, 0x58, 0x2a, 0xa3, 0x81,
91 0x84, 0x8d, 0x9, 0xa0, 0x6a, 0xc1, 0xbb, 0xd9, 0xf5, 0x86,
92 0xac, 0xbd, 0x75, 0x61, 0x9, 0xe6, 0x8c, 0x3d, 0x77, 0xb2,
93 0xed, 0x30, 0x20, 0xe4, 0x0, 0x1d, 0x97, 0xe8, 0xbf, 0xc7,
94 0x0, 0x1b, 0x21, 0xb1, 0x16, 0xe7, 0x41, 0x67, 0x2e, 0xec,
95 0x38, 0xbc, 0xe5, 0x1b, 0xb4, 0x6, 0x23, 0x31, 0x71, 0x1c,
96 0x49, 0xcd, 0x76, 0x4a, 0x76, 0x36, 0x8d, 0xa3, 0x89, 0x8b,
97 0x4a, 0x7a, 0xf4, 0x87, 0xc8, 0x15, 0xf, 0x37, 0x39, 0xf6,
98 0x6d, 0x80, 0x19, 0xef, 0x5c, 0xa8, 0x66, 0xce, 0x1b, 0x16,
99 0x79, 0x21, 0xdf, 0xd7, 0x31, 0x30, 0xc4, 0x21, 0xdd, 0x34,
100 0x5b, 0xd2, 0x1a, 0x2b, 0x3e, 0x5d, 0xf7, 0xea, 0xca, 0x5,
101 0x8e, 0xb7, 0xcb, 0x49, 0x2e, 0xa0, 0xe3, 0xf4, 0xa7, 0x48,
102 0x19, 0x10, 0x9c, 0x4, 0xa7, 0xf4, 0x28, 0x74, 0xc8, 0x6f,
103 0x63, 0x20, 0x2b, 0x46, 0x24, 0x26, 0x19, 0x1d, 0xd1, 0x2c,
104 0x31, 0x6d, 0x5a, 0x29, 0xa2, 0x6, 0xa6, 0xb2, 0x41, 0xcc,
105 0xa, 0x27, 0x96, 0x9, 0x96, 0xac, 0x47, 0x65, 0x78, 0x68,
106 0x51, 0x98, 0xd6, 0xd8, 0xa6, 0x2d, 0xa0, 0xcf, 0xec, 0xe2,
107 0x74, 0xf2, 0x82, 0xe3, 0x97, 0xd9, 0x7e, 0xd4, 0xf8, 0xb,
108 0x70, 0x43, 0x3d, 0xb1, 0x7b, 0x97, 0x80, 0xd6, 0xcb, 0xd7,
109 0x19, 0xbc, 0x63, 0xb, 0xfd, 0x4d, 0x88, 0xfe, 0x67, 0xac,
110 0xb8, 0xcc, 0x50, 0xb7, 0x68, 0xb3, 0x5b, 0xd6, 0x1e, 0x25,
111 0xfc, 0x5f, 0x3c, 0x8d, 0xb1, 0x33, 0x7c, 0xb3, 0x49, 0x1,
112 0x3f, 0x71, 0x55, 0xe, 0x51, 0xba, 0x61, 0x26, 0xfa, 0xea,
113 0xe5, 0xb5, 0xe8, 0xaa, 0xcf, 0xcd, 0x96, 0x9f, 0xd6, 0xc1,
114 0x5f, 0x53, 0x91, 0xad, 0x5, 0xde, 0x20, 0xe7, 0x51, 0xda,
115 0x5b, 0x95, 0x67, 0xed, 0xf4, 0xee, 0x42, 0x65, 0x70, 0x13,
116 0xb, 0x70, 0x14, 0x1c, 0xc9, 0xe0, 0x19, 0xca, 0x5f, 0xf5,
117 0x1d, 0x70, 0x4b, 0x6c, 0x6, 0x74, 0xec, 0xb5, 0x2e, 0x77,
118 0xe1, 0x74, 0xa1, 0xa3, 0x99, 0xa0, 0x85, 0x9e, 0xf1, 0xac,
119 0xd8, 0x7e,
120};
121
Igor Opaniukfc7ef0f2024-02-09 20:20:43 +0100122const char *str_avb_io_error(AvbIOResult res)
123{
124 switch (res) {
125 case AVB_IO_RESULT_OK:
126 return "Requested operation was successful";
127 case AVB_IO_RESULT_ERROR_IO:
128 return "Underlying hardware encountered an I/O error";
129 case AVB_IO_RESULT_ERROR_OOM:
130 return "Unable to allocate memory";
131 case AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION:
132 return "Requested partition does not exist";
133 case AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION:
134 return "Bytes requested is outside the range of partition";
135 case AVB_IO_RESULT_ERROR_NO_SUCH_VALUE:
136 return "Named persistent value does not exist";
137 case AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE:
138 return "Named persistent value size is not supported";
139 case AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE:
140 return "Buffer is too small for the requested operation";
141 default:
142 return "Unknown AVB error";
143 }
144}
145
146const char *str_avb_slot_error(AvbSlotVerifyResult res)
147{
148 switch (res) {
149 case AVB_SLOT_VERIFY_RESULT_OK:
150 return "Verification passed successfully";
151 case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
152 return "Allocation of memory failed";
153 case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
154 return "I/O error occurred while trying to load data";
155 case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
156 return "Digest didn't match or signature checks failed";
157 case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
158 return "Rollback index is less than its stored value";
159 case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
160 return "Public keys are not accepted";
161 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
162 return "Metadata is invalid or inconsistent";
163 case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
164 return "Metadata requires a newer version of libavb";
165 case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
166 return "Invalid arguments are used";
167 default:
168 return "Unknown AVB slot verification error";
169 }
170}
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300171/**
172 * ============================================================================
Igor Opaniuk5d4fd872018-06-03 21:56:40 +0300173 * Boot states support (GREEN, YELLOW, ORANGE, RED) and dm_verity
174 * ============================================================================
175 */
176char *avb_set_state(AvbOps *ops, enum avb_boot_state boot_state)
177{
178 struct AvbOpsData *data;
179 char *cmdline = NULL;
180
181 if (!ops)
182 return NULL;
183
184 data = (struct AvbOpsData *)ops->user_data;
185 if (!data)
186 return NULL;
187
188 data->boot_state = boot_state;
189 switch (boot_state) {
190 case AVB_GREEN:
191 cmdline = "androidboot.verifiedbootstate=green";
192 break;
193 case AVB_YELLOW:
194 cmdline = "androidboot.verifiedbootstate=yellow";
195 break;
196 case AVB_ORANGE:
197 cmdline = "androidboot.verifiedbootstate=orange";
198 case AVB_RED:
199 break;
200 }
201
202 return cmdline;
203}
204
205char *append_cmd_line(char *cmdline_orig, char *cmdline_new)
206{
207 char *cmd_line;
208
209 if (!cmdline_new)
210 return cmdline_orig;
211
212 if (cmdline_orig)
213 cmd_line = cmdline_orig;
214 else
215 cmd_line = " ";
216
217 cmd_line = avb_strdupv(cmd_line, " ", cmdline_new, NULL);
218
219 return cmd_line;
220}
221
222static int avb_find_dm_args(char **args, char *str)
223{
224 int i;
225
226 if (!str)
227 return -1;
228
Eugeniu Rosca2e2067b2018-08-14 02:43:04 +0200229 for (i = 0; i < AVB_MAX_ARGS && args[i]; ++i) {
Igor Opaniuk5d4fd872018-06-03 21:56:40 +0300230 if (strstr(args[i], str))
231 return i;
232 }
233
234 return -1;
235}
236
237static char *avb_set_enforce_option(const char *cmdline, const char *option)
238{
239 char *cmdarg[AVB_MAX_ARGS];
240 char *newargs = NULL;
241 int i = 0;
242 int total_args;
243
244 memset(cmdarg, 0, sizeof(cmdarg));
245 cmdarg[i++] = strtok((char *)cmdline, " ");
246
247 do {
248 cmdarg[i] = strtok(NULL, " ");
249 if (!cmdarg[i])
250 break;
251
252 if (++i >= AVB_MAX_ARGS) {
253 printf("%s: Can't handle more then %d args\n",
254 __func__, i);
255 return NULL;
256 }
257 } while (true);
258
259 total_args = i;
260 i = avb_find_dm_args(&cmdarg[0], VERITY_TABLE_OPT_LOGGING);
261 if (i >= 0) {
262 cmdarg[i] = (char *)option;
263 } else {
264 i = avb_find_dm_args(&cmdarg[0], VERITY_TABLE_OPT_RESTART);
265 if (i < 0) {
266 printf("%s: No verity options found\n", __func__);
267 return NULL;
268 }
269
270 cmdarg[i] = (char *)option;
271 }
272
273 for (i = 0; i <= total_args; i++)
274 newargs = append_cmd_line(newargs, cmdarg[i]);
275
276 return newargs;
277}
278
279char *avb_set_ignore_corruption(const char *cmdline)
280{
281 char *newargs = NULL;
282
283 newargs = avb_set_enforce_option(cmdline, VERITY_TABLE_OPT_LOGGING);
284 if (newargs)
285 newargs = append_cmd_line(newargs,
286 "androidboot.veritymode=eio");
287
288 return newargs;
289}
290
291char *avb_set_enforce_verity(const char *cmdline)
292{
293 char *newargs;
294
295 newargs = avb_set_enforce_option(cmdline, VERITY_TABLE_OPT_RESTART);
296 if (newargs)
297 newargs = append_cmd_line(newargs,
298 "androidboot.veritymode=enforcing");
299 return newargs;
300}
301
302/**
303 * ============================================================================
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300304 * IO(mmc) auxiliary functions
305 * ============================================================================
306 */
307static unsigned long mmc_read_and_flush(struct mmc_part *part,
308 lbaint_t start,
309 lbaint_t sectors,
310 void *buffer)
311{
312 unsigned long blks;
313 void *tmp_buf;
314 size_t buf_size;
315 bool unaligned = is_buf_unaligned(buffer);
316
317 if (start < part->info.start) {
318 printf("%s: partition start out of bounds\n", __func__);
319 return 0;
320 }
321 if ((start + sectors) > (part->info.start + part->info.size)) {
322 sectors = part->info.start + part->info.size - start;
323 printf("%s: read sector aligned to partition bounds (%ld)\n",
324 __func__, sectors);
325 }
326
327 /*
328 * Reading fails on unaligned buffers, so we have to
329 * use aligned temporary buffer and then copy to destination
330 */
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300331 if (unaligned) {
Igor Opaniuk0508a7c2024-02-09 20:20:41 +0100332 debug("%s: handling unaligned read buffer, addr = 0x%p\n",
333 __func__, buffer);
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300334 tmp_buf = get_sector_buf();
335 buf_size = get_sector_buf_size();
336 if (sectors > buf_size / part->info.blksz)
337 sectors = buf_size / part->info.blksz;
338 } else {
339 tmp_buf = buffer;
340 }
341
Igor Opaniuke9ee7392018-07-17 14:33:26 +0300342 blks = blk_dread(part->mmc_blk,
343 start, sectors, tmp_buf);
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300344 /* flush cache after read */
345 flush_cache((ulong)tmp_buf, sectors * part->info.blksz);
346
347 if (unaligned)
348 memcpy(buffer, tmp_buf, sectors * part->info.blksz);
349
350 return blks;
351}
352
353static unsigned long mmc_write(struct mmc_part *part, lbaint_t start,
354 lbaint_t sectors, void *buffer)
355{
356 void *tmp_buf;
357 size_t buf_size;
358 bool unaligned = is_buf_unaligned(buffer);
359
360 if (start < part->info.start) {
361 printf("%s: partition start out of bounds\n", __func__);
362 return 0;
363 }
364 if ((start + sectors) > (part->info.start + part->info.size)) {
365 sectors = part->info.start + part->info.size - start;
366 printf("%s: sector aligned to partition bounds (%ld)\n",
367 __func__, sectors);
368 }
369 if (unaligned) {
370 tmp_buf = get_sector_buf();
371 buf_size = get_sector_buf_size();
Igor Opaniuk0508a7c2024-02-09 20:20:41 +0100372 debug("%s: handling unaligned read buffer, addr = 0x%p\n",
373 __func__, buffer);
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300374 if (sectors > buf_size / part->info.blksz)
375 sectors = buf_size / part->info.blksz;
376
377 memcpy(tmp_buf, buffer, sectors * part->info.blksz);
378 } else {
379 tmp_buf = buffer;
380 }
381
Igor Opaniuke9ee7392018-07-17 14:33:26 +0300382 return blk_dwrite(part->mmc_blk,
383 start, sectors, tmp_buf);
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300384}
385
386static struct mmc_part *get_partition(AvbOps *ops, const char *partition)
387{
388 int ret;
389 u8 dev_num;
390 int part_num = 0;
391 struct mmc_part *part;
392 struct blk_desc *mmc_blk;
393
394 part = malloc(sizeof(struct mmc_part));
395 if (!part)
396 return NULL;
397
398 dev_num = get_boot_device(ops);
399 part->mmc = find_mmc_device(dev_num);
400 if (!part->mmc) {
Igor Opaniuk0508a7c2024-02-09 20:20:41 +0100401 printf("%s: no MMC device at slot %x\n", __func__, dev_num);
Eugeniu Rosca047bc5c2018-08-14 02:43:07 +0200402 goto err;
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300403 }
404
Igor Opaniuk0508a7c2024-02-09 20:20:41 +0100405 ret = mmc_init(part->mmc);
406 if (ret) {
407 printf("%s: MMC initialization failed, err = %d\n",
408 __func__, ret);
Eugeniu Rosca047bc5c2018-08-14 02:43:07 +0200409 goto err;
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300410 }
411
Igor Opaniukc2f72d02024-02-09 20:20:39 +0100412 if (IS_MMC(part->mmc)) {
413 ret = mmc_switch_part(part->mmc, part_num);
Igor Opaniuk0508a7c2024-02-09 20:20:41 +0100414 if (ret) {
415 printf("%s: MMC part switch failed, err = %d\n",
416 __func__, ret);
Igor Opaniukc2f72d02024-02-09 20:20:39 +0100417 goto err;
Igor Opaniuk0508a7c2024-02-09 20:20:41 +0100418 }
Igor Opaniukc2f72d02024-02-09 20:20:39 +0100419 }
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300420
421 mmc_blk = mmc_get_blk_desc(part->mmc);
422 if (!mmc_blk) {
Igor Opaniuk0508a7c2024-02-09 20:20:41 +0100423 printf("%s: failed to obtain block descriptor\n", __func__);
Eugeniu Rosca047bc5c2018-08-14 02:43:07 +0200424 goto err;
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300425 }
426
427 ret = part_get_info_by_name(mmc_blk, partition, &part->info);
schspa04534112021-02-26 00:19:10 +0800428 if (ret < 0) {
Igor Opaniuk0508a7c2024-02-09 20:20:41 +0100429 printf("%s: can't find partition '%s'\n", __func__, partition);
Eugeniu Rosca047bc5c2018-08-14 02:43:07 +0200430 goto err;
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300431 }
432
433 part->dev_num = dev_num;
434 part->mmc_blk = mmc_blk;
435
436 return part;
Eugeniu Rosca047bc5c2018-08-14 02:43:07 +0200437err:
438 free(part);
439 return NULL;
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300440}
441
442static AvbIOResult mmc_byte_io(AvbOps *ops,
443 const char *partition,
444 s64 offset,
445 size_t num_bytes,
446 void *buffer,
447 size_t *out_num_read,
448 enum mmc_io_type io_type)
449{
450 ulong ret;
451 struct mmc_part *part;
452 u64 start_offset, start_sector, sectors, residue;
453 u8 *tmp_buf;
454 size_t io_cnt = 0;
455
456 if (!partition || !buffer || io_type > IO_WRITE)
457 return AVB_IO_RESULT_ERROR_IO;
458
459 part = get_partition(ops, partition);
460 if (!part)
461 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
462
Eugeniu Roscae1904f42018-08-14 02:43:09 +0200463 if (!part->info.blksz)
464 return AVB_IO_RESULT_ERROR_IO;
465
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300466 start_offset = calc_offset(part, offset);
467 while (num_bytes) {
468 start_sector = start_offset / part->info.blksz;
469 sectors = num_bytes / part->info.blksz;
470 /* handle non block-aligned reads */
471 if (start_offset % part->info.blksz ||
472 num_bytes < part->info.blksz) {
473 tmp_buf = get_sector_buf();
474 if (start_offset % part->info.blksz) {
475 residue = part->info.blksz -
476 (start_offset % part->info.blksz);
477 if (residue > num_bytes)
478 residue = num_bytes;
479 } else {
480 residue = num_bytes;
481 }
482
483 if (io_type == IO_READ) {
484 ret = mmc_read_and_flush(part,
485 part->info.start +
486 start_sector,
487 1, tmp_buf);
488
489 if (ret != 1) {
490 printf("%s: read error (%ld, %lld)\n",
491 __func__, ret, start_sector);
492 return AVB_IO_RESULT_ERROR_IO;
493 }
494 /*
495 * if this is not aligned at sector start,
496 * we have to adjust the tmp buffer
497 */
498 tmp_buf += (start_offset % part->info.blksz);
499 memcpy(buffer, (void *)tmp_buf, residue);
500 } else {
501 ret = mmc_read_and_flush(part,
502 part->info.start +
503 start_sector,
504 1, tmp_buf);
505
506 if (ret != 1) {
507 printf("%s: read error (%ld, %lld)\n",
508 __func__, ret, start_sector);
509 return AVB_IO_RESULT_ERROR_IO;
510 }
511 memcpy((void *)tmp_buf +
512 start_offset % part->info.blksz,
513 buffer, residue);
514
515 ret = mmc_write(part, part->info.start +
516 start_sector, 1, tmp_buf);
517 if (ret != 1) {
518 printf("%s: write error (%ld, %lld)\n",
519 __func__, ret, start_sector);
520 return AVB_IO_RESULT_ERROR_IO;
521 }
522 }
523
524 io_cnt += residue;
525 buffer += residue;
526 start_offset += residue;
527 num_bytes -= residue;
528 continue;
529 }
530
531 if (sectors) {
532 if (io_type == IO_READ) {
533 ret = mmc_read_and_flush(part,
534 part->info.start +
535 start_sector,
536 sectors, buffer);
537 } else {
538 ret = mmc_write(part,
539 part->info.start +
540 start_sector,
541 sectors, buffer);
542 }
543
544 if (!ret) {
545 printf("%s: sector read error\n", __func__);
546 return AVB_IO_RESULT_ERROR_IO;
547 }
548
549 io_cnt += ret * part->info.blksz;
550 buffer += ret * part->info.blksz;
551 start_offset += ret * part->info.blksz;
552 num_bytes -= ret * part->info.blksz;
553 }
554 }
555
556 /* Set counter for read operation */
557 if (io_type == IO_READ && out_num_read)
558 *out_num_read = io_cnt;
559
560 return AVB_IO_RESULT_OK;
561}
562
563/**
564 * ============================================================================
565 * AVB 2.0 operations
566 * ============================================================================
567 */
568
569/**
570 * read_from_partition() - reads @num_bytes from @offset from partition
571 * identified by a string name
572 *
573 * @ops: contains AVB ops handlers
574 * @partition_name: partition name, NUL-terminated UTF-8 string
575 * @offset: offset from the beginning of partition
576 * @num_bytes: amount of bytes to read
577 * @buffer: destination buffer to store data
578 * @out_num_read:
579 *
580 * @return:
581 * AVB_IO_RESULT_OK, if partition was found and read operation succeed
582 * AVB_IO_RESULT_ERROR_IO, if i/o error occurred from the underlying i/o
583 * subsystem
584 * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if there is no partition with
585 * the given name
586 */
587static AvbIOResult read_from_partition(AvbOps *ops,
588 const char *partition_name,
589 s64 offset_from_partition,
590 size_t num_bytes,
591 void *buffer,
592 size_t *out_num_read)
593{
594 return mmc_byte_io(ops, partition_name, offset_from_partition,
595 num_bytes, buffer, out_num_read, IO_READ);
596}
597
598/**
599 * write_to_partition() - writes N bytes to a partition identified by a string
600 * name
601 *
602 * @ops: AvbOps, contains AVB ops handlers
603 * @partition_name: partition name
604 * @offset_from_partition: offset from the beginning of partition
605 * @num_bytes: amount of bytes to write
606 * @buf: data to write
607 * @out_num_read:
608 *
609 * @return:
610 * AVB_IO_RESULT_OK, if partition was found and read operation succeed
611 * AVB_IO_RESULT_ERROR_IO, if input/output error occurred
612 * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition, specified in
613 * @partition_name was not found
614 */
615static AvbIOResult write_to_partition(AvbOps *ops,
616 const char *partition_name,
617 s64 offset_from_partition,
618 size_t num_bytes,
619 const void *buffer)
620{
621 return mmc_byte_io(ops, partition_name, offset_from_partition,
622 num_bytes, (void *)buffer, NULL, IO_WRITE);
623}
624
625/**
626 * validate_vmbeta_public_key() - checks if the given public key used to sign
627 * the vbmeta partition is trusted
628 *
629 * @ops: AvbOps, contains AVB ops handlers
630 * @public_key_data: public key for verifying vbmeta partition signature
631 * @public_key_length: length of public key
632 * @public_key_metadata:
633 * @public_key_metadata_length:
634 * @out_key_is_trusted:
635 *
636 * @return:
637 * AVB_IO_RESULT_OK, if partition was found and read operation succeed
638 */
639static AvbIOResult validate_vbmeta_public_key(AvbOps *ops,
640 const u8 *public_key_data,
641 size_t public_key_length,
642 const u8
643 *public_key_metadata,
644 size_t
645 public_key_metadata_length,
646 bool *out_key_is_trusted)
647{
648 if (!public_key_length || !public_key_data || !out_key_is_trusted)
649 return AVB_IO_RESULT_ERROR_IO;
650
651 *out_key_is_trusted = false;
652 if (public_key_length != sizeof(avb_root_pub))
653 return AVB_IO_RESULT_ERROR_IO;
654
655 if (memcmp(avb_root_pub, public_key_data, public_key_length) == 0)
656 *out_key_is_trusted = true;
657
658 return AVB_IO_RESULT_OK;
659}
660
Jens Wiklander6663e072018-09-25 16:40:20 +0200661#ifdef CONFIG_OPTEE_TA_AVB
662static int get_open_session(struct AvbOpsData *ops_data)
663{
664 struct udevice *tee = NULL;
665
666 while (!ops_data->tee) {
667 const struct tee_optee_ta_uuid uuid = TA_AVB_UUID;
668 struct tee_open_session_arg arg;
669 int rc;
670
671 tee = tee_find_device(tee, NULL, NULL, NULL);
672 if (!tee)
673 return -ENODEV;
674
675 memset(&arg, 0, sizeof(arg));
676 tee_optee_ta_uuid_to_octets(arg.uuid, &uuid);
677 rc = tee_open_session(tee, &arg, 0, NULL);
Ivan Khoronzhuk3106e472023-01-27 22:02:14 +0200678 if (rc || arg.ret)
679 continue;
680
681 ops_data->tee = tee;
682 ops_data->session = arg.session;
Jens Wiklander6663e072018-09-25 16:40:20 +0200683 }
684
685 return 0;
686}
687
688static AvbIOResult invoke_func(struct AvbOpsData *ops_data, u32 func,
689 ulong num_param, struct tee_param *param)
690{
691 struct tee_invoke_arg arg;
692
693 if (get_open_session(ops_data))
694 return AVB_IO_RESULT_ERROR_IO;
695
696 memset(&arg, 0, sizeof(arg));
697 arg.func = func;
698 arg.session = ops_data->session;
699
700 if (tee_invoke_func(ops_data->tee, &arg, num_param, param))
701 return AVB_IO_RESULT_ERROR_IO;
702 switch (arg.ret) {
703 case TEE_SUCCESS:
704 return AVB_IO_RESULT_OK;
705 case TEE_ERROR_OUT_OF_MEMORY:
706 return AVB_IO_RESULT_ERROR_OOM;
Igor Opaniukfc1fe012019-04-09 15:38:14 +0200707 case TEE_ERROR_STORAGE_NO_SPACE:
708 return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE;
709 case TEE_ERROR_ITEM_NOT_FOUND:
710 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
Jens Wiklander6663e072018-09-25 16:40:20 +0200711 case TEE_ERROR_TARGET_DEAD:
712 /*
713 * The TA has paniced, close the session to reload the TA
714 * for the next request.
715 */
716 tee_close_session(ops_data->tee, ops_data->session);
717 ops_data->tee = NULL;
718 return AVB_IO_RESULT_ERROR_IO;
719 default:
720 return AVB_IO_RESULT_ERROR_IO;
721 }
722}
723#endif
724
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300725/**
726 * read_rollback_index() - gets the rollback index corresponding to the
727 * location of given by @out_rollback_index.
728 *
729 * @ops: contains AvbOps handlers
730 * @rollback_index_slot:
731 * @out_rollback_index: used to write a retrieved rollback index.
732 *
733 * @return
734 * AVB_IO_RESULT_OK, if the roolback index was retrieved
735 */
736static AvbIOResult read_rollback_index(AvbOps *ops,
737 size_t rollback_index_slot,
738 u64 *out_rollback_index)
739{
Jens Wiklander6663e072018-09-25 16:40:20 +0200740#ifndef CONFIG_OPTEE_TA_AVB
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300741 /* For now we always return 0 as the stored rollback index. */
Igor Opaniuk0508a7c2024-02-09 20:20:41 +0100742 debug("%s: rollback protection is not implemented\n", __func__);
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300743
744 if (out_rollback_index)
745 *out_rollback_index = 0;
746
747 return AVB_IO_RESULT_OK;
Jens Wiklander6663e072018-09-25 16:40:20 +0200748#else
749 AvbIOResult rc;
750 struct tee_param param[2];
751
752 if (rollback_index_slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS)
753 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
754
755 memset(param, 0, sizeof(param));
756 param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
757 param[0].u.value.a = rollback_index_slot;
758 param[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT;
759
760 rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_ROLLBACK_INDEX,
761 ARRAY_SIZE(param), param);
762 if (rc)
763 return rc;
764
765 *out_rollback_index = (u64)param[1].u.value.a << 32 |
766 (u32)param[1].u.value.b;
767 return AVB_IO_RESULT_OK;
768#endif
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300769}
770
771/**
772 * write_rollback_index() - sets the rollback index corresponding to the
773 * location of given by @out_rollback_index.
774 *
775 * @ops: contains AvbOps handlers
776 * @rollback_index_slot:
777 * @rollback_index: rollback index to write.
778 *
779 * @return
780 * AVB_IO_RESULT_OK, if the roolback index was retrieved
781 */
782static AvbIOResult write_rollback_index(AvbOps *ops,
783 size_t rollback_index_slot,
784 u64 rollback_index)
785{
Jens Wiklander6663e072018-09-25 16:40:20 +0200786#ifndef CONFIG_OPTEE_TA_AVB
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300787 /* For now this is a no-op. */
Igor Opaniuk0508a7c2024-02-09 20:20:41 +0100788 debug("%s: rollback protection is not implemented\n", __func__);
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300789
790 return AVB_IO_RESULT_OK;
Jens Wiklander6663e072018-09-25 16:40:20 +0200791#else
792 struct tee_param param[2];
793
794 if (rollback_index_slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS)
795 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
796
797 memset(param, 0, sizeof(param));
798 param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
799 param[0].u.value.a = rollback_index_slot;
800 param[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
801 param[1].u.value.a = (u32)(rollback_index >> 32);
802 param[1].u.value.b = (u32)rollback_index;
803
804 return invoke_func(ops->user_data, TA_AVB_CMD_WRITE_ROLLBACK_INDEX,
805 ARRAY_SIZE(param), param);
806#endif
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300807}
808
809/**
810 * read_is_device_unlocked() - gets whether the device is unlocked
811 *
812 * @ops: contains AVB ops handlers
813 * @out_is_unlocked: device unlock state is stored here, true if unlocked,
814 * false otherwise
815 *
816 * @return:
817 * AVB_IO_RESULT_OK: state is retrieved successfully
818 * AVB_IO_RESULT_ERROR_IO: an error occurred
819 */
820static AvbIOResult read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked)
821{
Jens Wiklander6663e072018-09-25 16:40:20 +0200822#ifndef CONFIG_OPTEE_TA_AVB
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300823 /* For now we always return that the device is unlocked. */
Igor Opaniuk0508a7c2024-02-09 20:20:41 +0100824 debug("%s: device locking is not implemented\n", __func__);
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300825
826 *out_is_unlocked = true;
827
828 return AVB_IO_RESULT_OK;
Jens Wiklander6663e072018-09-25 16:40:20 +0200829#else
830 AvbIOResult rc;
831 struct tee_param param = { .attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT };
832
833 rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_LOCK_STATE, 1, &param);
834 if (rc)
835 return rc;
836 *out_is_unlocked = !param.u.value.a;
837 return AVB_IO_RESULT_OK;
838#endif
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300839}
840
841/**
842 * get_unique_guid_for_partition() - gets the GUID for a partition identified
843 * by a string name
844 *
845 * @ops: contains AVB ops handlers
846 * @partition: partition name (NUL-terminated UTF-8 string)
847 * @guid_buf: buf, used to copy in GUID string. Example of value:
848 * 527c1c6d-6361-4593-8842-3c78fcd39219
849 * @guid_buf_size: @guid_buf buffer size
850 *
851 * @return:
852 * AVB_IO_RESULT_OK, on success (GUID found)
853 * AVB_IO_RESULT_ERROR_IO, if incorrect buffer size (@guid_buf_size) was
854 * provided
855 * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition was not found
856 */
857static AvbIOResult get_unique_guid_for_partition(AvbOps *ops,
858 const char *partition,
859 char *guid_buf,
860 size_t guid_buf_size)
861{
862 struct mmc_part *part;
863 size_t uuid_size;
864
865 part = get_partition(ops, partition);
866 if (!part)
867 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
868
869 uuid_size = sizeof(part->info.uuid);
870 if (uuid_size > guid_buf_size)
871 return AVB_IO_RESULT_ERROR_IO;
872
873 memcpy(guid_buf, part->info.uuid, uuid_size);
874 guid_buf[uuid_size - 1] = 0;
875
876 return AVB_IO_RESULT_OK;
877}
878
879/**
Igor Opaniuk7a5fbfe2018-08-10 16:59:59 +0300880 * get_size_of_partition() - gets the size of a partition identified
881 * by a string name
882 *
883 * @ops: contains AVB ops handlers
884 * @partition: partition name (NUL-terminated UTF-8 string)
885 * @out_size_num_bytes: returns the value of a partition size
886 *
887 * @return:
888 * AVB_IO_RESULT_OK, on success (GUID found)
889 * AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE, out_size_num_bytes is NULL
890 * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition was not found
891 */
892static AvbIOResult get_size_of_partition(AvbOps *ops,
893 const char *partition,
894 u64 *out_size_num_bytes)
895{
896 struct mmc_part *part;
897
898 if (!out_size_num_bytes)
899 return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE;
900
901 part = get_partition(ops, partition);
902 if (!part)
903 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
904
905 *out_size_num_bytes = part->info.blksz * part->info.size;
906
907 return AVB_IO_RESULT_OK;
908}
909
Sam Protsenkof254bd02019-07-31 19:59:08 +0300910#ifdef CONFIG_OPTEE_TA_AVB
Igor Opaniukfc1fe012019-04-09 15:38:14 +0200911static AvbIOResult read_persistent_value(AvbOps *ops,
912 const char *name,
913 size_t buffer_size,
914 u8 *out_buffer,
915 size_t *out_num_bytes_read)
916{
917 AvbIOResult rc;
918 struct tee_shm *shm_name;
919 struct tee_shm *shm_buf;
920 struct tee_param param[2];
921 struct udevice *tee;
922 size_t name_size = strlen(name) + 1;
923
924 if (get_open_session(ops->user_data))
925 return AVB_IO_RESULT_ERROR_IO;
926
927 tee = ((struct AvbOpsData *)ops->user_data)->tee;
928
929 rc = tee_shm_alloc(tee, name_size,
930 TEE_SHM_ALLOC, &shm_name);
931 if (rc)
932 return AVB_IO_RESULT_ERROR_OOM;
933
934 rc = tee_shm_alloc(tee, buffer_size,
935 TEE_SHM_ALLOC, &shm_buf);
936 if (rc) {
937 rc = AVB_IO_RESULT_ERROR_OOM;
938 goto free_name;
939 }
940
941 memcpy(shm_name->addr, name, name_size);
942
943 memset(param, 0, sizeof(param));
944 param[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
945 param[0].u.memref.shm = shm_name;
946 param[0].u.memref.size = name_size;
947 param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INOUT;
948 param[1].u.memref.shm = shm_buf;
949 param[1].u.memref.size = buffer_size;
950
951 rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_PERSIST_VALUE,
952 2, param);
953 if (rc)
954 goto out;
955
956 if (param[1].u.memref.size > buffer_size) {
957 rc = AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
958 goto out;
959 }
960
961 *out_num_bytes_read = param[1].u.memref.size;
962
963 memcpy(out_buffer, shm_buf->addr, *out_num_bytes_read);
964
965out:
966 tee_shm_free(shm_buf);
967free_name:
968 tee_shm_free(shm_name);
969
970 return rc;
971}
972
973static AvbIOResult write_persistent_value(AvbOps *ops,
974 const char *name,
975 size_t value_size,
976 const u8 *value)
977{
978 AvbIOResult rc;
979 struct tee_shm *shm_name;
980 struct tee_shm *shm_buf;
981 struct tee_param param[2];
982 struct udevice *tee;
983 size_t name_size = strlen(name) + 1;
984
985 if (get_open_session(ops->user_data))
986 return AVB_IO_RESULT_ERROR_IO;
987
988 tee = ((struct AvbOpsData *)ops->user_data)->tee;
989
990 if (!value_size)
991 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
992
993 rc = tee_shm_alloc(tee, name_size,
994 TEE_SHM_ALLOC, &shm_name);
995 if (rc)
996 return AVB_IO_RESULT_ERROR_OOM;
997
998 rc = tee_shm_alloc(tee, value_size,
999 TEE_SHM_ALLOC, &shm_buf);
1000 if (rc) {
1001 rc = AVB_IO_RESULT_ERROR_OOM;
1002 goto free_name;
1003 }
1004
1005 memcpy(shm_name->addr, name, name_size);
1006 memcpy(shm_buf->addr, value, value_size);
1007
1008 memset(param, 0, sizeof(param));
1009 param[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
1010 param[0].u.memref.shm = shm_name;
1011 param[0].u.memref.size = name_size;
1012 param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
1013 param[1].u.memref.shm = shm_buf;
1014 param[1].u.memref.size = value_size;
1015
1016 rc = invoke_func(ops->user_data, TA_AVB_CMD_WRITE_PERSIST_VALUE,
1017 2, param);
1018 if (rc)
1019 goto out;
1020
1021out:
1022 tee_shm_free(shm_buf);
1023free_name:
1024 tee_shm_free(shm_name);
1025
1026 return rc;
1027}
Sam Protsenkof254bd02019-07-31 19:59:08 +03001028#endif
1029
Igor Opaniuk7a5fbfe2018-08-10 16:59:59 +03001030/**
Igor Opaniuk3af30e42018-06-03 21:56:38 +03001031 * ============================================================================
1032 * AVB2.0 AvbOps alloc/initialisation/free
1033 * ============================================================================
1034 */
1035AvbOps *avb_ops_alloc(int boot_device)
1036{
1037 struct AvbOpsData *ops_data;
1038
1039 ops_data = avb_calloc(sizeof(struct AvbOpsData));
1040 if (!ops_data)
1041 return NULL;
1042
1043 ops_data->ops.user_data = ops_data;
1044
1045 ops_data->ops.read_from_partition = read_from_partition;
1046 ops_data->ops.write_to_partition = write_to_partition;
1047 ops_data->ops.validate_vbmeta_public_key = validate_vbmeta_public_key;
1048 ops_data->ops.read_rollback_index = read_rollback_index;
1049 ops_data->ops.write_rollback_index = write_rollback_index;
1050 ops_data->ops.read_is_device_unlocked = read_is_device_unlocked;
1051 ops_data->ops.get_unique_guid_for_partition =
1052 get_unique_guid_for_partition;
Igor Opaniukfc1fe012019-04-09 15:38:14 +02001053#ifdef CONFIG_OPTEE_TA_AVB
1054 ops_data->ops.write_persistent_value = write_persistent_value;
1055 ops_data->ops.read_persistent_value = read_persistent_value;
1056#endif
Igor Opaniuk7a5fbfe2018-08-10 16:59:59 +03001057 ops_data->ops.get_size_of_partition = get_size_of_partition;
Igor Opaniuk3af30e42018-06-03 21:56:38 +03001058 ops_data->mmc_dev = boot_device;
1059
1060 return &ops_data->ops;
1061}
1062
1063void avb_ops_free(AvbOps *ops)
1064{
1065 struct AvbOpsData *ops_data;
1066
Eugeniu Rosca47e41632018-08-14 02:43:08 +02001067 if (!ops)
Igor Opaniuk3af30e42018-06-03 21:56:38 +03001068 return;
1069
1070 ops_data = ops->user_data;
1071
Jens Wiklander6663e072018-09-25 16:40:20 +02001072 if (ops_data) {
1073#ifdef CONFIG_OPTEE_TA_AVB
1074 if (ops_data->tee)
1075 tee_close_session(ops_data->tee, ops_data->session);
1076#endif
Igor Opaniuk3af30e42018-06-03 21:56:38 +03001077 avb_free(ops_data);
Jens Wiklander6663e072018-09-25 16:40:20 +02001078 }
Igor Opaniuk3af30e42018-06-03 21:56:38 +03001079}