1 /* 2 * (C) Copyright 2017 Rockchip Electronics Co., Ltd 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <image.h> 9 #include <android_image.h> 10 #include <malloc.h> 11 #include <mapmem.h> 12 #include <errno.h> 13 #include <command.h> 14 #include <mmc.h> 15 #include <blk.h> 16 #include <part.h> 17 #include <android_avb/avb_ops_user.h> 18 #include <android_avb/libavb_ab.h> 19 #include <android_avb/avb_atx_validate.h> 20 #include <android_avb/avb_atx_types.h> 21 #include <optee_include/OpteeClientInterface.h> 22 #include <optee_include/tee_api_defines.h> 23 #include <android_avb/avb_vbmeta_image.h> 24 #include <android_avb/avb_atx_validate.h> 25 #include <android_avb/rk_avb_ops_user.h> 26 #include <boot_rkimg.h> 27 #include <asm/arch/rk_atags.h> 28 29 /* rk used */ 30 int rk_avb_get_pub_key(struct rk_pub_key *pub_key) 31 { 32 struct tag *t = NULL; 33 34 t = atags_get_tag(ATAG_PUB_KEY); 35 if (!t) 36 return -1; 37 38 memcpy(pub_key, t->u.pub_key.data, sizeof(struct rk_pub_key)); 39 40 return 0; 41 } 42 int rk_avb_get_perm_attr_cer(uint8_t *cer, uint32_t size) 43 { 44 #ifdef CONFIG_OPTEE_CLIENT 45 if (trusty_read_permanent_attributes_cer((uint8_t *)cer, size)) 46 return -EIO; 47 48 return 0; 49 #else 50 return -1; 51 #endif 52 } 53 54 int rk_avb_set_perm_attr_cer(uint8_t *cer, uint32_t size) 55 { 56 #ifdef CONFIG_OPTEE_CLIENT 57 if (trusty_write_permanent_attributes_cer((uint8_t *)cer, size)) 58 return -EIO; 59 60 return 0; 61 #else 62 return -1; 63 #endif 64 } 65 66 int rk_avb_read_slot_count(char *slot_count) 67 { 68 *slot_count = SLOT_NUM; 69 70 return 0; 71 } 72 73 int rk_avb_read_slot_suffixes(char *slot_suffixes) 74 { 75 memcpy(slot_suffixes, CURR_SYSTEM_SLOT_SUFFIX, 76 strlen(CURR_SYSTEM_SLOT_SUFFIX)); 77 78 return 0; 79 } 80 81 int rk_avb_set_slot_active(unsigned int *slot_number) 82 { 83 AvbOps* ops; 84 ops = avb_ops_user_new(); 85 int ret = 0; 86 87 if (ops == NULL) { 88 printf("avb_ops_user_new() failed!\n"); 89 return -1; 90 } 91 92 debug("set_slot_active\n"); 93 if (avb_ab_mark_slot_active(ops->ab_ops, *slot_number) != 0) { 94 printf("set_slot_active error!\n"); 95 ret = -1; 96 } 97 98 avb_ops_user_free(ops); 99 return ret; 100 } 101 102 static bool slot_is_bootable(AvbABSlotData* slot) { 103 return (slot->priority > 0) && 104 (slot->successful_boot || (slot->tries_remaining > 0)); 105 } 106 107 AvbABFlowResult rk_avb_ab_slot_select(AvbABOps* ab_ops,char* select_slot) 108 { 109 AvbABFlowResult ret = AVB_AB_FLOW_RESULT_OK; 110 AvbIOResult io_ret = AVB_IO_RESULT_OK; 111 AvbABData ab_data; 112 size_t slot_index_to_boot; 113 114 io_ret = ab_ops->read_ab_metadata(ab_ops, &ab_data); 115 if (io_ret != AVB_IO_RESULT_OK) { 116 avb_error("I/O error while loading A/B metadata.\n"); 117 ret = AVB_AB_FLOW_RESULT_ERROR_IO; 118 goto out; 119 } 120 if (slot_is_bootable(&ab_data.slots[0]) && slot_is_bootable(&ab_data.slots[1])) { 121 if (ab_data.slots[1].priority > ab_data.slots[0].priority) { 122 slot_index_to_boot = 1; 123 } else { 124 slot_index_to_boot = 0; 125 } 126 } else if(slot_is_bootable(&ab_data.slots[0])) { 127 slot_index_to_boot = 0; 128 } else if(slot_is_bootable(&ab_data.slots[1])) { 129 slot_index_to_boot = 1; 130 } else { 131 avb_error("No bootable slots found.\n"); 132 ret = AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS; 133 goto out; 134 } 135 136 if (slot_index_to_boot == 0) { 137 strcpy(select_slot, "_a"); 138 } else if(slot_index_to_boot == 1) { 139 strcpy(select_slot, "_b"); 140 } 141 out: 142 return ret; 143 } 144 145 int rk_avb_get_current_slot(char *select_slot) 146 { 147 AvbOps* ops; 148 int ret = 0; 149 150 ops = avb_ops_user_new(); 151 if (ops == NULL) { 152 printf("avb_ops_user_new() failed!\n"); 153 return -1; 154 } 155 156 if (rk_avb_ab_slot_select(ops->ab_ops, select_slot) != 0) { 157 printf("###There is no bootable slot, bring up last_boot!###\n"); 158 if (rk_get_lastboot() == 1) 159 memcpy(select_slot, "_b", 2); 160 else if(rk_get_lastboot() == 0) 161 memcpy(select_slot, "_a", 2); 162 else 163 return -1; 164 ret = 0; 165 } 166 167 avb_ops_user_free(ops); 168 return ret; 169 } 170 171 int rk_avb_read_permanent_attributes(uint8_t *attributes, uint32_t size) 172 { 173 #ifdef CONFIG_OPTEE_CLIENT 174 if(trusty_read_permanent_attributes(attributes, size) != 0) { 175 printf("trusty_read_permanent_attributes failed!\n"); 176 return -1; 177 } 178 179 return 0; 180 #else 181 return -1; 182 #endif 183 } 184 185 int rk_avb_write_permanent_attributes(uint8_t *attributes, uint32_t size) 186 { 187 #ifdef CONFIG_OPTEE_CLIENT 188 if(trusty_write_permanent_attributes(attributes, size) != 0) { 189 printf("trusty_write_permanent_attributes failed!\n"); 190 return -1; 191 } 192 193 return 0; 194 #else 195 return -1; 196 #endif 197 } 198 199 int rk_avb_read_flash_lock_state(uint8_t *flash_lock_state) 200 { 201 #ifdef CONFIG_OPTEE_CLIENT 202 int ret; 203 204 ret = trusty_read_flash_lock_state(flash_lock_state); 205 switch (ret) { 206 case TEE_SUCCESS: 207 break; 208 case TEE_ERROR_GENERIC: 209 case TEE_ERROR_NO_DATA: 210 case TEE_ERROR_ITEM_NOT_FOUND: 211 *flash_lock_state = 1; 212 if (trusty_write_flash_lock_state(*flash_lock_state)) { 213 avb_error("trusty_write_flash_lock_state error!"); 214 ret = -1; 215 } else { 216 ret = trusty_read_flash_lock_state(flash_lock_state); 217 } 218 break; 219 default: 220 printf("%s: trusty_read_flash_lock_state failed\n", __FILE__); 221 } 222 223 return ret; 224 #else 225 return -1; 226 #endif 227 } 228 229 int rk_avb_write_flash_lock_state(uint8_t flash_lock_state) 230 { 231 #ifdef CONFIG_OPTEE_CLIENT 232 if (trusty_write_flash_lock_state(flash_lock_state)) { 233 printf("trusty_write_flash_lock_state error!\n"); 234 return -1; 235 } 236 237 return 0; 238 #else 239 return -1; 240 #endif 241 } 242 243 int rk_avb_write_lock_state(uint8_t lock_state) 244 { 245 #ifdef CONFIG_OPTEE_CLIENT 246 if (trusty_write_lock_state(lock_state)) { 247 printf("trusty_write_lock_state error!\n"); 248 return -1; 249 } 250 251 return 0; 252 #else 253 return -1; 254 #endif 255 } 256 257 int rk_avb_read_lock_state(uint8_t *lock_state) 258 { 259 #ifdef CONFIG_OPTEE_CLIENT 260 int ret; 261 262 ret = trusty_read_lock_state(lock_state); 263 switch (ret) { 264 case TEE_SUCCESS: 265 break; 266 case TEE_ERROR_GENERIC: 267 case TEE_ERROR_NO_DATA: 268 case TEE_ERROR_ITEM_NOT_FOUND: 269 *lock_state = 1; 270 if (rk_avb_write_lock_state(*lock_state)) { 271 avb_error("avb_write_lock_state error!"); 272 ret = -1; 273 } else { 274 ret = trusty_read_lock_state(lock_state); 275 } 276 break; 277 default: 278 printf("%s: trusty_read_lock_state failed\n", __FILE__); 279 } 280 281 return ret; 282 #else 283 return -1; 284 #endif 285 } 286 287 int rk_avb_write_perm_attr_flag(uint8_t flag) 288 { 289 #ifdef CONFIG_OPTEE_CLIENT 290 if (trusty_write_permanent_attributes_flag(flag)) { 291 printf("trusty_write_permanent_attributes_flag error!\n"); 292 return -1; 293 } 294 295 return 0; 296 #else 297 return -1; 298 #endif 299 } 300 301 int rk_avb_read_perm_attr_flag(uint8_t *flag) 302 { 303 #ifdef CONFIG_OPTEE_CLIENT 304 int ret; 305 306 ret = trusty_read_permanent_attributes_flag(flag); 307 switch (ret) { 308 case TEE_SUCCESS: 309 break; 310 case TEE_ERROR_GENERIC: 311 case TEE_ERROR_NO_DATA: 312 case TEE_ERROR_ITEM_NOT_FOUND: 313 *flag = 0; 314 if (rk_avb_write_perm_attr_flag(*flag)) { 315 avb_error("avb_write_perm_attr_flag error!"); 316 ret = -1; 317 } else { 318 ret = trusty_read_permanent_attributes_flag(flag); 319 } 320 break; 321 default: 322 printf("%s: trusty_read_permanent_attributes_flag failed", 323 __FILE__); 324 } 325 326 return ret; 327 #else 328 return -1; 329 #endif 330 } 331 332 int rk_avb_read_vbootkey_hash(uint8_t *buf, uint8_t length) 333 { 334 #ifdef CONFIG_OPTEE_CLIENT 335 if (trusty_read_vbootkey_hash((uint32_t *)buf, 336 (uint32_t)length / sizeof(uint32_t))) { 337 printf("trusty_read_vbootkey_hash error!\n"); 338 return -1; 339 } 340 341 return 0; 342 #else 343 return -1; 344 #endif 345 } 346 347 int rk_avb_write_vbootkey_hash(uint8_t *buf, uint8_t length) 348 { 349 #ifdef CONFIG_OPTEE_CLIENT 350 if (trusty_write_vbootkey_hash((uint32_t *)buf, 351 (uint32_t)length / sizeof(uint32_t))) { 352 printf("trusty_write_vbootkey_hash error!\n"); 353 return -1; 354 } 355 356 return 0; 357 #else 358 return -1; 359 #endif 360 } 361 362 int rk_avb_close_optee_client(void) 363 { 364 #ifdef CONFIG_OPTEE_CLIENT 365 if(trusty_notify_optee_uboot_end()) { 366 printf("trusty_notify_optee_uboot_end error!\n"); 367 return -1; 368 } 369 370 return 0; 371 #else 372 return -1; 373 #endif 374 } 375 376 int rk_avb_read_attribute_hash(uint8_t *buf, uint8_t length) 377 { 378 #ifdef CONFIG_OPTEE_CLIENT 379 if (trusty_read_attribute_hash((uint32_t *)buf, 380 (uint32_t)(length/sizeof(uint32_t)))) { 381 printf("trusty_read_attribute_hash error!\n"); 382 return -1; 383 } 384 385 return 0; 386 #else 387 return -1; 388 #endif 389 } 390 391 int rk_avb_write_attribute_hash(uint8_t *buf, uint8_t length) 392 { 393 #ifdef CONFIG_OPTEE_CLIENT 394 if (trusty_write_attribute_hash((uint32_t *)buf, 395 (uint32_t)(length/sizeof(uint32_t)))) { 396 printf("trusty_write_attribute_hash error!\n"); 397 return -1; 398 } 399 400 return 0; 401 #else 402 return -1; 403 #endif 404 } 405 406 int rk_avb_read_all_rollback_index(char *buffer) 407 { 408 AvbOps* ops; 409 uint64_t stored_rollback_index = 0; 410 AvbIOResult io_ret; 411 char temp[ROLLBACK_MAX_SIZE] = {0}; 412 int n; 413 414 ops = avb_ops_user_new(); 415 if (ops == NULL) { 416 printf("avb_ops_user_new() failed!\n"); 417 return -1; 418 } 419 420 for (n = 0; n < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS; n++) { 421 io_ret = ops->read_rollback_index( 422 ops, n, &stored_rollback_index); 423 if (io_ret != AVB_IO_RESULT_OK) 424 goto out; 425 snprintf(temp, sizeof(int) + 1, "%d", n); 426 strncat(buffer, temp, ROLLBACK_MAX_SIZE); 427 strncat(buffer, ":", 1); 428 snprintf(temp, sizeof(uint64_t) + 1, "%lld", 429 stored_rollback_index); 430 strncat(buffer, temp, ROLLBACK_MAX_SIZE); 431 strncat(buffer, ",", 1); 432 } 433 434 io_ret = 435 ops->read_rollback_index(ops, 436 AVB_ATX_PIK_VERSION_LOCATION, 437 &stored_rollback_index); 438 if (io_ret != AVB_IO_RESULT_OK) { 439 avb_error("Failed to read PIK minimum version.\n"); 440 goto out; 441 } 442 /* PIK rollback index */ 443 snprintf(temp, sizeof(int) + 1, "%d", AVB_ATX_PIK_VERSION_LOCATION); 444 strncat(buffer, temp, ROLLBACK_MAX_SIZE); 445 strncat(buffer, ":", 1); 446 snprintf(temp, sizeof(uint64_t) + 1, "%lld", stored_rollback_index); 447 strncat(buffer, temp, ROLLBACK_MAX_SIZE); 448 strncat(buffer, ",", 1); 449 io_ret = ops->read_rollback_index(ops, 450 AVB_ATX_PSK_VERSION_LOCATION, 451 &stored_rollback_index); 452 if (io_ret != AVB_IO_RESULT_OK) { 453 avb_error("Failed to read PSK minimum version.\n"); 454 goto out; 455 } 456 /* PSK rollback index */ 457 snprintf(temp, sizeof(int) + 1, "%d", AVB_ATX_PSK_VERSION_LOCATION); 458 strncat(buffer, temp, ROLLBACK_MAX_SIZE); 459 strncat(buffer, ":", 1); 460 snprintf(temp, sizeof(uint64_t) + 1, "%lld", stored_rollback_index); 461 strncat(buffer, temp, ROLLBACK_MAX_SIZE); 462 debug("%s\n", buffer); 463 avb_ops_user_free(ops); 464 465 return 0; 466 out: 467 avb_ops_user_free(ops); 468 469 return -1; 470 } 471 472 int rk_avb_read_bootloader_locked_flag(uint8_t *flag) 473 { 474 #ifdef CONFIG_OPTEE_CLIENT 475 if (trusty_read_vbootkey_enable_flag(flag)) { 476 return -1; 477 } 478 return 0; 479 #else 480 return -1; 481 #endif 482 } 483 484 #ifdef CONFIG_SUPPORT_EMMC_RPMB 485 static int curr_device = -1; 486 487 int rk_bootloader_rollback_index_read(uint32_t offset, uint32_t bytes, 488 void *rb_index) 489 { 490 491 struct mmc *mmc; 492 uint8_t rpmb_buf[256] = {0}; 493 uint32_t n; 494 char original_part; 495 496 if ((offset + bytes) > 256) 497 return -1; 498 499 if (curr_device < 0) { 500 if (get_mmc_num() > 0) 501 curr_device = 0; 502 else { 503 avb_error("No MMC device available"); 504 return -1; 505 } 506 } 507 508 mmc = find_mmc_device(curr_device); 509 /* Switch to the RPMB partition */ 510 #ifndef CONFIG_BLK 511 original_part = mmc->block_dev.hwpart; 512 #else 513 original_part = mmc_get_blk_desc(mmc)->hwpart; 514 #endif 515 if (blk_select_hwpart_devnum(IF_TYPE_MMC, curr_device, MMC_PART_RPMB) != 516 0) 517 return -1; 518 519 n = mmc_rpmb_read(mmc, rpmb_buf, RPMB_BASE_ADDR, 1, NULL); 520 if (n != 1) 521 return -1; 522 523 /* Return to original partition */ 524 if (blk_select_hwpart_devnum(IF_TYPE_MMC, curr_device, original_part) != 525 0) 526 return -1; 527 528 memcpy(rb_index, (void*)&rpmb_buf[offset], bytes); 529 530 return 0; 531 } 532 533 int rk_avb_get_bootloader_min_version(char *buffer) 534 { 535 uint32_t rb_index; 536 char temp[ROLLBACK_MAX_SIZE] = {0}; 537 538 if (rk_bootloader_rollback_index_read(UBOOT_RB_INDEX_OFFSET, 539 sizeof(uint32_t), &rb_index)) { 540 avb_error("Can not read uboot rollback index"); 541 return -1; 542 } 543 snprintf(temp, sizeof(int) + 1, "%d", 0); 544 strncat(buffer, temp, ROLLBACK_MAX_SIZE); 545 strncat(buffer, ":", 1); 546 snprintf(temp, sizeof(uint32_t) + 1, "%d", rb_index); 547 strncat(buffer, temp, ROLLBACK_MAX_SIZE); 548 strncat(buffer, ",", 1); 549 550 if (rk_bootloader_rollback_index_read(TRUST_RB_INDEX_OFFSET, 551 sizeof(uint32_t), &rb_index)) { 552 avb_error("Can not read trust rollback index"); 553 return -1; 554 } 555 556 snprintf(temp, sizeof(int) + 1, "%d", 1); 557 strncat(buffer, temp, ROLLBACK_MAX_SIZE); 558 strncat(buffer, ":", 1); 559 snprintf(temp, sizeof(uint32_t) + 1, "%d", rb_index); 560 strncat(buffer, temp, ROLLBACK_MAX_SIZE); 561 562 return 0; 563 } 564 #endif 565 566 void rk_avb_get_at_vboot_state(char *buf) 567 { 568 char temp_flag = 0; 569 char *lock_val = NULL; 570 char *unlock_dis_val = NULL; 571 char *perm_attr_flag = NULL; 572 char *bootloader_locked_flag = NULL; 573 char *rollback_indices; 574 char min_versions[ROLLBACK_MAX_SIZE + 1] = {0}; 575 int n; 576 577 if (rk_avb_read_perm_attr_flag((uint8_t *)&temp_flag)) { 578 avb_error("Can not read perm_attr_flag!"); 579 perm_attr_flag = ""; 580 } else { 581 perm_attr_flag = temp_flag ? "1" : "0"; 582 } 583 584 temp_flag = 0; 585 if (rk_avb_read_lock_state((uint8_t *)&temp_flag)) { 586 avb_error("Can not read lock state!"); 587 lock_val = ""; 588 unlock_dis_val = ""; 589 } else { 590 lock_val = (temp_flag & LOCK_MASK) ? "0" : "1"; 591 unlock_dis_val = (temp_flag & UNLOCK_DISABLE_MASK) ? "1" : "0"; 592 } 593 594 temp_flag = 0; 595 if (rk_avb_read_bootloader_locked_flag((uint8_t *)&temp_flag)) { 596 avb_error("Can not read bootloader locked flag!"); 597 bootloader_locked_flag = ""; 598 } else { 599 bootloader_locked_flag = temp_flag ? "1" : "0"; 600 } 601 602 rollback_indices = malloc(VBOOT_STATE_SIZE); 603 if (!rollback_indices) { 604 avb_error("No buff to malloc!"); 605 return; 606 } 607 608 memset(rollback_indices, 0, VBOOT_STATE_SIZE); 609 if (rk_avb_read_all_rollback_index(rollback_indices)) 610 avb_error("Can not read avb_min_ver!"); 611 612 /* bootloader-min-versions */ 613 if (rk_avb_get_bootloader_min_version(min_versions)) 614 avb_error("Call rk_avb_get_bootloader_min_version error!"); 615 616 n = snprintf(buf, VBOOT_STATE_SIZE - 1, 617 "avb-perm-attr-set=%s\n" 618 "avb-locked=%s\n" 619 "avb-unlock-disabled=%s\n" 620 "bootloader-locked=%s\n" 621 "avb-min-versions=%s\n" 622 "bootloader-min-versions=%s\n", 623 perm_attr_flag, 624 lock_val, 625 unlock_dis_val, 626 bootloader_locked_flag, 627 rollback_indices, 628 min_versions); 629 if (n >= VBOOT_STATE_SIZE) { 630 avb_error("The VBOOT_STATE buf is truncated\n"); 631 buf[VBOOT_STATE_SIZE - 1] = 0; 632 } 633 debug("The vboot state buf is %s\n", buf); 634 free(rollback_indices); 635 } 636 637 int rk_avb_get_ab_info(AvbABData* ab_data) 638 { 639 AvbOps* ops; 640 AvbIOResult io_ret = AVB_IO_RESULT_OK; 641 int ret = 0; 642 643 ops = avb_ops_user_new(); 644 if (ops == NULL) { 645 printf("%s: avb_ops_user_new() failed!\n", __FILE__); 646 return -1; 647 } 648 649 io_ret = ops->ab_ops->read_ab_metadata(ops->ab_ops, ab_data); 650 if (io_ret != AVB_IO_RESULT_OK) { 651 avb_error("I/O error while loading A/B metadata.\n"); 652 ret = -1; 653 } 654 655 avb_ops_user_free(ops); 656 657 return ret; 658 } 659 660 int rk_avb_get_part_has_slot_info(const char *base_name) 661 { 662 char *part_name; 663 int part_num; 664 size_t part_name_len; 665 disk_partition_t part_info; 666 struct blk_desc *dev_desc; 667 const char *slot_suffix = "_a"; 668 669 dev_desc = rockchip_get_bootdev(); 670 if (!dev_desc) { 671 printf("%s: Could not find device!\n", __func__); 672 return -1; 673 } 674 675 if (base_name == NULL) { 676 printf("The base_name is NULL!\n"); 677 return -1; 678 } 679 680 part_name_len = strlen(base_name) + 1; 681 part_name_len += strlen(slot_suffix); 682 part_name = malloc(part_name_len); 683 if (!part_name) { 684 printf("%s can not malloc a buffer!\n", __FILE__); 685 return -1; 686 } 687 688 memset(part_name, 0, part_name_len); 689 snprintf(part_name, part_name_len, "%s%s", base_name, slot_suffix); 690 part_num = part_get_info_by_name(dev_desc, part_name, &part_info); 691 if (part_num < 0) { 692 printf("Could not find partition \"%s\"\n", part_name); 693 part_num = -1; 694 } 695 696 free(part_name); 697 return part_num; 698 } 699 700 int rk_auth_unlock(void *buffer, char *out_is_trusted) 701 { 702 AvbOps* ops; 703 704 ops = avb_ops_user_new(); 705 if (ops == NULL) { 706 avb_error("avb_ops_user_new() failed!"); 707 return -1; 708 } 709 710 if (avb_atx_validate_unlock_credential(ops->atx_ops, 711 (AvbAtxUnlockCredential*)buffer, 712 (bool*)out_is_trusted)) { 713 avb_ops_user_free(ops); 714 return -1; 715 } 716 avb_ops_user_free(ops); 717 if (*out_is_trusted == true) 718 return 0; 719 else 720 return -1; 721 } 722 723 int rk_generate_unlock_challenge(void *buffer, uint32_t *challenge_len) 724 { 725 AvbOps* ops; 726 AvbIOResult result = AVB_IO_RESULT_OK; 727 728 ops = avb_ops_user_new(); 729 if (ops == NULL) { 730 avb_error("avb_ops_user_new() failed!"); 731 return -1; 732 } 733 734 result = avb_atx_generate_unlock_challenge(ops->atx_ops, 735 (AvbAtxUnlockChallenge *)buffer); 736 avb_ops_user_free(ops); 737 *challenge_len = sizeof(AvbAtxUnlockChallenge); 738 if (result == AVB_IO_RESULT_OK) 739 return 0; 740 else 741 return -1; 742 } 743 744 int rk_get_lastboot(void) 745 { 746 747 AvbIOResult io_ret = AVB_IO_RESULT_OK; 748 AvbABData ab_data; 749 int lastboot = -1; 750 AvbOps* ops; 751 752 ops = avb_ops_user_new(); 753 if (ops == NULL) { 754 printf("avb_ops_user_new() failed!\n"); 755 return -1; 756 } 757 758 io_ret = ops->ab_ops->read_ab_metadata(ops->ab_ops, &ab_data); 759 if (io_ret != AVB_IO_RESULT_OK) { 760 avb_error("I/O error while loading A/B metadata.\n"); 761 goto out; 762 } 763 764 lastboot = ab_data.last_boot; 765 out: 766 avb_ops_user_free(ops); 767 768 return lastboot; 769 } 770 771 int rk_avb_init_ab_metadata(void) 772 { 773 AvbOps *ops; 774 AvbABData ab_data; 775 776 memset(&ab_data, 0, sizeof(AvbABData)); 777 debug("sizeof(AvbABData) = %d\n", (int)(size_t)sizeof(AvbABData)); 778 779 ops = avb_ops_user_new(); 780 if (ops == NULL) { 781 printf("avb_ops_user_new() failed!\n"); 782 return -1; 783 } 784 785 avb_ab_data_init(&ab_data); 786 if (ops->ab_ops->write_ab_metadata(ops->ab_ops, &ab_data) != 0) { 787 printf("do_avb_init_ab_metadata error!\n"); 788 avb_ops_user_free(ops); 789 return -1; 790 } 791 792 printf("Initialize ab data to misc partition success.\n"); 793 avb_ops_user_free(ops); 794 795 return 0; 796 }