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