blob: 0bc1c2369fac419372595a97462c14d052542a30 [file] [log] [blame]
Igor Opaniuk3af30e42018-06-03 21:56:38 +03001/*
2 * (C) Copyright 2018, Linaro Limited
3 *
4 * SPDX-License-Identifier: GPL-2.0+
5 */
6
7#include <avb_verify.h>
Igor Opaniuke9ee7392018-07-17 14:33:26 +03008#include <blk.h>
Igor Opaniuk3af30e42018-06-03 21:56:38 +03009#include <fastboot.h>
10#include <image.h>
11#include <malloc.h>
12#include <part.h>
13
Eugeniu Rosca55d56d22018-08-14 02:43:06 +020014static const unsigned char avb_root_pub[1032] = {
Igor Opaniuk3af30e42018-06-03 21:56:38 +030015 0x0, 0x0, 0x10, 0x0, 0x55, 0xd9, 0x4, 0xad, 0xd8, 0x4,
16 0xaf, 0xe3, 0xd3, 0x84, 0x6c, 0x7e, 0xd, 0x89, 0x3d, 0xc2,
17 0x8c, 0xd3, 0x12, 0x55, 0xe9, 0x62, 0xc9, 0xf1, 0xf, 0x5e,
18 0xcc, 0x16, 0x72, 0xab, 0x44, 0x7c, 0x2c, 0x65, 0x4a, 0x94,
19 0xb5, 0x16, 0x2b, 0x0, 0xbb, 0x6, 0xef, 0x13, 0x7, 0x53,
20 0x4c, 0xf9, 0x64, 0xb9, 0x28, 0x7a, 0x1b, 0x84, 0x98, 0x88,
21 0xd8, 0x67, 0xa4, 0x23, 0xf9, 0xa7, 0x4b, 0xdc, 0x4a, 0xf,
22 0xf7, 0x3a, 0x18, 0xae, 0x54, 0xa8, 0x15, 0xfe, 0xb0, 0xad,
23 0xac, 0x35, 0xda, 0x3b, 0xad, 0x27, 0xbc, 0xaf, 0xe8, 0xd3,
24 0x2f, 0x37, 0x34, 0xd6, 0x51, 0x2b, 0x6c, 0x5a, 0x27, 0xd7,
25 0x96, 0x6, 0xaf, 0x6b, 0xb8, 0x80, 0xca, 0xfa, 0x30, 0xb4,
26 0xb1, 0x85, 0xb3, 0x4d, 0xaa, 0xaa, 0xc3, 0x16, 0x34, 0x1a,
27 0xb8, 0xe7, 0xc7, 0xfa, 0xf9, 0x9, 0x77, 0xab, 0x97, 0x93,
28 0xeb, 0x44, 0xae, 0xcf, 0x20, 0xbc, 0xf0, 0x80, 0x11, 0xdb,
29 0x23, 0xc, 0x47, 0x71, 0xb9, 0x6d, 0xd6, 0x7b, 0x60, 0x47,
30 0x87, 0x16, 0x56, 0x93, 0xb7, 0xc2, 0x2a, 0x9a, 0xb0, 0x4c,
31 0x1, 0xc, 0x30, 0xd8, 0x93, 0x87, 0xf0, 0xed, 0x6e, 0x8b,
32 0xbe, 0x30, 0x5b, 0xf6, 0xa6, 0xaf, 0xdd, 0x80, 0x7c, 0x45,
33 0x5e, 0x8f, 0x91, 0x93, 0x5e, 0x44, 0xfe, 0xb8, 0x82, 0x7,
34 0xee, 0x79, 0xca, 0xbf, 0x31, 0x73, 0x62, 0x58, 0xe3, 0xcd,
35 0xc4, 0xbc, 0xc2, 0x11, 0x1d, 0xa1, 0x4a, 0xbf, 0xfe, 0x27,
36 0x7d, 0xa1, 0xf6, 0x35, 0xa3, 0x5e, 0xca, 0xdc, 0x57, 0x2f,
37 0x3e, 0xf0, 0xc9, 0x5d, 0x86, 0x6a, 0xf8, 0xaf, 0x66, 0xa7,
38 0xed, 0xcd, 0xb8, 0xed, 0xa1, 0x5f, 0xba, 0x9b, 0x85, 0x1a,
39 0xd5, 0x9, 0xae, 0x94, 0x4e, 0x3b, 0xcf, 0xcb, 0x5c, 0xc9,
40 0x79, 0x80, 0xf7, 0xcc, 0xa6, 0x4a, 0xa8, 0x6a, 0xd8, 0xd3,
41 0x31, 0x11, 0xf9, 0xf6, 0x2, 0x63, 0x2a, 0x1a, 0x2d, 0xd1,
42 0x1a, 0x66, 0x1b, 0x16, 0x41, 0xbd, 0xbd, 0xf7, 0x4d, 0xc0,
43 0x4a, 0xe5, 0x27, 0x49, 0x5f, 0x7f, 0x58, 0xe3, 0x27, 0x2d,
44 0xe5, 0xc9, 0x66, 0xe, 0x52, 0x38, 0x16, 0x38, 0xfb, 0x16,
45 0xeb, 0x53, 0x3f, 0xe6, 0xfd, 0xe9, 0xa2, 0x5e, 0x25, 0x59,
46 0xd8, 0x79, 0x45, 0xff, 0x3, 0x4c, 0x26, 0xa2, 0x0, 0x5a,
47 0x8e, 0xc2, 0x51, 0xa1, 0x15, 0xf9, 0x7b, 0xf4, 0x5c, 0x81,
48 0x9b, 0x18, 0x47, 0x35, 0xd8, 0x2d, 0x5, 0xe9, 0xad, 0xf,
49 0x35, 0x74, 0x15, 0xa3, 0x8e, 0x8b, 0xcc, 0x27, 0xda, 0x7c,
50 0x5d, 0xe4, 0xfa, 0x4, 0xd3, 0x5, 0xb, 0xba, 0x3a, 0xb2,
51 0x49, 0x45, 0x2f, 0x47, 0xc7, 0xd, 0x41, 0x3f, 0x97, 0x80,
52 0x4d, 0x3f, 0xc1, 0xb5, 0xbb, 0x70, 0x5f, 0xa7, 0x37, 0xaf,
53 0x48, 0x22, 0x12, 0x45, 0x2e, 0xf5, 0xf, 0x87, 0x92, 0xe2,
54 0x84, 0x1, 0xf9, 0x12, 0xf, 0x14, 0x15, 0x24, 0xce, 0x89,
55 0x99, 0xee, 0xb9, 0xc4, 0x17, 0x70, 0x70, 0x15, 0xea, 0xbe,
56 0xc6, 0x6c, 0x1f, 0x62, 0xb3, 0xf4, 0x2d, 0x16, 0x87, 0xfb,
57 0x56, 0x1e, 0x45, 0xab, 0xae, 0x32, 0xe4, 0x5e, 0x91, 0xed,
58 0x53, 0x66, 0x5e, 0xbd, 0xed, 0xad, 0xe6, 0x12, 0x39, 0xd,
59 0x83, 0xc9, 0xe8, 0x6b, 0x6c, 0x2d, 0xa5, 0xee, 0xc4, 0x5a,
60 0x66, 0xae, 0x8c, 0x97, 0xd7, 0xd, 0x6c, 0x49, 0xc7, 0xf5,
61 0xc4, 0x92, 0x31, 0x8b, 0x9, 0xee, 0x33, 0xda, 0xa9, 0x37,
62 0xb6, 0x49, 0x18, 0xf8, 0xe, 0x60, 0x45, 0xc8, 0x33, 0x91,
63 0xef, 0x20, 0x57, 0x10, 0xbe, 0x78, 0x2d, 0x83, 0x26, 0xd6,
64 0xca, 0x61, 0xf9, 0x2f, 0xe0, 0xbf, 0x5, 0x30, 0x52, 0x5a,
65 0x12, 0x1c, 0x0, 0xa7, 0x5d, 0xcc, 0x7c, 0x2e, 0xc5, 0x95,
66 0x8b, 0xa3, 0x3b, 0xf0, 0x43, 0x2e, 0x5e, 0xdd, 0x0, 0xdb,
67 0xd, 0xb3, 0x37, 0x99, 0xa9, 0xcd, 0x9c, 0xb7, 0x43, 0xf7,
68 0x35, 0x44, 0x21, 0xc2, 0x82, 0x71, 0xab, 0x8d, 0xaa, 0xb4,
69 0x41, 0x11, 0xec, 0x1e, 0x8d, 0xfc, 0x14, 0x82, 0x92, 0x4e,
70 0x83, 0x6a, 0xa, 0x6b, 0x35, 0x5e, 0x5d, 0xe9, 0x5c, 0xcc,
71 0x8c, 0xde, 0x39, 0xd1, 0x4a, 0x5b, 0x5f, 0x63, 0xa9, 0x64,
72 0xe0, 0xa, 0xcb, 0xb, 0xb8, 0x5a, 0x7c, 0xc3, 0xb, 0xe6,
73 0xbe, 0xfe, 0x8b, 0xf, 0x7d, 0x34, 0x8e, 0x2, 0x66, 0x74,
74 0x1, 0x6c, 0xca, 0x76, 0xac, 0x7c, 0x67, 0x8, 0x2f, 0x3f,
75 0x1a, 0xa6, 0x2c, 0x60, 0xb3, 0xff, 0xda, 0x8d, 0xb8, 0x12,
76 0xc, 0x0, 0x7f, 0xcc, 0x50, 0xa1, 0x5c, 0x64, 0xa1, 0xe2,
77 0x5f, 0x32, 0x65, 0xc9, 0x9c, 0xbe, 0xd6, 0xa, 0x13, 0x87,
78 0x3c, 0x2a, 0x45, 0x47, 0xc, 0xca, 0x42, 0x82, 0xfa, 0x89,
79 0x65, 0xe7, 0x89, 0xb4, 0x8f, 0xf7, 0x1e, 0xe6, 0x23, 0xa5,
80 0xd0, 0x59, 0x37, 0x79, 0x92, 0xd7, 0xce, 0x3d, 0xfd, 0xe3,
81 0xa1, 0xb, 0xcf, 0x6c, 0x85, 0xa0, 0x65, 0xf3, 0x5c, 0xc6,
82 0x4a, 0x63, 0x5f, 0x6e, 0x3a, 0x3a, 0x2a, 0x8b, 0x6a, 0xb6,
83 0x2f, 0xbb, 0xf8, 0xb2, 0x4b, 0x62, 0xbc, 0x1a, 0x91, 0x25,
84 0x66, 0xe3, 0x69, 0xca, 0x60, 0x49, 0xb, 0xf6, 0x8a, 0xbe,
85 0x3e, 0x76, 0x53, 0xc2, 0x7a, 0xa8, 0x4, 0x17, 0x75, 0xf1,
86 0xf3, 0x3, 0x62, 0x1b, 0x85, 0xb2, 0xb0, 0xef, 0x80, 0x15,
87 0xb6, 0xd4, 0x4e, 0xdf, 0x71, 0xac, 0xdb, 0x2a, 0x4, 0xd4,
88 0xb4, 0x21, 0xba, 0x65, 0x56, 0x57, 0xe8, 0xfa, 0x84, 0xa2,
89 0x7d, 0x13, 0xe, 0xaf, 0xd7, 0x9a, 0x58, 0x2a, 0xa3, 0x81,
90 0x84, 0x8d, 0x9, 0xa0, 0x6a, 0xc1, 0xbb, 0xd9, 0xf5, 0x86,
91 0xac, 0xbd, 0x75, 0x61, 0x9, 0xe6, 0x8c, 0x3d, 0x77, 0xb2,
92 0xed, 0x30, 0x20, 0xe4, 0x0, 0x1d, 0x97, 0xe8, 0xbf, 0xc7,
93 0x0, 0x1b, 0x21, 0xb1, 0x16, 0xe7, 0x41, 0x67, 0x2e, 0xec,
94 0x38, 0xbc, 0xe5, 0x1b, 0xb4, 0x6, 0x23, 0x31, 0x71, 0x1c,
95 0x49, 0xcd, 0x76, 0x4a, 0x76, 0x36, 0x8d, 0xa3, 0x89, 0x8b,
96 0x4a, 0x7a, 0xf4, 0x87, 0xc8, 0x15, 0xf, 0x37, 0x39, 0xf6,
97 0x6d, 0x80, 0x19, 0xef, 0x5c, 0xa8, 0x66, 0xce, 0x1b, 0x16,
98 0x79, 0x21, 0xdf, 0xd7, 0x31, 0x30, 0xc4, 0x21, 0xdd, 0x34,
99 0x5b, 0xd2, 0x1a, 0x2b, 0x3e, 0x5d, 0xf7, 0xea, 0xca, 0x5,
100 0x8e, 0xb7, 0xcb, 0x49, 0x2e, 0xa0, 0xe3, 0xf4, 0xa7, 0x48,
101 0x19, 0x10, 0x9c, 0x4, 0xa7, 0xf4, 0x28, 0x74, 0xc8, 0x6f,
102 0x63, 0x20, 0x2b, 0x46, 0x24, 0x26, 0x19, 0x1d, 0xd1, 0x2c,
103 0x31, 0x6d, 0x5a, 0x29, 0xa2, 0x6, 0xa6, 0xb2, 0x41, 0xcc,
104 0xa, 0x27, 0x96, 0x9, 0x96, 0xac, 0x47, 0x65, 0x78, 0x68,
105 0x51, 0x98, 0xd6, 0xd8, 0xa6, 0x2d, 0xa0, 0xcf, 0xec, 0xe2,
106 0x74, 0xf2, 0x82, 0xe3, 0x97, 0xd9, 0x7e, 0xd4, 0xf8, 0xb,
107 0x70, 0x43, 0x3d, 0xb1, 0x7b, 0x97, 0x80, 0xd6, 0xcb, 0xd7,
108 0x19, 0xbc, 0x63, 0xb, 0xfd, 0x4d, 0x88, 0xfe, 0x67, 0xac,
109 0xb8, 0xcc, 0x50, 0xb7, 0x68, 0xb3, 0x5b, 0xd6, 0x1e, 0x25,
110 0xfc, 0x5f, 0x3c, 0x8d, 0xb1, 0x33, 0x7c, 0xb3, 0x49, 0x1,
111 0x3f, 0x71, 0x55, 0xe, 0x51, 0xba, 0x61, 0x26, 0xfa, 0xea,
112 0xe5, 0xb5, 0xe8, 0xaa, 0xcf, 0xcd, 0x96, 0x9f, 0xd6, 0xc1,
113 0x5f, 0x53, 0x91, 0xad, 0x5, 0xde, 0x20, 0xe7, 0x51, 0xda,
114 0x5b, 0x95, 0x67, 0xed, 0xf4, 0xee, 0x42, 0x65, 0x70, 0x13,
115 0xb, 0x70, 0x14, 0x1c, 0xc9, 0xe0, 0x19, 0xca, 0x5f, 0xf5,
116 0x1d, 0x70, 0x4b, 0x6c, 0x6, 0x74, 0xec, 0xb5, 0x2e, 0x77,
117 0xe1, 0x74, 0xa1, 0xa3, 0x99, 0xa0, 0x85, 0x9e, 0xf1, 0xac,
118 0xd8, 0x7e,
119};
120
121/**
122 * ============================================================================
Igor Opaniuk5d4fd872018-06-03 21:56:40 +0300123 * Boot states support (GREEN, YELLOW, ORANGE, RED) and dm_verity
124 * ============================================================================
125 */
126char *avb_set_state(AvbOps *ops, enum avb_boot_state boot_state)
127{
128 struct AvbOpsData *data;
129 char *cmdline = NULL;
130
131 if (!ops)
132 return NULL;
133
134 data = (struct AvbOpsData *)ops->user_data;
135 if (!data)
136 return NULL;
137
138 data->boot_state = boot_state;
139 switch (boot_state) {
140 case AVB_GREEN:
141 cmdline = "androidboot.verifiedbootstate=green";
142 break;
143 case AVB_YELLOW:
144 cmdline = "androidboot.verifiedbootstate=yellow";
145 break;
146 case AVB_ORANGE:
147 cmdline = "androidboot.verifiedbootstate=orange";
148 case AVB_RED:
149 break;
150 }
151
152 return cmdline;
153}
154
155char *append_cmd_line(char *cmdline_orig, char *cmdline_new)
156{
157 char *cmd_line;
158
159 if (!cmdline_new)
160 return cmdline_orig;
161
162 if (cmdline_orig)
163 cmd_line = cmdline_orig;
164 else
165 cmd_line = " ";
166
167 cmd_line = avb_strdupv(cmd_line, " ", cmdline_new, NULL);
168
169 return cmd_line;
170}
171
172static int avb_find_dm_args(char **args, char *str)
173{
174 int i;
175
176 if (!str)
177 return -1;
178
Eugeniu Rosca2e2067b2018-08-14 02:43:04 +0200179 for (i = 0; i < AVB_MAX_ARGS && args[i]; ++i) {
Igor Opaniuk5d4fd872018-06-03 21:56:40 +0300180 if (strstr(args[i], str))
181 return i;
182 }
183
184 return -1;
185}
186
187static char *avb_set_enforce_option(const char *cmdline, const char *option)
188{
189 char *cmdarg[AVB_MAX_ARGS];
190 char *newargs = NULL;
191 int i = 0;
192 int total_args;
193
194 memset(cmdarg, 0, sizeof(cmdarg));
195 cmdarg[i++] = strtok((char *)cmdline, " ");
196
197 do {
198 cmdarg[i] = strtok(NULL, " ");
199 if (!cmdarg[i])
200 break;
201
202 if (++i >= AVB_MAX_ARGS) {
203 printf("%s: Can't handle more then %d args\n",
204 __func__, i);
205 return NULL;
206 }
207 } while (true);
208
209 total_args = i;
210 i = avb_find_dm_args(&cmdarg[0], VERITY_TABLE_OPT_LOGGING);
211 if (i >= 0) {
212 cmdarg[i] = (char *)option;
213 } else {
214 i = avb_find_dm_args(&cmdarg[0], VERITY_TABLE_OPT_RESTART);
215 if (i < 0) {
216 printf("%s: No verity options found\n", __func__);
217 return NULL;
218 }
219
220 cmdarg[i] = (char *)option;
221 }
222
223 for (i = 0; i <= total_args; i++)
224 newargs = append_cmd_line(newargs, cmdarg[i]);
225
226 return newargs;
227}
228
229char *avb_set_ignore_corruption(const char *cmdline)
230{
231 char *newargs = NULL;
232
233 newargs = avb_set_enforce_option(cmdline, VERITY_TABLE_OPT_LOGGING);
234 if (newargs)
235 newargs = append_cmd_line(newargs,
236 "androidboot.veritymode=eio");
237
238 return newargs;
239}
240
241char *avb_set_enforce_verity(const char *cmdline)
242{
243 char *newargs;
244
245 newargs = avb_set_enforce_option(cmdline, VERITY_TABLE_OPT_RESTART);
246 if (newargs)
247 newargs = append_cmd_line(newargs,
248 "androidboot.veritymode=enforcing");
249 return newargs;
250}
251
252/**
253 * ============================================================================
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300254 * IO(mmc) auxiliary functions
255 * ============================================================================
256 */
257static unsigned long mmc_read_and_flush(struct mmc_part *part,
258 lbaint_t start,
259 lbaint_t sectors,
260 void *buffer)
261{
262 unsigned long blks;
263 void *tmp_buf;
264 size_t buf_size;
265 bool unaligned = is_buf_unaligned(buffer);
266
267 if (start < part->info.start) {
268 printf("%s: partition start out of bounds\n", __func__);
269 return 0;
270 }
271 if ((start + sectors) > (part->info.start + part->info.size)) {
272 sectors = part->info.start + part->info.size - start;
273 printf("%s: read sector aligned to partition bounds (%ld)\n",
274 __func__, sectors);
275 }
276
277 /*
278 * Reading fails on unaligned buffers, so we have to
279 * use aligned temporary buffer and then copy to destination
280 */
281
282 if (unaligned) {
283 printf("Handling unaligned read buffer..\n");
284 tmp_buf = get_sector_buf();
285 buf_size = get_sector_buf_size();
286 if (sectors > buf_size / part->info.blksz)
287 sectors = buf_size / part->info.blksz;
288 } else {
289 tmp_buf = buffer;
290 }
291
Igor Opaniuke9ee7392018-07-17 14:33:26 +0300292 blks = blk_dread(part->mmc_blk,
293 start, sectors, tmp_buf);
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300294 /* flush cache after read */
295 flush_cache((ulong)tmp_buf, sectors * part->info.blksz);
296
297 if (unaligned)
298 memcpy(buffer, tmp_buf, sectors * part->info.blksz);
299
300 return blks;
301}
302
303static unsigned long mmc_write(struct mmc_part *part, lbaint_t start,
304 lbaint_t sectors, void *buffer)
305{
306 void *tmp_buf;
307 size_t buf_size;
308 bool unaligned = is_buf_unaligned(buffer);
309
310 if (start < part->info.start) {
311 printf("%s: partition start out of bounds\n", __func__);
312 return 0;
313 }
314 if ((start + sectors) > (part->info.start + part->info.size)) {
315 sectors = part->info.start + part->info.size - start;
316 printf("%s: sector aligned to partition bounds (%ld)\n",
317 __func__, sectors);
318 }
319 if (unaligned) {
320 tmp_buf = get_sector_buf();
321 buf_size = get_sector_buf_size();
322 printf("Handling unaligned wrire buffer..\n");
323 if (sectors > buf_size / part->info.blksz)
324 sectors = buf_size / part->info.blksz;
325
326 memcpy(tmp_buf, buffer, sectors * part->info.blksz);
327 } else {
328 tmp_buf = buffer;
329 }
330
Igor Opaniuke9ee7392018-07-17 14:33:26 +0300331 return blk_dwrite(part->mmc_blk,
332 start, sectors, tmp_buf);
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300333}
334
335static struct mmc_part *get_partition(AvbOps *ops, const char *partition)
336{
337 int ret;
338 u8 dev_num;
339 int part_num = 0;
340 struct mmc_part *part;
341 struct blk_desc *mmc_blk;
342
343 part = malloc(sizeof(struct mmc_part));
344 if (!part)
345 return NULL;
346
347 dev_num = get_boot_device(ops);
348 part->mmc = find_mmc_device(dev_num);
349 if (!part->mmc) {
350 printf("No MMC device at slot %x\n", dev_num);
Eugeniu Rosca047bc5c2018-08-14 02:43:07 +0200351 goto err;
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300352 }
353
354 if (mmc_init(part->mmc)) {
355 printf("MMC initialization failed\n");
Eugeniu Rosca047bc5c2018-08-14 02:43:07 +0200356 goto err;
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300357 }
358
359 ret = mmc_switch_part(part->mmc, part_num);
360 if (ret)
Eugeniu Rosca047bc5c2018-08-14 02:43:07 +0200361 goto err;
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300362
363 mmc_blk = mmc_get_blk_desc(part->mmc);
364 if (!mmc_blk) {
365 printf("Error - failed to obtain block descriptor\n");
Eugeniu Rosca047bc5c2018-08-14 02:43:07 +0200366 goto err;
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300367 }
368
369 ret = part_get_info_by_name(mmc_blk, partition, &part->info);
370 if (!ret) {
371 printf("Can't find partition '%s'\n", partition);
Eugeniu Rosca047bc5c2018-08-14 02:43:07 +0200372 goto err;
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300373 }
374
375 part->dev_num = dev_num;
376 part->mmc_blk = mmc_blk;
377
378 return part;
Eugeniu Rosca047bc5c2018-08-14 02:43:07 +0200379err:
380 free(part);
381 return NULL;
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300382}
383
384static AvbIOResult mmc_byte_io(AvbOps *ops,
385 const char *partition,
386 s64 offset,
387 size_t num_bytes,
388 void *buffer,
389 size_t *out_num_read,
390 enum mmc_io_type io_type)
391{
392 ulong ret;
393 struct mmc_part *part;
394 u64 start_offset, start_sector, sectors, residue;
395 u8 *tmp_buf;
396 size_t io_cnt = 0;
397
398 if (!partition || !buffer || io_type > IO_WRITE)
399 return AVB_IO_RESULT_ERROR_IO;
400
401 part = get_partition(ops, partition);
402 if (!part)
403 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
404
405 start_offset = calc_offset(part, offset);
406 while (num_bytes) {
407 start_sector = start_offset / part->info.blksz;
408 sectors = num_bytes / part->info.blksz;
409 /* handle non block-aligned reads */
410 if (start_offset % part->info.blksz ||
411 num_bytes < part->info.blksz) {
412 tmp_buf = get_sector_buf();
413 if (start_offset % part->info.blksz) {
414 residue = part->info.blksz -
415 (start_offset % part->info.blksz);
416 if (residue > num_bytes)
417 residue = num_bytes;
418 } else {
419 residue = num_bytes;
420 }
421
422 if (io_type == IO_READ) {
423 ret = mmc_read_and_flush(part,
424 part->info.start +
425 start_sector,
426 1, tmp_buf);
427
428 if (ret != 1) {
429 printf("%s: read error (%ld, %lld)\n",
430 __func__, ret, start_sector);
431 return AVB_IO_RESULT_ERROR_IO;
432 }
433 /*
434 * if this is not aligned at sector start,
435 * we have to adjust the tmp buffer
436 */
437 tmp_buf += (start_offset % part->info.blksz);
438 memcpy(buffer, (void *)tmp_buf, residue);
439 } else {
440 ret = mmc_read_and_flush(part,
441 part->info.start +
442 start_sector,
443 1, tmp_buf);
444
445 if (ret != 1) {
446 printf("%s: read error (%ld, %lld)\n",
447 __func__, ret, start_sector);
448 return AVB_IO_RESULT_ERROR_IO;
449 }
450 memcpy((void *)tmp_buf +
451 start_offset % part->info.blksz,
452 buffer, residue);
453
454 ret = mmc_write(part, part->info.start +
455 start_sector, 1, tmp_buf);
456 if (ret != 1) {
457 printf("%s: write error (%ld, %lld)\n",
458 __func__, ret, start_sector);
459 return AVB_IO_RESULT_ERROR_IO;
460 }
461 }
462
463 io_cnt += residue;
464 buffer += residue;
465 start_offset += residue;
466 num_bytes -= residue;
467 continue;
468 }
469
470 if (sectors) {
471 if (io_type == IO_READ) {
472 ret = mmc_read_and_flush(part,
473 part->info.start +
474 start_sector,
475 sectors, buffer);
476 } else {
477 ret = mmc_write(part,
478 part->info.start +
479 start_sector,
480 sectors, buffer);
481 }
482
483 if (!ret) {
484 printf("%s: sector read error\n", __func__);
485 return AVB_IO_RESULT_ERROR_IO;
486 }
487
488 io_cnt += ret * part->info.blksz;
489 buffer += ret * part->info.blksz;
490 start_offset += ret * part->info.blksz;
491 num_bytes -= ret * part->info.blksz;
492 }
493 }
494
495 /* Set counter for read operation */
496 if (io_type == IO_READ && out_num_read)
497 *out_num_read = io_cnt;
498
499 return AVB_IO_RESULT_OK;
500}
501
502/**
503 * ============================================================================
504 * AVB 2.0 operations
505 * ============================================================================
506 */
507
508/**
509 * read_from_partition() - reads @num_bytes from @offset from partition
510 * identified by a string name
511 *
512 * @ops: contains AVB ops handlers
513 * @partition_name: partition name, NUL-terminated UTF-8 string
514 * @offset: offset from the beginning of partition
515 * @num_bytes: amount of bytes to read
516 * @buffer: destination buffer to store data
517 * @out_num_read:
518 *
519 * @return:
520 * AVB_IO_RESULT_OK, if partition was found and read operation succeed
521 * AVB_IO_RESULT_ERROR_IO, if i/o error occurred from the underlying i/o
522 * subsystem
523 * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if there is no partition with
524 * the given name
525 */
526static AvbIOResult read_from_partition(AvbOps *ops,
527 const char *partition_name,
528 s64 offset_from_partition,
529 size_t num_bytes,
530 void *buffer,
531 size_t *out_num_read)
532{
533 return mmc_byte_io(ops, partition_name, offset_from_partition,
534 num_bytes, buffer, out_num_read, IO_READ);
535}
536
537/**
538 * write_to_partition() - writes N bytes to a partition identified by a string
539 * name
540 *
541 * @ops: AvbOps, contains AVB ops handlers
542 * @partition_name: partition name
543 * @offset_from_partition: offset from the beginning of partition
544 * @num_bytes: amount of bytes to write
545 * @buf: data to write
546 * @out_num_read:
547 *
548 * @return:
549 * AVB_IO_RESULT_OK, if partition was found and read operation succeed
550 * AVB_IO_RESULT_ERROR_IO, if input/output error occurred
551 * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition, specified in
552 * @partition_name was not found
553 */
554static AvbIOResult write_to_partition(AvbOps *ops,
555 const char *partition_name,
556 s64 offset_from_partition,
557 size_t num_bytes,
558 const void *buffer)
559{
560 return mmc_byte_io(ops, partition_name, offset_from_partition,
561 num_bytes, (void *)buffer, NULL, IO_WRITE);
562}
563
564/**
565 * validate_vmbeta_public_key() - checks if the given public key used to sign
566 * the vbmeta partition is trusted
567 *
568 * @ops: AvbOps, contains AVB ops handlers
569 * @public_key_data: public key for verifying vbmeta partition signature
570 * @public_key_length: length of public key
571 * @public_key_metadata:
572 * @public_key_metadata_length:
573 * @out_key_is_trusted:
574 *
575 * @return:
576 * AVB_IO_RESULT_OK, if partition was found and read operation succeed
577 */
578static AvbIOResult validate_vbmeta_public_key(AvbOps *ops,
579 const u8 *public_key_data,
580 size_t public_key_length,
581 const u8
582 *public_key_metadata,
583 size_t
584 public_key_metadata_length,
585 bool *out_key_is_trusted)
586{
587 if (!public_key_length || !public_key_data || !out_key_is_trusted)
588 return AVB_IO_RESULT_ERROR_IO;
589
590 *out_key_is_trusted = false;
591 if (public_key_length != sizeof(avb_root_pub))
592 return AVB_IO_RESULT_ERROR_IO;
593
594 if (memcmp(avb_root_pub, public_key_data, public_key_length) == 0)
595 *out_key_is_trusted = true;
596
597 return AVB_IO_RESULT_OK;
598}
599
600/**
601 * read_rollback_index() - gets the rollback index corresponding to the
602 * location of given by @out_rollback_index.
603 *
604 * @ops: contains AvbOps handlers
605 * @rollback_index_slot:
606 * @out_rollback_index: used to write a retrieved rollback index.
607 *
608 * @return
609 * AVB_IO_RESULT_OK, if the roolback index was retrieved
610 */
611static AvbIOResult read_rollback_index(AvbOps *ops,
612 size_t rollback_index_slot,
613 u64 *out_rollback_index)
614{
615 /* For now we always return 0 as the stored rollback index. */
Igor Opaniuk5d4fd872018-06-03 21:56:40 +0300616 printf("%s not supported yet\n", __func__);
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300617
618 if (out_rollback_index)
619 *out_rollback_index = 0;
620
621 return AVB_IO_RESULT_OK;
622}
623
624/**
625 * write_rollback_index() - sets the rollback index corresponding to the
626 * location of given by @out_rollback_index.
627 *
628 * @ops: contains AvbOps handlers
629 * @rollback_index_slot:
630 * @rollback_index: rollback index to write.
631 *
632 * @return
633 * AVB_IO_RESULT_OK, if the roolback index was retrieved
634 */
635static AvbIOResult write_rollback_index(AvbOps *ops,
636 size_t rollback_index_slot,
637 u64 rollback_index)
638{
639 /* For now this is a no-op. */
Igor Opaniuk5d4fd872018-06-03 21:56:40 +0300640 printf("%s not supported yet\n", __func__);
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300641
642 return AVB_IO_RESULT_OK;
643}
644
645/**
646 * read_is_device_unlocked() - gets whether the device is unlocked
647 *
648 * @ops: contains AVB ops handlers
649 * @out_is_unlocked: device unlock state is stored here, true if unlocked,
650 * false otherwise
651 *
652 * @return:
653 * AVB_IO_RESULT_OK: state is retrieved successfully
654 * AVB_IO_RESULT_ERROR_IO: an error occurred
655 */
656static AvbIOResult read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked)
657{
658 /* For now we always return that the device is unlocked. */
659
Igor Opaniuk5d4fd872018-06-03 21:56:40 +0300660 printf("%s not supported yet\n", __func__);
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300661
662 *out_is_unlocked = true;
663
664 return AVB_IO_RESULT_OK;
665}
666
667/**
668 * get_unique_guid_for_partition() - gets the GUID for a partition identified
669 * by a string name
670 *
671 * @ops: contains AVB ops handlers
672 * @partition: partition name (NUL-terminated UTF-8 string)
673 * @guid_buf: buf, used to copy in GUID string. Example of value:
674 * 527c1c6d-6361-4593-8842-3c78fcd39219
675 * @guid_buf_size: @guid_buf buffer size
676 *
677 * @return:
678 * AVB_IO_RESULT_OK, on success (GUID found)
679 * AVB_IO_RESULT_ERROR_IO, if incorrect buffer size (@guid_buf_size) was
680 * provided
681 * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition was not found
682 */
683static AvbIOResult get_unique_guid_for_partition(AvbOps *ops,
684 const char *partition,
685 char *guid_buf,
686 size_t guid_buf_size)
687{
688 struct mmc_part *part;
689 size_t uuid_size;
690
691 part = get_partition(ops, partition);
692 if (!part)
693 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
694
695 uuid_size = sizeof(part->info.uuid);
696 if (uuid_size > guid_buf_size)
697 return AVB_IO_RESULT_ERROR_IO;
698
699 memcpy(guid_buf, part->info.uuid, uuid_size);
700 guid_buf[uuid_size - 1] = 0;
701
702 return AVB_IO_RESULT_OK;
703}
704
705/**
Igor Opaniuk7a5fbfe2018-08-10 16:59:59 +0300706 * get_size_of_partition() - gets the size of a partition identified
707 * by a string name
708 *
709 * @ops: contains AVB ops handlers
710 * @partition: partition name (NUL-terminated UTF-8 string)
711 * @out_size_num_bytes: returns the value of a partition size
712 *
713 * @return:
714 * AVB_IO_RESULT_OK, on success (GUID found)
715 * AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE, out_size_num_bytes is NULL
716 * AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION, if partition was not found
717 */
718static AvbIOResult get_size_of_partition(AvbOps *ops,
719 const char *partition,
720 u64 *out_size_num_bytes)
721{
722 struct mmc_part *part;
723
724 if (!out_size_num_bytes)
725 return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE;
726
727 part = get_partition(ops, partition);
728 if (!part)
729 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
730
731 *out_size_num_bytes = part->info.blksz * part->info.size;
732
733 return AVB_IO_RESULT_OK;
734}
735
736/**
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300737 * ============================================================================
738 * AVB2.0 AvbOps alloc/initialisation/free
739 * ============================================================================
740 */
741AvbOps *avb_ops_alloc(int boot_device)
742{
743 struct AvbOpsData *ops_data;
744
745 ops_data = avb_calloc(sizeof(struct AvbOpsData));
746 if (!ops_data)
747 return NULL;
748
749 ops_data->ops.user_data = ops_data;
750
751 ops_data->ops.read_from_partition = read_from_partition;
752 ops_data->ops.write_to_partition = write_to_partition;
753 ops_data->ops.validate_vbmeta_public_key = validate_vbmeta_public_key;
754 ops_data->ops.read_rollback_index = read_rollback_index;
755 ops_data->ops.write_rollback_index = write_rollback_index;
756 ops_data->ops.read_is_device_unlocked = read_is_device_unlocked;
757 ops_data->ops.get_unique_guid_for_partition =
758 get_unique_guid_for_partition;
Igor Opaniuk7a5fbfe2018-08-10 16:59:59 +0300759 ops_data->ops.get_size_of_partition = get_size_of_partition;
Igor Opaniuk3af30e42018-06-03 21:56:38 +0300760 ops_data->mmc_dev = boot_device;
761
762 return &ops_data->ops;
763}
764
765void avb_ops_free(AvbOps *ops)
766{
767 struct AvbOpsData *ops_data;
768
769 if (ops)
770 return;
771
772 ops_data = ops->user_data;
773
774 if (ops_data)
775 avb_free(ops_data);
776}