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