1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7 #include <android_bootloader.h> 8 #include <android_avb/avb_version.h> 9 #include <android_avb/avb_ab_flow.h> 10 #include <android_avb/avb_ops_user.h> 11 #include <android_cmds.h> 12 #include <malloc.h> 13 #include <common.h> 14 #include <bootm.h> 15 #include <command.h> 16 #include <android_bootloader_message.h> 17 18 static int do_boot_android(cmd_tbl_t *cmdtp, int flag, int argc, 19 char * const argv[]) 20 { 21 unsigned long load_address; 22 int ret = CMD_RET_SUCCESS; 23 char *addr_arg_endp, *addr_str; 24 struct blk_desc *dev_desc; 25 disk_partition_t part_info; 26 27 if (argc < 4) 28 return CMD_RET_USAGE; 29 if (argc > 5) 30 return CMD_RET_USAGE; 31 32 if (argc >= 5) { 33 load_address = simple_strtoul(argv[4], &addr_arg_endp, 16); 34 if (addr_arg_endp == argv[4] || *addr_arg_endp != '\0') 35 return CMD_RET_USAGE; 36 } else { 37 addr_str = env_get("loadaddr"); 38 if (addr_str) 39 load_address = simple_strtoul(addr_str, NULL, 16); 40 else 41 load_address = CONFIG_SYS_LOAD_ADDR; 42 } 43 44 if (part_get_info_by_dev_and_name_or_num(argv[1], argv[2], 45 &dev_desc, &part_info) < 0) { 46 return CMD_RET_FAILURE; 47 } 48 49 ret = android_bootloader_boot_flow(dev_desc, &part_info, argv[3], 50 load_address); 51 if (ret < 0) { 52 printf("Android boot failed, error %d.\n", ret); 53 return CMD_RET_FAILURE; 54 } 55 return CMD_RET_SUCCESS; 56 } 57 58 U_BOOT_CMD( 59 boot_android, 5, 0, do_boot_android, 60 "Execute the Android Bootloader flow.", 61 "<interface> <dev[:part|;part_name]> <slot> [<kernel_addr>]\n" 62 " - Load the Boot Control Block (BCB) from the partition 'part' on\n" 63 " device type 'interface' instance 'dev' to determine the boot\n" 64 " mode, and load and execute the appropriate kernel.\n" 65 " In normal and recovery mode, the kernel will be loaded from\n" 66 " the corresponding \"boot\" partition. In bootloader mode, the\n" 67 " command defined in the \"fastbootcmd\" variable will be\n" 68 " executed.\n" 69 " On Android devices with multiple slots, the pass 'slot' is\n" 70 " used to load the appropriate kernel. The standard slot names\n" 71 " are 'a' and 'b'.\n" 72 " - If 'part_name' is passed, preceded with a ; instead of :, the\n" 73 " partition name whose label is 'part_name' will be looked up in\n" 74 " the partition table. This is commonly the \"misc\" partition.\n" 75 ); 76 77 #ifdef CONFIG_AVB_LIBAVB_USER 78 static int bootloader_message_read(struct android_bootloader_message *data) 79 { 80 AvbOps *ops; 81 char requested_partitions[] = "misc"; 82 size_t out_num_read; 83 char *buffer; 84 85 ops = avb_ops_user_new(); 86 buffer = (char *)data; 87 88 if (ops == NULL) { 89 printf("avb_ops_user_new() failed!\n"); 90 return CMD_RET_FAILURE; 91 } 92 93 if (ops->read_from_partition(ops, requested_partitions, 94 0, 2048, buffer, 95 &out_num_read) != 0) { 96 printf("do avb read error!\n"); 97 avb_ops_user_free(ops); 98 return CMD_RET_FAILURE; 99 } 100 101 avb_ops_user_free(ops); 102 103 return CMD_RET_SUCCESS; 104 } 105 106 static int bootloader_message_write(struct android_bootloader_message *data) 107 { 108 AvbOps *ops; 109 char requested_partitions[] = "misc"; 110 char *buffer; 111 112 ops = avb_ops_user_new(); 113 buffer = (char *)data; 114 115 if (ops == NULL) { 116 printf("avb_ops_user_new() failed!\n"); 117 return CMD_RET_FAILURE; 118 } 119 120 if (ops->write_to_partition(ops, requested_partitions, 121 0, 2048, buffer) != 0) { 122 printf("do avb write error!\n"); 123 avb_ops_user_free(ops); 124 return CMD_RET_FAILURE; 125 } 126 127 avb_ops_user_free(ops); 128 129 return CMD_RET_SUCCESS; 130 } 131 132 int do_avb_init_ab_metadata(cmd_tbl_t *cmdtp, int flag, 133 int argc, char * const argv[]) 134 { 135 AvbOps *ops; 136 AvbABData ab_data; 137 138 memset(&ab_data, 0, sizeof(AvbABData)); 139 debug("sizeof(AvbABData) = %d\n", sizeof(AvbABData)); 140 if (argc != 1) 141 return CMD_RET_USAGE; 142 143 ops = avb_ops_user_new(); 144 if (ops == NULL) { 145 printf("avb_ops_user_new() failed!\n"); 146 return CMD_RET_FAILURE; 147 } 148 149 ops->ab_ops->init_ab_metadata(&ab_data); 150 debug("init"); 151 if (ops->ab_ops->write_ab_metadata(ops->ab_ops, &ab_data) != 0) { 152 printf("do_avb_init_ab_metadata error!\n"); 153 avb_ops_user_free(ops); 154 return CMD_RET_FAILURE; 155 } 156 157 avb_ops_user_free(ops); 158 159 return CMD_RET_SUCCESS; 160 } 161 162 int do_avb_version(cmd_tbl_t *cmdtp, int flag, int argc, 163 char * const argv[]) 164 { 165 const char *avb_version; 166 167 if (argc != 1) 168 return CMD_RET_USAGE; 169 170 avb_version = avb_version_string(); 171 printf("Android avb version is %s.\n", avb_version); 172 173 return CMD_RET_SUCCESS; 174 } 175 176 int do_avb_ab_mark_slot_active(cmd_tbl_t *cmdtp, int flag, 177 int argc, char * const argv[]) 178 { 179 AvbOps *ops; 180 unsigned int slot_number; 181 182 if (argc != 2) 183 return CMD_RET_USAGE; 184 185 ops = avb_ops_user_new(); 186 if (ops == NULL) { 187 printf("avb_ops_user_new() failed!\n"); 188 return CMD_RET_FAILURE; 189 } 190 191 slot_number = simple_strtoul(argv[1], NULL, 16); 192 if (avb_ab_mark_slot_active(ops->ab_ops, slot_number) != 0) { 193 printf("avb_ab_mark_slot_active error!\n"); 194 avb_ops_user_free(ops); 195 return CMD_RET_FAILURE; 196 } 197 198 avb_ops_user_free(ops); 199 200 return CMD_RET_SUCCESS; 201 } 202 203 int do_avb_ab_mark_slot_unbootable(cmd_tbl_t *cmdtp, int flag, 204 int argc, char * const argv[]) 205 { 206 AvbOps *ops; 207 unsigned int slot_number; 208 209 if (argc != 2) 210 return CMD_RET_USAGE; 211 212 ops = avb_ops_user_new(); 213 if (ops == NULL) { 214 printf("avb_ops_user_new() failed!\n"); 215 return CMD_RET_FAILURE; 216 } 217 218 slot_number = simple_strtoul(argv[1], NULL, 16); 219 if (avb_ab_mark_slot_unbootable(ops->ab_ops, slot_number) != 0) { 220 printf("do_avb_ab_mark_slot_unbootable error!\n"); 221 avb_ops_user_free(ops); 222 return CMD_RET_FAILURE; 223 } 224 225 avb_ops_user_free(ops); 226 227 return CMD_RET_SUCCESS; 228 } 229 230 int do_avb_ab_mark_slot_successful(cmd_tbl_t *cmdtp, int flag, 231 int argc, char * const argv[]) 232 { 233 AvbOps *ops; 234 unsigned int slot_number; 235 236 if (argc != 2) 237 return CMD_RET_USAGE; 238 239 ops = avb_ops_user_new(); 240 if (ops == NULL) { 241 printf("avb_ops_user_new() failed!\n"); 242 return CMD_RET_FAILURE; 243 } 244 245 slot_number = simple_strtoul(argv[1], NULL, 16); 246 if (avb_ab_mark_slot_successful(ops->ab_ops, slot_number) != 0) { 247 printf("do_avb_ab_mark_slot_successful error!\n"); 248 avb_ops_user_free(ops); 249 return CMD_RET_FAILURE; 250 } 251 252 avb_ops_user_free(ops); 253 254 return CMD_RET_SUCCESS; 255 } 256 257 int do_avb_read_rollback_index(cmd_tbl_t *cmdtp, int flag, 258 int argc, char * const argv[]) 259 { 260 AvbOps *ops; 261 uint64_t out_rollback_index; 262 size_t rollback_index_location; 263 264 if (argc != 2) 265 return CMD_RET_USAGE; 266 267 ops = avb_ops_user_new(); 268 if (ops == NULL) { 269 printf("avb_ops_user_new() failed!\n"); 270 return CMD_RET_FAILURE; 271 } 272 273 rollback_index_location = simple_strtoul(argv[1], NULL, 16); 274 if (ops->read_rollback_index(ops, rollback_index_location, 275 &out_rollback_index) != 0) { 276 printf("do_avb_read_rollback_index error!\n"); 277 avb_ops_user_free(ops); 278 return CMD_RET_FAILURE; 279 } 280 281 printf("out_rollback_index = %llx\n", out_rollback_index); 282 avb_ops_user_free(ops); 283 284 return CMD_RET_SUCCESS; 285 } 286 287 int do_avb_write_rollback_index(cmd_tbl_t *cmdtp, int flag, 288 int argc, char * const argv[]) 289 { 290 AvbOps *ops; 291 uint64_t out_rollback_index; 292 size_t rollback_index_location; 293 294 if (argc != 3) 295 return CMD_RET_USAGE; 296 297 rollback_index_location = simple_strtoul(argv[1], NULL, 16); 298 out_rollback_index = simple_strtoull(argv[2], NULL, 16); 299 debug("out_rollback_index = %llx\n", out_rollback_index); 300 ops = avb_ops_user_new(); 301 if (ops == NULL) { 302 printf("avb_ops_user_new() failed!\n"); 303 return CMD_RET_FAILURE; 304 } 305 306 if (ops->write_rollback_index(ops, rollback_index_location, 307 out_rollback_index) != 0) { 308 printf("do_avb_write_rollback_index error!\n"); 309 avb_ops_user_free(ops); 310 return CMD_RET_FAILURE; 311 } 312 313 avb_ops_user_free(ops); 314 315 return CMD_RET_SUCCESS; 316 } 317 318 int do_avb_read_is_device_unlocked(cmd_tbl_t *cmdtp, int flag, 319 int argc, char * const argv[]) 320 { 321 AvbOps *ops; 322 bool out_is_unlocked; 323 324 if (argc != 1) 325 return CMD_RET_USAGE; 326 327 ops = avb_ops_user_new(); 328 if (ops == NULL) { 329 printf("avb_ops_user_new() failed!\n"); 330 return CMD_RET_FAILURE; 331 } 332 333 if (ops->read_is_device_unlocked(ops, &out_is_unlocked) != 0) { 334 printf("do_avb_read_is_device_unlocked error!\n"); 335 avb_ops_user_free(ops); 336 return CMD_RET_FAILURE; 337 } 338 339 debug("out_is_unlocked = %d\n", out_is_unlocked); 340 avb_ops_user_free(ops); 341 342 return CMD_RET_SUCCESS; 343 } 344 int do_avb_write_is_device_unlocked(cmd_tbl_t *cmdtp, int flag, 345 int argc, char * const argv[]) 346 { 347 AvbOps *ops; 348 bool out_is_unlocked; 349 350 if (argc != 2) 351 return CMD_RET_USAGE; 352 353 out_is_unlocked = simple_strtoul(argv[1], NULL, 16); 354 if ((out_is_unlocked != 0) || (out_is_unlocked != 1)) 355 printf("enter out_is_unlocked value must is '0' or '1'\n"); 356 357 ops = avb_ops_user_new(); 358 if (ops == NULL) { 359 printf("avb_ops_user_new() failed!\n"); 360 return CMD_RET_FAILURE; 361 } 362 363 if (ops->write_is_device_unlocked(ops, &out_is_unlocked) != 0) { 364 printf("do_avb_write_is_device_unlocked error!\n"); 365 avb_ops_user_free(ops); 366 return CMD_RET_FAILURE; 367 } 368 369 debug("out_is_unlocked = %d\n", out_is_unlocked); 370 avb_ops_user_free(ops); 371 372 return CMD_RET_SUCCESS; 373 } 374 375 int do_avb_get_size_of_partition(cmd_tbl_t *cmdtp, int flag, 376 int argc, char * const argv[]) 377 { 378 AvbOps *ops; 379 char *requested_partitions; 380 uint64_t out_size_in_bytes; 381 382 if (argc != 2) 383 return CMD_RET_USAGE; 384 385 requested_partitions = argv[1]; 386 ops = avb_ops_user_new(); 387 if (ops == NULL) { 388 printf("avb_ops_user_new() failed!\n"); 389 return CMD_RET_FAILURE; 390 } 391 392 if (ops->get_size_of_partition(ops, requested_partitions, 393 &out_size_in_bytes) != 0) { 394 printf("do_avb_get_size_of_partition error!\n"); 395 avb_ops_user_free(ops); 396 return CMD_RET_FAILURE; 397 } 398 399 printf("partition size = %lld\n", out_size_in_bytes); 400 avb_ops_user_free(ops); 401 402 return CMD_RET_SUCCESS; 403 } 404 405 int do_avb_get_get_unique_guid_for_partition(cmd_tbl_t *cmdtp, int flag, 406 int argc, char * const argv[]) 407 { 408 AvbOps *ops; 409 char *requested_partitions; 410 size_t guid_buf_size = 37; 411 char guid_buf[37]; 412 413 if (argc != 2) 414 return CMD_RET_USAGE; 415 416 requested_partitions = argv[1]; 417 ops = avb_ops_user_new(); 418 if (ops == NULL) { 419 printf("avb_ops_user_new() failed!\n"); 420 return CMD_RET_FAILURE; 421 } 422 423 if (ops->get_unique_guid_for_partition(ops, requested_partitions, 424 guid_buf, guid_buf_size) != 0) { 425 printf("do_avb_get_get_unique_guid_for_partition error!\n"); 426 avb_ops_user_free(ops); 427 return CMD_RET_FAILURE; 428 } 429 430 printf("guid = %s\n", guid_buf); 431 avb_ops_user_free(ops); 432 433 return CMD_RET_SUCCESS; 434 } 435 436 int do_avb_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 437 { 438 AvbOps *ops; 439 char *requested_partitions; 440 int64_t offset_blk; 441 size_t blkcnt; 442 size_t out_num_read; 443 int i; 444 char *buffer; 445 446 if (argc != 4) 447 return CMD_RET_USAGE; 448 449 requested_partitions = argv[1]; 450 offset_blk = simple_strtoul(argv[2], NULL, 16); 451 blkcnt = simple_strtoul(argv[3], NULL, 16); 452 ops = avb_ops_user_new(); 453 buffer = (char *)malloc(blkcnt * 512); 454 if (buffer == NULL) 455 printf("malloc buffer failed!\n"); 456 457 if (ops == NULL) { 458 printf("avb_ops_user_new() failed!\n"); 459 return CMD_RET_FAILURE; 460 } 461 462 if (ops->read_from_partition(ops, requested_partitions, 463 offset_blk, blkcnt, buffer, 464 &out_num_read) != 0) { 465 printf("do avb read error!\n"); 466 free(buffer); 467 avb_ops_user_free(ops); 468 return CMD_RET_FAILURE; 469 } 470 471 for (i = 0; i < 512 * blkcnt; i++) 472 printf("buffer %d = %d\n", i, buffer[i]); 473 474 free(buffer); 475 avb_ops_user_free(ops); 476 477 return CMD_RET_SUCCESS; 478 } 479 480 int do_avb_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 481 { 482 AvbOps *ops; 483 char *requested_partitions; 484 int64_t offset_blk; 485 size_t blkcnt; 486 size_t out_num_read; 487 char *buffer; 488 489 if (argc != 4) 490 return CMD_RET_USAGE; 491 492 requested_partitions = argv[1]; 493 offset_blk = simple_strtoul(argv[2], NULL, 16); 494 blkcnt = simple_strtoul(argv[3], NULL, 16); 495 ops = avb_ops_user_new(); 496 buffer = (char *)malloc(blkcnt * 512); 497 if (buffer == NULL) { 498 printf("malloc buffer failed!\n"); 499 return CMD_RET_FAILURE; 500 } 501 502 if (ops == NULL) { 503 printf("avb_ops_user_new() failed!\n"); 504 return CMD_RET_FAILURE; 505 } 506 if (ops->read_from_partition(ops, requested_partitions, offset_blk, 507 blkcnt, buffer, &out_num_read) != 0) { 508 printf("do_avb_write error!\n"); 509 free(buffer); 510 avb_ops_user_free(ops); 511 return CMD_RET_FAILURE; 512 } 513 514 free(buffer); 515 avb_ops_user_free(ops); 516 517 return CMD_RET_SUCCESS; 518 } 519 520 int do_avb_load_ab_metadata(cmd_tbl_t *cmdtp, int flag, 521 int argc, char * const argv[]) 522 { 523 AvbOps *ops; 524 AvbABData ab_data, ab_data_orig; 525 char *data; 526 int i; 527 528 if (argc != 1) 529 return CMD_RET_USAGE; 530 531 ops = avb_ops_user_new(); 532 if (ops == NULL) { 533 printf("avb_ops_user_new() failed!\n"); 534 return CMD_RET_FAILURE; 535 } 536 537 if (load_metadata(ops->ab_ops, &ab_data, &ab_data_orig) != 0) { 538 printf("do_avb_write_ab_metadata error!\n"); 539 avb_ops_user_free(ops); 540 return CMD_RET_FAILURE; 541 } 542 543 data = (char *)&ab_data; 544 for (i = 0; i < 33; i++) 545 printf("%d\n", data[i]); 546 547 avb_ops_user_free(ops); 548 549 return CMD_RET_SUCCESS; 550 } 551 552 int do_avb_read_ab_metadata(cmd_tbl_t *cmdtp, int flag, 553 int argc, char * const argv[]) 554 { 555 AvbOps *ops; 556 AvbABData ab_data; 557 558 if (argc != 1) 559 return CMD_RET_USAGE; 560 561 ops = avb_ops_user_new(); 562 if (ops == NULL) { 563 printf("avb_ops_user_new() failed!\n"); 564 return CMD_RET_FAILURE; 565 } 566 567 if (ops->ab_ops->read_ab_metadata(ops->ab_ops, &ab_data) != 0) { 568 printf("do_avb_write_ab_metadata error!\n"); 569 avb_ops_user_free(ops); 570 return CMD_RET_FAILURE; 571 } 572 573 avb_ops_user_free(ops); 574 575 return CMD_RET_SUCCESS; 576 } 577 578 int do_avb_write_ab_metadata(cmd_tbl_t *cmdtp, int flag, 579 int argc, char * const argv[]) 580 { 581 AvbOps *ops; 582 AvbABData ab_data; 583 584 if (argc != 1) 585 return CMD_RET_USAGE; 586 587 ops = avb_ops_user_new(); 588 if (ops == NULL) { 589 printf("avb_ops_user_new() failed!\n"); 590 return CMD_RET_FAILURE; 591 } 592 593 if (ops->ab_ops->write_ab_metadata(ops->ab_ops, &ab_data) != 0) { 594 printf("do_avb_write_ab_metadata error!\n"); 595 avb_ops_user_free(ops); 596 return CMD_RET_FAILURE; 597 } 598 599 avb_ops_user_free(ops); 600 601 return CMD_RET_SUCCESS; 602 } 603 604 int do_avb_verify_partition(cmd_tbl_t *cmdtp, int flag, 605 int argc, char * const argv[]) 606 { 607 AvbOps *ops; 608 const char *requested_partitions[1]; 609 const char * slot_suffixes[2] = {"_a", "_b"}; 610 AvbSlotVerifyFlags flags; 611 AvbSlotVerifyData *slot_data[2] = {NULL, NULL}; 612 AvbSlotVerifyResult verify_result; 613 size_t n; 614 615 if (argc != 3) 616 return CMD_RET_USAGE; 617 618 requested_partitions[0] = argv[1]; 619 n = simple_strtoul(argv[2], NULL, 16); 620 ops = avb_ops_user_new(); 621 flags = AVB_SLOT_VERIFY_FLAGS_NONE; 622 verify_result = 623 avb_slot_verify(ops, 624 requested_partitions, 625 slot_suffixes[n], 626 flags, 627 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, 628 &slot_data[n]); 629 if (verify_result != 0) 630 return CMD_RET_FAILURE; 631 632 avb_ops_user_free(ops); 633 634 return CMD_RET_SUCCESS; 635 } 636 637 int do_avb_flow(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 638 { 639 char slot_partition[2][20] = {{0}, {0}}; 640 unsigned long load_address; 641 AvbOps *ops; 642 const char *avb_version; 643 AvbSlotVerifyData *slot_data; 644 AvbSlotVerifyFlags flags; 645 const char *requested_partitions[] = {"boot", "system", NULL}; 646 char *command_line; 647 bool unlocked = true; 648 const char *mode_cmdline = NULL; 649 char root_data[70] = "root=PARTUUID="; 650 size_t guid_buf_size = 37; 651 char guid_buf[37]; 652 char verify_flag; 653 char boot_slot_select[5]; 654 struct android_bootloader_message data; 655 const char *fastboot_cmd = env_get("fastbootcmd"); 656 657 if (argc != 2) 658 return CMD_RET_USAGE; 659 660 bootloader_message_read(&data); 661 if (!strcmp("bootonce-bootloader", data.command)) { 662 memset(data.command, 0, sizeof(data.command)); 663 bootloader_message_write(&data); 664 if (fastboot_cmd) { 665 printf("bootonce-bootloader!\n"); 666 return run_command(fastboot_cmd, CMD_FLAG_ENV); 667 } else { 668 printf("The fastbootcmd is NULL!\n"); 669 return CMD_RET_SUCCESS; 670 } 671 } else if (!strcmp("boot-recovery", data.command)) { 672 printf("Enter boot-recovery!\n"); 673 } else if(!strcmp("boot-normal", data.command)) { 674 printf("Enter boot-normal!\n"); 675 mode_cmdline = "skip_initramfs"; 676 } else { 677 /* 678 * Firstly, confirm if there is a command in misc partition in 679 * previous cases, and then we need to confirm whether user has 680 * requested to enter recovery mode by entering "reboot recovery" 681 * command through adb or serial console. 682 */ 683 char *env_rebootmode = env_get("reboot_mode"); 684 685 if (env_rebootmode && !strcmp("recovery", env_rebootmode)) 686 printf("Enter recovery mode by command 'reboot recovery'!\n"); 687 else 688 mode_cmdline = "skip_initramfs"; 689 } 690 691 avb_version = avb_version_string(); 692 printf("Android avb version is %s.\n", avb_version); 693 ops = avb_ops_user_new(); 694 if (ops == NULL) 695 printf("avb_ops_user_new() failed!\n"); 696 697 if (ops->read_is_device_unlocked(ops, &unlocked) != 0) 698 printf("Error determining whether device is unlocked.\n"); 699 700 printf("read_is_device_unlocked() ops returned that device is %s\n", 701 unlocked ? "UNLOCKED" : "LOCKED"); 702 703 flags = AVB_SLOT_VERIFY_FLAGS_NONE; 704 if (unlocked) 705 flags |= AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR; 706 707 verify_flag = argv[1][0]; 708 if (verify_flag == 'v') { 709 debug("start with verify!\n"); 710 if (avb_ab_flow(ops->ab_ops, 711 requested_partitions, 712 flags, 713 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, 714 &slot_data)) { 715 avb_slot_verify_data_free(slot_data); 716 avb_ops_user_free(ops); 717 printf("avb_ab_flow() error!\n"); 718 return CMD_RET_FAILURE; 719 } 720 721 strcat(slot_partition[1], requested_partitions[1]); 722 strcat(slot_partition[1], slot_data->ab_suffix); 723 ops->get_unique_guid_for_partition(ops, 724 slot_partition[1], 725 guid_buf, 726 guid_buf_size); 727 strcat(root_data, guid_buf); 728 command_line = android_assemble_cmdline(slot_data->ab_suffix, 729 mode_cmdline); 730 strcat(root_data, " "); 731 strcat(root_data, command_line); 732 env_set("bootargs", root_data); 733 load_address = CONFIG_SYS_LOAD_ADDR; 734 if (avb_close_optee_client()) 735 printf("Can not close optee client!\n"); 736 737 memcpy((uint8_t*)load_address, 738 slot_data->loaded_partitions->data, 739 slot_data->loaded_partitions->data_size); 740 android_bootloader_boot_kernel(load_address); 741 } else if (verify_flag == 'n') { 742 load_address = CONFIG_SYS_LOAD_ADDR; 743 avb_ab_slot_select(ops->ab_ops, boot_slot_select); 744 strcat(slot_partition[1], requested_partitions[1]); 745 strcat(slot_partition[1], boot_slot_select); 746 printf("%s\n", slot_partition[1]); 747 ops->get_unique_guid_for_partition(ops, 748 slot_partition[1], 749 guid_buf, 750 guid_buf_size); 751 strcat(root_data, guid_buf); 752 command_line = android_assemble_cmdline(boot_slot_select, 753 mode_cmdline); 754 strcat(root_data, " "); 755 strcat(root_data, command_line); 756 env_set("bootargs", root_data); 757 android_avb_boot_flow(boot_slot_select, load_address); 758 } else { 759 return CMD_RET_USAGE; 760 } 761 762 return CMD_RET_SUCCESS; 763 } 764 765 static cmd_tbl_t cmd_avb[] = { 766 U_BOOT_CMD_MKENT(init, 1, 1, do_avb_init_ab_metadata, "", ""), 767 U_BOOT_CMD_MKENT(version, 1, 1, do_avb_version, "", ""), 768 U_BOOT_CMD_MKENT(slot_active, 2, 1, 769 do_avb_ab_mark_slot_active, "", ""), 770 U_BOOT_CMD_MKENT(slot_unbootable, 2, 1, 771 do_avb_ab_mark_slot_unbootable, "", ""), 772 U_BOOT_CMD_MKENT(slot_successful, 2, 1, 773 do_avb_ab_mark_slot_successful, "", ""), 774 U_BOOT_CMD_MKENT(read_rollback, 2, 1, 775 do_avb_read_rollback_index, "", ""), 776 U_BOOT_CMD_MKENT(write_rollback, 3, 1, 777 do_avb_write_rollback_index, "", ""), 778 U_BOOT_CMD_MKENT(read_lock_status, 1, 1, 779 do_avb_read_is_device_unlocked, "", ""), 780 U_BOOT_CMD_MKENT(write_lock_status, 2, 1, 781 do_avb_write_is_device_unlocked, "", ""), 782 U_BOOT_CMD_MKENT(part_size, 2, 1, 783 do_avb_get_size_of_partition, "", ""), 784 U_BOOT_CMD_MKENT(part_guid, 2, 1, 785 do_avb_get_get_unique_guid_for_partition, "", ""), 786 U_BOOT_CMD_MKENT(read, 4, 1, do_avb_read, "", ""), 787 U_BOOT_CMD_MKENT(write, 4, 1, do_avb_write, "", ""), 788 U_BOOT_CMD_MKENT(loadabmisc, 1, 1, do_avb_load_ab_metadata, "", ""), 789 U_BOOT_CMD_MKENT(readabmisc, 1, 1, do_avb_read_ab_metadata, "", ""), 790 U_BOOT_CMD_MKENT(writeabmisc, 1, 1, do_avb_write_ab_metadata, "", ""), 791 U_BOOT_CMD_MKENT(verify, 3, 1, do_avb_verify_partition, "", ""), 792 U_BOOT_CMD_MKENT(flow, 2, 1, do_avb_flow, "", "") 793 }; 794 795 static int do_boot_avb(cmd_tbl_t *cmdtp, 796 int flag, 797 int argc, 798 char * const argv[]) 799 { 800 cmd_tbl_t *cp; 801 802 cp = find_cmd_tbl(argv[1], cmd_avb, ARRAY_SIZE(cmd_avb)); 803 804 argc--; 805 argv++; 806 807 if (cp == NULL || argc > cp->maxargs) 808 return CMD_RET_USAGE; 809 if (flag == CMD_FLAG_REPEAT && !cp->repeatable) 810 return CMD_RET_SUCCESS; 811 812 return cp->cmd(cmdtp, flag, argc, argv); 813 } 814 815 U_BOOT_CMD( 816 bootavb, 29, 1, do_boot_avb, 817 "Execute the Android avb a/b boot flow.", 818 "init - initialize the avbabmeta\n" 819 "bootavb version - display info of bootavb version\n" 820 "bootavb slot_active cnt\n" 821 "bootavb slot_unbootable cnt\n" 822 "bootavb slot_successful cnt\n" 823 "bootavb read_rollback rollback_index_location\n" 824 "bootavb write_rollback rollback_index_location out_rollback_index\n" 825 "bootavb read_lock_status\n" 826 "bootavb write_lock_status 0 or 1\n" 827 "bootavb part_size partitions_name\n" 828 "bootavb part_guid partitions_name\n" 829 "bootavb read partition offset_blk cnt\n" 830 "bootavb write partition offset_blk cnt\n" 831 "bootavb loadabmisc\n" 832 "bootavb readabmisc\n" 833 "bootavb writeabmisc\n" 834 "bootavb verify partition slot_cnt;partion name without '_a' or '_b'\n" 835 "bootavb flow v/n\n" 836 ); 837 #endif 838