1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25 #include <common.h>
26 #include <image.h>
27 #include <android_image.h>
28 #include <malloc.h>
29 #include <mapmem.h>
30 #include <errno.h>
31 #include <command.h>
32 #include <mmc.h>
33 #include <blk.h>
34 #include <part.h>
35 #include <stdio.h>
36 #include <android_avb/avb_ops_user.h>
37 #include <android_avb/libavb_ab.h>
38 #include <android_avb/avb_atx_validate.h>
39 #include <android_avb/avb_atx_types.h>
40 #include <optee_include/OpteeClientInterface.h>
41 #include <optee_include/tee_api_defines.h>
42 #include <android_avb/avb_vbmeta_image.h>
43 #include <android_avb/avb_atx_validate.h>
44 #include <boot_rkimg.h>
45
byte_to_block(int64_t * offset,size_t * num_bytes,lbaint_t * offset_blk,lbaint_t * blkcnt)46 static void byte_to_block(int64_t *offset,
47 size_t *num_bytes,
48 lbaint_t *offset_blk,
49 lbaint_t *blkcnt)
50 {
51 *offset_blk = (lbaint_t)(*offset / 512);
52 if (*num_bytes % 512 == 0) {
53 if (*offset % 512 == 0)
54 *blkcnt = (lbaint_t)(*num_bytes / 512);
55 else
56 *blkcnt = (lbaint_t)(*num_bytes / 512) + 1;
57 } else {
58 if (*offset % 512 == 0) {
59 *blkcnt = (lbaint_t)(*num_bytes / 512) + 1;
60 } else {
61 if ((*offset % 512) + (*num_bytes % 512) < 512 ||
62 (*offset % 512) + (*num_bytes % 512) == 512) {
63 *blkcnt = (lbaint_t)(*num_bytes / 512) + 1;
64 } else {
65 *blkcnt = (lbaint_t)(*num_bytes / 512) + 2;
66 }
67 }
68 }
69 }
70
get_size_of_partition(AvbOps * ops,const char * partition,uint64_t * out_size_in_bytes)71 static AvbIOResult get_size_of_partition(AvbOps *ops,
72 const char *partition,
73 uint64_t *out_size_in_bytes)
74 {
75 struct blk_desc *dev_desc;
76 disk_partition_t part_info;
77
78 dev_desc = rockchip_get_bootdev();
79 if (!dev_desc) {
80 printf("%s: Could not find device\n", __func__);
81 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
82 }
83
84 if (part_get_info_by_name(dev_desc, partition, &part_info) < 0)
85 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
86
87 *out_size_in_bytes = (part_info.size) * 512;
88 return AVB_IO_RESULT_OK;
89 }
90
read_from_partition(AvbOps * ops,const char * partition,int64_t offset,size_t num_bytes,void * buffer,size_t * out_num_read)91 static AvbIOResult read_from_partition(AvbOps *ops,
92 const char *partition,
93 int64_t offset,
94 size_t num_bytes,
95 void *buffer,
96 size_t *out_num_read)
97 {
98 struct blk_desc *dev_desc;
99 lbaint_t offset_blk, blkcnt;
100 disk_partition_t part_info;
101 uint64_t partition_size;
102
103 if (offset < 0) {
104 if (get_size_of_partition(ops, partition, &partition_size))
105 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
106
107 if (-offset > partition_size)
108 return AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION;
109
110 offset = partition_size - (-offset);
111 }
112
113 byte_to_block(&offset, &num_bytes, &offset_blk, &blkcnt);
114 dev_desc = rockchip_get_bootdev();
115 if (!dev_desc) {
116 printf("%s: Could not find device\n", __func__);
117 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
118 }
119
120 if (part_get_info_by_name(dev_desc, partition, &part_info) < 0) {
121 printf("Could not find \"%s\" partition\n", partition);
122 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
123 }
124
125 if ((offset % 512 == 0) && (num_bytes % 512 == 0)) {
126 blk_dread(dev_desc, part_info.start + offset_blk,
127 blkcnt, buffer);
128 *out_num_read = blkcnt * 512;
129 } else {
130 char *buffer_temp;
131
132 buffer_temp = malloc(512 * blkcnt);
133 if (!buffer_temp) {
134 printf("malloc error!\n");
135 return AVB_IO_RESULT_ERROR_OOM;
136 }
137 blk_dread(dev_desc, part_info.start + offset_blk,
138 blkcnt, buffer_temp);
139 memcpy(buffer, buffer_temp + (offset % 512), num_bytes);
140 *out_num_read = num_bytes;
141 free(buffer_temp);
142 }
143
144 return AVB_IO_RESULT_OK;
145 }
146
write_to_partition(AvbOps * ops,const char * partition,int64_t offset,size_t num_bytes,const void * buffer)147 static AvbIOResult write_to_partition(AvbOps *ops,
148 const char *partition,
149 int64_t offset,
150 size_t num_bytes,
151 const void *buffer)
152 {
153 struct blk_desc *dev_desc;
154 char *buffer_temp;
155 disk_partition_t part_info;
156 lbaint_t offset_blk, blkcnt;
157
158 byte_to_block(&offset, &num_bytes, &offset_blk, &blkcnt);
159 buffer_temp = malloc(512 * blkcnt);
160 if (!buffer_temp) {
161 printf("malloc error!\n");
162 return AVB_IO_RESULT_ERROR_OOM;
163 }
164 memset(buffer_temp, 0, 512 * blkcnt);
165 dev_desc = rockchip_get_bootdev();
166 if (!dev_desc) {
167 printf("%s: Could not find device\n", __func__);
168 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
169 }
170
171 if (part_get_info_by_name(dev_desc, partition, &part_info) < 0) {
172 printf("Could not find \"%s\" partition\n", partition);
173 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
174 }
175
176 if ((offset % 512 != 0) && (num_bytes % 512) != 0)
177 blk_dread(dev_desc, part_info.start + offset_blk,
178 blkcnt, buffer_temp);
179
180 memcpy(buffer_temp, buffer + (offset % 512), num_bytes);
181 blk_dwrite(dev_desc, part_info.start + offset_blk, blkcnt, buffer);
182 free(buffer_temp);
183
184 return AVB_IO_RESULT_OK;
185 }
186
187 static AvbIOResult
validate_vbmeta_public_key(AvbOps * ops,const uint8_t * public_key_data,size_t public_key_length,const uint8_t * public_key_metadata,size_t public_key_metadata_length,bool * out_is_trusted)188 validate_vbmeta_public_key(AvbOps *ops,
189 const uint8_t *public_key_data,
190 size_t public_key_length,
191 const uint8_t *public_key_metadata,
192 size_t public_key_metadata_length,
193 bool *out_is_trusted)
194 {
195 /* remain AVB_VBMETA_PUBLIC_KEY_VALIDATE to compatible legacy code */
196 #if defined(CONFIG_AVB_VBMETA_PUBLIC_KEY_VALIDATE) || \
197 defined(AVB_VBMETA_PUBLIC_KEY_VALIDATE)
198 if (out_is_trusted) {
199 avb_atx_validate_vbmeta_public_key(ops,
200 public_key_data,
201 public_key_length,
202 public_key_metadata,
203 public_key_metadata_length,
204 out_is_trusted);
205 }
206 #else
207 if (out_is_trusted)
208 *out_is_trusted = true;
209 #endif
210 return AVB_IO_RESULT_OK;
211 }
212
read_rollback_index(AvbOps * ops,size_t rollback_index_location,uint64_t * out_rollback_index)213 static AvbIOResult read_rollback_index(AvbOps *ops,
214 size_t rollback_index_location,
215 uint64_t *out_rollback_index)
216 {
217 if (out_rollback_index) {
218 #ifdef CONFIG_OPTEE_CLIENT
219 int ret;
220
221 ret = trusty_read_rollback_index(rollback_index_location,
222 out_rollback_index);
223 switch (ret) {
224 case TEE_SUCCESS:
225 ret = AVB_IO_RESULT_OK;
226 break;
227 case TEE_ERROR_GENERIC:
228 case TEE_ERROR_NO_DATA:
229 case TEE_ERROR_ITEM_NOT_FOUND:
230 *out_rollback_index = 0;
231 ret = trusty_write_rollback_index(rollback_index_location,
232 *out_rollback_index);
233 if (ret) {
234 printf("%s: init rollback index error\n",
235 __FILE__);
236 ret = AVB_IO_RESULT_ERROR_IO;
237 } else {
238 ret =
239 trusty_read_rollback_index(rollback_index_location,
240 out_rollback_index);
241 if (ret)
242 ret = AVB_IO_RESULT_ERROR_IO;
243 else
244 ret = AVB_IO_RESULT_OK;
245 }
246 break;
247 default:
248 ret = AVB_IO_RESULT_ERROR_IO;
249 printf("%s: trusty_read_rollback_index failed",
250 __FILE__);
251 }
252
253 return ret;
254 #else
255 *out_rollback_index = 0;
256
257 return AVB_IO_RESULT_OK;
258 #endif
259 }
260
261 return AVB_IO_RESULT_ERROR_IO;
262 }
263
write_rollback_index(AvbOps * ops,size_t rollback_index_location,uint64_t rollback_index)264 static AvbIOResult write_rollback_index(AvbOps *ops,
265 size_t rollback_index_location,
266 uint64_t rollback_index)
267 {
268 #ifdef CONFIG_OPTEE_CLIENT
269 if (trusty_write_rollback_index(rollback_index_location,
270 rollback_index)) {
271 printf("%s: Fail to write rollback index\n", __FILE__);
272 return AVB_IO_RESULT_ERROR_IO;
273 }
274 return AVB_IO_RESULT_OK;
275 #endif
276 return AVB_IO_RESULT_ERROR_IO;
277 }
278
read_is_device_unlocked(AvbOps * ops,bool * out_is_unlocked)279 static AvbIOResult read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked)
280 {
281 if (out_is_unlocked) {
282 #ifdef CONFIG_OPTEE_CLIENT
283 uint8_t vboot_flag = 0;
284 int ret;
285
286 ret = trusty_read_lock_state((uint8_t *)out_is_unlocked);
287 switch (ret) {
288 case TEE_SUCCESS:
289 ret = AVB_IO_RESULT_OK;
290 break;
291 case TEE_ERROR_GENERIC:
292 case TEE_ERROR_NO_DATA:
293 case TEE_ERROR_ITEM_NOT_FOUND:
294 if (trusty_read_vbootkey_enable_flag(&vboot_flag)) {
295 printf("Can't read vboot flag\n");
296 return AVB_IO_RESULT_ERROR_IO;
297 }
298
299 if (vboot_flag)
300 *out_is_unlocked = 0;
301 else
302 *out_is_unlocked = 1;
303
304 if (trusty_write_lock_state(*out_is_unlocked)) {
305 printf("%s: init lock state error\n", __FILE__);
306 ret = AVB_IO_RESULT_ERROR_IO;
307 } else {
308 ret =
309 trusty_read_lock_state((uint8_t *)out_is_unlocked);
310 if (ret == 0)
311 ret = AVB_IO_RESULT_OK;
312 else
313 ret = AVB_IO_RESULT_ERROR_IO;
314 }
315 break;
316 default:
317 ret = AVB_IO_RESULT_ERROR_IO;
318 printf("%s: trusty_read_lock_state failed\n", __FILE__);
319 }
320 return ret;
321 #else
322 *out_is_unlocked = 1;
323
324 return AVB_IO_RESULT_OK;
325 #endif
326 }
327 return AVB_IO_RESULT_ERROR_IO;
328 }
329
write_is_device_unlocked(AvbOps * ops,bool * out_is_unlocked)330 static AvbIOResult write_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked)
331 {
332 if (out_is_unlocked) {
333 #ifdef CONFIG_OPTEE_CLIENT
334 if (trusty_write_lock_state(*out_is_unlocked)) {
335 printf("%s: Fail to write lock state\n", __FILE__);
336 return AVB_IO_RESULT_ERROR_IO;
337 }
338 return AVB_IO_RESULT_OK;
339 #endif
340 }
341 return AVB_IO_RESULT_ERROR_IO;
342 }
343
get_unique_guid_for_partition(AvbOps * ops,const char * partition,char * guid_buf,size_t guid_buf_size)344 static AvbIOResult get_unique_guid_for_partition(AvbOps *ops,
345 const char *partition,
346 char *guid_buf,
347 size_t guid_buf_size)
348 {
349 struct blk_desc *dev_desc;
350 disk_partition_t part_info;
351
352 dev_desc = rockchip_get_bootdev();
353 if (!dev_desc) {
354 printf("%s: Could not find device\n", __func__);
355 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
356 }
357
358 if (part_get_info_by_name(dev_desc, partition, &part_info) < 0) {
359 printf("Could not find \"%s\" partition\n", partition);
360 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
361 }
362 if (guid_buf && guid_buf_size > 0)
363 memcpy(guid_buf, part_info.uuid, guid_buf_size);
364
365 return AVB_IO_RESULT_OK;
366 }
367
368 /* read permanent attributes from rpmb */
avb_read_perm_attr(AvbAtxOps * atx_ops,AvbAtxPermanentAttributes * attributes)369 AvbIOResult avb_read_perm_attr(AvbAtxOps *atx_ops,
370 AvbAtxPermanentAttributes *attributes)
371 {
372 if (attributes) {
373 #ifdef CONFIG_OPTEE_CLIENT
374 trusty_read_permanent_attributes((uint8_t *)attributes,
375 sizeof(struct AvbAtxPermanentAttributes));
376 return AVB_IO_RESULT_OK;
377 #endif
378 }
379
380 return -1;
381 }
382
383 /*read permanent attributes hash from efuse */
avb_read_perm_attr_hash(AvbAtxOps * atx_ops,uint8_t hash[AVB_SHA256_DIGEST_SIZE])384 AvbIOResult avb_read_perm_attr_hash(AvbAtxOps *atx_ops,
385 uint8_t hash[AVB_SHA256_DIGEST_SIZE])
386 {
387 #ifndef CONFIG_ROCKCHIP_PRELOADER_PUB_KEY
388 #ifdef CONFIG_OPTEE_CLIENT
389 if (trusty_read_attribute_hash((uint32_t *)hash,
390 AVB_SHA256_DIGEST_SIZE / 4))
391 return -1;
392 #else
393 printf("Please open the macro!\n");
394 return -1;
395 #endif
396 #endif
397 return AVB_IO_RESULT_OK;
398 }
399
avb_set_key_version(AvbAtxOps * atx_ops,size_t rollback_index_location,uint64_t key_version)400 static void avb_set_key_version(AvbAtxOps *atx_ops,
401 size_t rollback_index_location,
402 uint64_t key_version)
403 {
404 #ifdef CONFIG_OPTEE_CLIENT
405 uint64_t key_version_temp = 0;
406
407 if (trusty_read_rollback_index(rollback_index_location, &key_version_temp))
408 printf("%s: Fail to read rollback index\n", __FILE__);
409 if (key_version_temp == key_version)
410 return;
411 if (trusty_write_rollback_index(rollback_index_location, key_version))
412 printf("%s: Fail to write rollback index\n", __FILE__);
413 #endif
414 }
415
rk_get_random(AvbAtxOps * atx_ops,size_t num_bytes,uint8_t * output)416 AvbIOResult rk_get_random(AvbAtxOps *atx_ops,
417 size_t num_bytes,
418 uint8_t *output)
419 {
420 int i;
421 unsigned int seed;
422
423 seed = (unsigned int)get_timer(0);
424 for (i = 0; i < num_bytes; i++) {
425 srand(seed);
426 output[i] = (uint8_t)(rand());
427 seed = (unsigned int)(output[i]);
428 }
429
430 return 0;
431 }
432
433 #ifdef CONFIG_ANDROID_BOOT_IMAGE
get_preloaded_partition(AvbOps * ops,const char * partition,size_t num_bytes,uint8_t ** out_pointer,size_t * out_num_bytes_preloaded,int allow_verification_error)434 static AvbIOResult get_preloaded_partition(AvbOps* ops,
435 const char* partition,
436 size_t num_bytes,
437 uint8_t** out_pointer,
438 size_t* out_num_bytes_preloaded,
439 int allow_verification_error)
440 {
441 struct preloaded_partition *preload_info = NULL;
442 struct AvbOpsData *data = ops->user_data;
443 struct blk_desc *dev_desc;
444 disk_partition_t part_info;
445 ulong load_addr;
446 AvbIOResult ret;
447 int full_preload = 0;
448
449 dev_desc = rockchip_get_bootdev();
450 if (!dev_desc)
451 return AVB_IO_RESULT_ERROR_IO;
452
453 if (part_get_info_by_name(dev_desc, partition, &part_info) < 0) {
454 printf("Could not find \"%s\" partition\n", partition);
455 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
456 }
457
458 if (!allow_verification_error) {
459 if (!strncmp(partition, ANDROID_PARTITION_BOOT, 4) ||
460 !strncmp(partition, ANDROID_PARTITION_RECOVERY, 8))
461 preload_info = &data->boot;
462 else if (!strncmp(partition, ANDROID_PARTITION_VENDOR_BOOT, 11))
463 preload_info = &data->vendor_boot;
464 else if (!strncmp(partition, ANDROID_PARTITION_INIT_BOOT, 9))
465 preload_info = &data->init_boot;
466 else if (!strncmp(partition, ANDROID_PARTITION_RESOURCE, 8))
467 preload_info = &data->resource;
468
469 if (!preload_info) {
470 printf("Error: unknown full load partition '%s'\n", partition);
471 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
472 }
473
474 printf("preloaded(s): %sfull image from '%s' at 0x%08lx - 0x%08lx\n",
475 preload_info->size ? "pre-" : "", partition,
476 (ulong)preload_info->addr,
477 (ulong)preload_info->addr + num_bytes);
478
479 /* If the partition hasn't yet been preloaded, do it now.*/
480 if (preload_info->size == 0) {
481 ret = ops->read_from_partition(ops, partition,
482 0, num_bytes,
483 preload_info->addr,
484 &preload_info->size);
485 if (ret != AVB_IO_RESULT_OK)
486 return ret;
487 }
488 *out_pointer = preload_info->addr;
489 *out_num_bytes_preloaded = preload_info->size;
490 ret = AVB_IO_RESULT_OK;
491 } else {
492 if (!strncmp(partition, ANDROID_PARTITION_INIT_BOOT, 9) ||
493 !strncmp(partition, ANDROID_PARTITION_VENDOR_BOOT, 11) ||
494 !strncmp(partition, ANDROID_PARTITION_BOOT, 4) ||
495 !strncmp(partition, ANDROID_PARTITION_RECOVERY, 8) ||
496 !strncmp(partition, ANDROID_PARTITION_RESOURCE, 8)) {
497 /* If already full preloaded, just use it */
498 if (!strncmp(partition, ANDROID_PARTITION_BOOT, 4) ||
499 !strncmp(partition, ANDROID_PARTITION_RECOVERY, 8)) {
500 preload_info = &data->boot;
501 if (preload_info->size) {
502 *out_pointer = preload_info->addr;
503 *out_num_bytes_preloaded = num_bytes;
504 full_preload = 1;
505 }
506 }
507 printf("preloaded: %s image from '%s\n",
508 full_preload ? "pre-full" : "distribute", partition);
509 } else {
510 printf("Error: unknown preloaded partition '%s'\n", partition);
511 return AVB_IO_RESULT_ERROR_OOM;
512 }
513
514 /*
515 * Already preloaded during boot/recovery loading,
516 * here we just return a dummy buffer.
517 */
518 if (!strncmp(partition, ANDROID_PARTITION_INIT_BOOT, 9) ||
519 !strncmp(partition, ANDROID_PARTITION_VENDOR_BOOT, 11) ||
520 !strncmp(partition, ANDROID_PARTITION_RESOURCE, 8)) {
521 *out_pointer = (u8 *)avb_malloc(ARCH_DMA_MINALIGN);
522 *out_num_bytes_preloaded = num_bytes; /* return what it expects */
523 return AVB_IO_RESULT_OK;
524 }
525
526 /* If already full preloaded, there is nothing to do and just return */
527 if (full_preload)
528 return AVB_IO_RESULT_OK;
529
530 /*
531 * only boot/recovery partition can reach here
532 * and init/vendor_boot are loaded at this round.
533 */
534 load_addr = env_get_ulong("kernel_addr_r", 16, 0);
535 if (!load_addr)
536 return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
537
538 ret = android_image_load_by_partname(dev_desc, partition, &load_addr);
539 if (!ret) {
540 *out_pointer = (u8 *)load_addr;
541 *out_num_bytes_preloaded = num_bytes; /* return what it expects */
542 ret = AVB_IO_RESULT_OK;
543 } else {
544 ret = AVB_IO_RESULT_ERROR_IO;
545 }
546 }
547
548 return ret;
549 }
550 #endif
551
validate_public_key_for_partition(AvbOps * ops,const char * partition,const uint8_t * public_key_data,size_t public_key_length,const uint8_t * public_key_metadata,size_t public_key_metadata_length,bool * out_is_trusted,uint32_t * out_rollback_index_location)552 AvbIOResult validate_public_key_for_partition(AvbOps *ops,
553 const char *partition,
554 const uint8_t *public_key_data,
555 size_t public_key_length,
556 const uint8_t *public_key_metadata,
557 size_t public_key_metadata_length,
558 bool *out_is_trusted,
559 uint32_t *out_rollback_index_location)
560 {
561 /* remain AVB_VBMETA_PUBLIC_KEY_VALIDATE to compatible legacy code */
562 #if defined(CONFIG_AVB_VBMETA_PUBLIC_KEY_VALIDATE) || \
563 defined(AVB_VBMETA_PUBLIC_KEY_VALIDATE)
564 if (out_is_trusted) {
565 avb_atx_validate_vbmeta_public_key(ops,
566 public_key_data,
567 public_key_length,
568 public_key_metadata,
569 public_key_metadata_length,
570 out_is_trusted);
571 }
572 #else
573 if (out_is_trusted)
574 *out_is_trusted = true;
575 #endif
576 *out_rollback_index_location = 0;
577 return AVB_IO_RESULT_OK;
578 }
579
avb_ops_user_new(void)580 AvbOps *avb_ops_user_new(void)
581 {
582 AvbOps *ops = NULL;
583 struct AvbOpsData *ops_data = NULL;
584
585 ops = calloc(1, sizeof(AvbOps));
586 if (!ops) {
587 printf("Error allocating memory for AvbOps.\n");
588 goto out;
589 }
590 ops->ab_ops = calloc(1, sizeof(AvbABOps));
591 if (!ops->ab_ops) {
592 printf("Error allocating memory for AvbABOps.\n");
593 free(ops);
594 goto out;
595 }
596
597 ops->atx_ops = calloc(1, sizeof(AvbAtxOps));
598 if (!ops->atx_ops) {
599 printf("Error allocating memory for AvbAtxOps.\n");
600 free(ops->ab_ops);
601 free(ops);
602 goto out;
603 }
604
605 ops_data = calloc(1, sizeof(struct AvbOpsData));
606 if (!ops_data) {
607 printf("Error allocating memory for AvbOpsData.\n");
608 free(ops->atx_ops);
609 free(ops->ab_ops);
610 free(ops);
611 goto out;
612 }
613
614 ops->ab_ops->ops = ops;
615 ops->atx_ops->ops = ops;
616 ops_data->ops = ops;
617 ops->user_data = ops_data;
618
619 ops->read_from_partition = read_from_partition;
620 ops->write_to_partition = write_to_partition;
621 ops->validate_vbmeta_public_key = validate_vbmeta_public_key;
622 ops->read_rollback_index = read_rollback_index;
623 ops->write_rollback_index = write_rollback_index;
624 ops->read_is_device_unlocked = read_is_device_unlocked;
625 ops->write_is_device_unlocked = write_is_device_unlocked;
626 ops->get_unique_guid_for_partition = get_unique_guid_for_partition;
627 ops->get_size_of_partition = get_size_of_partition;
628 #ifdef CONFIG_ANDROID_BOOT_IMAGE
629 ops->get_preloaded_partition = get_preloaded_partition;
630 #endif
631 ops->validate_public_key_for_partition = validate_public_key_for_partition;
632 ops->ab_ops->read_ab_metadata = avb_ab_data_read;
633 ops->ab_ops->write_ab_metadata = avb_ab_data_write;
634 ops->atx_ops->read_permanent_attributes = avb_read_perm_attr;
635 ops->atx_ops->read_permanent_attributes_hash = avb_read_perm_attr_hash;
636 ops->atx_ops->set_key_version = avb_set_key_version;
637 ops->atx_ops->get_random = rk_get_random;
638
639 return ops;
640 out:
641 return NULL;
642 }
643
avb_ops_user_free(AvbOps * ops)644 void avb_ops_user_free(AvbOps *ops)
645 {
646 free(ops->user_data);
647 free(ops->ab_ops);
648 free(ops->atx_ops);
649 free(ops);
650 }
651