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