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 17 static int do_boot_android(cmd_tbl_t *cmdtp, int flag, int argc, 18 char * const argv[]) 19 { 20 unsigned long load_address; 21 int ret = CMD_RET_SUCCESS; 22 char *addr_arg_endp, *addr_str; 23 struct blk_desc *dev_desc; 24 disk_partition_t part_info; 25 26 if (argc < 4) 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("loadaddr"); 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 if (part_get_info_by_dev_and_name_or_num(argv[1], argv[2], 44 &dev_desc, &part_info) < 0) { 45 return CMD_RET_FAILURE; 46 } 47 48 ret = android_bootloader_boot_flow(dev_desc, &part_info, argv[3], 49 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 int do_avb_init_ab_metadata(cmd_tbl_t *cmdtp, int flag, 78 int argc, char * const argv[]) 79 { 80 AvbOps *ops; 81 AvbABData ab_data; 82 83 memset(&ab_data, 0, sizeof(AvbABData)); 84 debug("sizeof(AvbABData) = %d\n", sizeof(AvbABData)); 85 if (argc != 1) 86 return CMD_RET_USAGE; 87 88 ops = avb_ops_user_new(); 89 if (ops == NULL) { 90 printf("avb_ops_user_new() failed!\n"); 91 return CMD_RET_FAILURE; 92 } 93 94 ops->ab_ops->init_ab_metadata(&ab_data); 95 debug("init"); 96 if (ops->ab_ops->write_ab_metadata(ops->ab_ops, &ab_data) != 0) { 97 printf("do_avb_init_ab_metadata error!\n"); 98 avb_ops_user_free(ops); 99 return CMD_RET_FAILURE; 100 } 101 102 avb_ops_user_free(ops); 103 104 return CMD_RET_SUCCESS; 105 } 106 107 int do_avb_version(cmd_tbl_t *cmdtp, int flag, int argc, 108 char * const argv[]) 109 { 110 const char *avb_version; 111 112 if (argc != 1) 113 return CMD_RET_USAGE; 114 115 avb_version = avb_version_string(); 116 printf("Android avb version is %s.\n", avb_version); 117 118 return CMD_RET_SUCCESS; 119 } 120 121 int do_avb_ab_mark_slot_active(cmd_tbl_t *cmdtp, int flag, 122 int argc, char * const argv[]) 123 { 124 AvbOps *ops; 125 unsigned int slot_number; 126 127 if (argc != 2) 128 return CMD_RET_USAGE; 129 130 ops = avb_ops_user_new(); 131 if (ops == NULL) { 132 printf("avb_ops_user_new() failed!\n"); 133 return CMD_RET_FAILURE; 134 } 135 136 slot_number = simple_strtoul(argv[1], NULL, 16); 137 if (avb_ab_mark_slot_active(ops->ab_ops, slot_number) != 0) { 138 printf("avb_ab_mark_slot_active error!\n"); 139 avb_ops_user_free(ops); 140 return CMD_RET_FAILURE; 141 } 142 143 avb_ops_user_free(ops); 144 145 return CMD_RET_SUCCESS; 146 } 147 148 int do_avb_ab_mark_slot_unbootable(cmd_tbl_t *cmdtp, int flag, 149 int argc, char * const argv[]) 150 { 151 AvbOps *ops; 152 unsigned int slot_number; 153 154 if (argc != 2) 155 return CMD_RET_USAGE; 156 157 ops = avb_ops_user_new(); 158 if (ops == NULL) { 159 printf("avb_ops_user_new() failed!\n"); 160 return CMD_RET_FAILURE; 161 } 162 163 slot_number = simple_strtoul(argv[1], NULL, 16); 164 if (avb_ab_mark_slot_unbootable(ops->ab_ops, slot_number) != 0) { 165 printf("do_avb_ab_mark_slot_unbootable error!\n"); 166 avb_ops_user_free(ops); 167 return CMD_RET_FAILURE; 168 } 169 170 avb_ops_user_free(ops); 171 172 return CMD_RET_SUCCESS; 173 } 174 175 int do_avb_ab_mark_slot_successful(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_successful(ops->ab_ops, slot_number) != 0) { 192 printf("do_avb_ab_mark_slot_successful 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_read_rollback_index(cmd_tbl_t *cmdtp, int flag, 203 int argc, char * const argv[]) 204 { 205 AvbOps *ops; 206 uint64_t out_rollback_index; 207 size_t rollback_index_location; 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 rollback_index_location = simple_strtoul(argv[1], NULL, 16); 219 if (ops->read_rollback_index(ops, rollback_index_location, 220 &out_rollback_index) != 0) { 221 printf("do_avb_read_rollback_index error!\n"); 222 avb_ops_user_free(ops); 223 return CMD_RET_FAILURE; 224 } 225 226 printf("out_rollback_index = %llx\n", out_rollback_index); 227 avb_ops_user_free(ops); 228 229 return CMD_RET_SUCCESS; 230 } 231 232 int do_avb_write_rollback_index(cmd_tbl_t *cmdtp, int flag, 233 int argc, char * const argv[]) 234 { 235 AvbOps *ops; 236 uint64_t out_rollback_index; 237 size_t rollback_index_location; 238 239 if (argc != 3) 240 return CMD_RET_USAGE; 241 242 rollback_index_location = simple_strtoul(argv[1], NULL, 16); 243 out_rollback_index = simple_strtoull(argv[2], NULL, 16); 244 debug("out_rollback_index = %llx\n", out_rollback_index); 245 ops = avb_ops_user_new(); 246 if (ops == NULL) { 247 printf("avb_ops_user_new() failed!\n"); 248 return CMD_RET_FAILURE; 249 } 250 251 if (ops->write_rollback_index(ops, rollback_index_location, 252 out_rollback_index) != 0) { 253 printf("do_avb_write_rollback_index error!\n"); 254 avb_ops_user_free(ops); 255 return CMD_RET_FAILURE; 256 } 257 258 avb_ops_user_free(ops); 259 260 return CMD_RET_SUCCESS; 261 } 262 263 int do_avb_read_is_device_unlocked(cmd_tbl_t *cmdtp, int flag, 264 int argc, char * const argv[]) 265 { 266 AvbOps *ops; 267 bool out_is_unlocked; 268 269 if (argc != 1) 270 return CMD_RET_USAGE; 271 272 ops = avb_ops_user_new(); 273 if (ops == NULL) { 274 printf("avb_ops_user_new() failed!\n"); 275 return CMD_RET_FAILURE; 276 } 277 278 if (ops->read_is_device_unlocked(ops, &out_is_unlocked) != 0) { 279 printf("do_avb_read_is_device_unlocked error!\n"); 280 avb_ops_user_free(ops); 281 return CMD_RET_FAILURE; 282 } 283 284 debug("out_is_unlocked = %d\n", out_is_unlocked); 285 avb_ops_user_free(ops); 286 287 return CMD_RET_SUCCESS; 288 } 289 int do_avb_write_is_device_unlocked(cmd_tbl_t *cmdtp, int flag, 290 int argc, char * const argv[]) 291 { 292 AvbOps *ops; 293 bool out_is_unlocked; 294 295 if (argc != 2) 296 return CMD_RET_USAGE; 297 298 out_is_unlocked = simple_strtoul(argv[1], NULL, 16); 299 if ((out_is_unlocked != 0) || (out_is_unlocked != 1)) 300 printf("enter out_is_unlocked value must is '0' or '1'\n"); 301 302 ops = avb_ops_user_new(); 303 if (ops == NULL) { 304 printf("avb_ops_user_new() failed!\n"); 305 return CMD_RET_FAILURE; 306 } 307 308 if (ops->write_is_device_unlocked(ops, &out_is_unlocked) != 0) { 309 printf("do_avb_write_is_device_unlocked error!\n"); 310 avb_ops_user_free(ops); 311 return CMD_RET_FAILURE; 312 } 313 314 debug("out_is_unlocked = %d\n", out_is_unlocked); 315 avb_ops_user_free(ops); 316 317 return CMD_RET_SUCCESS; 318 } 319 320 int do_avb_get_size_of_partition(cmd_tbl_t *cmdtp, int flag, 321 int argc, char * const argv[]) 322 { 323 AvbOps *ops; 324 char *requested_partitions; 325 uint64_t out_size_in_bytes; 326 327 if (argc != 2) 328 return CMD_RET_USAGE; 329 330 requested_partitions = argv[1]; 331 ops = avb_ops_user_new(); 332 if (ops == NULL) { 333 printf("avb_ops_user_new() failed!\n"); 334 return CMD_RET_FAILURE; 335 } 336 337 if (ops->get_size_of_partition(ops, requested_partitions, 338 &out_size_in_bytes) != 0) { 339 printf("do_avb_get_size_of_partition error!\n"); 340 avb_ops_user_free(ops); 341 return CMD_RET_FAILURE; 342 } 343 344 printf("partition size = %lld\n", out_size_in_bytes); 345 avb_ops_user_free(ops); 346 347 return CMD_RET_SUCCESS; 348 } 349 350 int do_avb_get_get_unique_guid_for_partition(cmd_tbl_t *cmdtp, int flag, 351 int argc, char * const argv[]) 352 { 353 AvbOps *ops; 354 char *requested_partitions; 355 size_t guid_buf_size = 37; 356 char guid_buf[37]; 357 358 if (argc != 2) 359 return CMD_RET_USAGE; 360 361 requested_partitions = argv[1]; 362 ops = avb_ops_user_new(); 363 if (ops == NULL) { 364 printf("avb_ops_user_new() failed!\n"); 365 return CMD_RET_FAILURE; 366 } 367 368 if (ops->get_unique_guid_for_partition(ops, requested_partitions, 369 guid_buf, guid_buf_size) != 0) { 370 printf("do_avb_get_get_unique_guid_for_partition error!\n"); 371 avb_ops_user_free(ops); 372 return CMD_RET_FAILURE; 373 } 374 375 printf("guid = %s\n", guid_buf); 376 avb_ops_user_free(ops); 377 378 return CMD_RET_SUCCESS; 379 } 380 381 int do_avb_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 382 { 383 AvbOps *ops; 384 char *requested_partitions; 385 int64_t offset_blk; 386 size_t blkcnt; 387 size_t out_num_read; 388 int i; 389 char *buffer; 390 391 if (argc != 4) 392 return CMD_RET_USAGE; 393 394 requested_partitions = argv[1]; 395 offset_blk = simple_strtoul(argv[2], NULL, 16); 396 blkcnt = simple_strtoul(argv[3], NULL, 16); 397 ops = avb_ops_user_new(); 398 buffer = (char *)malloc(blkcnt * 512); 399 if (buffer == NULL) 400 printf("malloc buffer failed!\n"); 401 402 if (ops == NULL) { 403 printf("avb_ops_user_new() failed!\n"); 404 return CMD_RET_FAILURE; 405 } 406 407 if (ops->read_from_partition(ops, requested_partitions, 408 offset_blk, blkcnt, buffer, 409 &out_num_read) != 0) { 410 printf("do avb read error!\n"); 411 free(buffer); 412 avb_ops_user_free(ops); 413 return CMD_RET_FAILURE; 414 } 415 416 for (i = 0; i < 512 * blkcnt; i++) 417 printf("buffer %d = %d\n", i, buffer[i]); 418 419 free(buffer); 420 avb_ops_user_free(ops); 421 422 return CMD_RET_SUCCESS; 423 } 424 425 int do_avb_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 426 { 427 AvbOps *ops; 428 char *requested_partitions; 429 int64_t offset_blk; 430 size_t blkcnt; 431 size_t out_num_read; 432 char *buffer; 433 434 if (argc != 4) 435 return CMD_RET_USAGE; 436 437 requested_partitions = argv[1]; 438 offset_blk = simple_strtoul(argv[2], NULL, 16); 439 blkcnt = simple_strtoul(argv[3], NULL, 16); 440 ops = avb_ops_user_new(); 441 buffer = (char *)malloc(blkcnt * 512); 442 if (buffer == NULL) { 443 printf("malloc buffer failed!\n"); 444 return CMD_RET_FAILURE; 445 } 446 447 if (ops == NULL) { 448 printf("avb_ops_user_new() failed!\n"); 449 return CMD_RET_FAILURE; 450 } 451 if (ops->read_from_partition(ops, requested_partitions, offset_blk, 452 blkcnt, buffer, &out_num_read) != 0) { 453 printf("do_avb_write error!\n"); 454 free(buffer); 455 avb_ops_user_free(ops); 456 return CMD_RET_FAILURE; 457 } 458 459 free(buffer); 460 avb_ops_user_free(ops); 461 462 return CMD_RET_SUCCESS; 463 } 464 465 int do_avb_load_ab_metadata(cmd_tbl_t *cmdtp, int flag, 466 int argc, char * const argv[]) 467 { 468 AvbOps *ops; 469 AvbABData ab_data, ab_data_orig; 470 char *data; 471 int i; 472 473 if (argc != 1) 474 return CMD_RET_USAGE; 475 476 ops = avb_ops_user_new(); 477 if (ops == NULL) { 478 printf("avb_ops_user_new() failed!\n"); 479 return CMD_RET_FAILURE; 480 } 481 482 if (load_metadata(ops->ab_ops, &ab_data, &ab_data_orig) != 0) { 483 printf("do_avb_write_ab_metadata error!\n"); 484 avb_ops_user_free(ops); 485 return CMD_RET_FAILURE; 486 } 487 488 data = (char *)&ab_data; 489 for (i = 0; i < 33; i++) 490 printf("%d\n", data[i]); 491 492 avb_ops_user_free(ops); 493 494 return CMD_RET_SUCCESS; 495 } 496 497 int do_avb_read_ab_metadata(cmd_tbl_t *cmdtp, int flag, 498 int argc, char * const argv[]) 499 { 500 AvbOps *ops; 501 AvbABData ab_data; 502 503 if (argc != 1) 504 return CMD_RET_USAGE; 505 506 ops = avb_ops_user_new(); 507 if (ops == NULL) { 508 printf("avb_ops_user_new() failed!\n"); 509 return CMD_RET_FAILURE; 510 } 511 512 if (ops->ab_ops->read_ab_metadata(ops->ab_ops, &ab_data) != 0) { 513 printf("do_avb_write_ab_metadata error!\n"); 514 avb_ops_user_free(ops); 515 return CMD_RET_FAILURE; 516 } 517 518 avb_ops_user_free(ops); 519 520 return CMD_RET_SUCCESS; 521 } 522 523 int do_avb_write_ab_metadata(cmd_tbl_t *cmdtp, int flag, 524 int argc, char * const argv[]) 525 { 526 AvbOps *ops; 527 AvbABData ab_data; 528 529 if (argc != 1) 530 return CMD_RET_USAGE; 531 532 ops = avb_ops_user_new(); 533 if (ops == NULL) { 534 printf("avb_ops_user_new() failed!\n"); 535 return CMD_RET_FAILURE; 536 } 537 538 if (ops->ab_ops->write_ab_metadata(ops->ab_ops, &ab_data) != 0) { 539 printf("do_avb_write_ab_metadata error!\n"); 540 avb_ops_user_free(ops); 541 return CMD_RET_FAILURE; 542 } 543 544 avb_ops_user_free(ops); 545 546 return CMD_RET_SUCCESS; 547 } 548 549 int do_avb_verify_partition(cmd_tbl_t *cmdtp, int flag, 550 int argc, char * const argv[]) 551 { 552 AvbOps *ops; 553 const char *requested_partitions[1]; 554 const char * slot_suffixes[2] = {"_a", "_b"}; 555 AvbSlotVerifyFlags flags; 556 AvbSlotVerifyData *slot_data[2] = {NULL, NULL}; 557 AvbSlotVerifyResult verify_result; 558 size_t n; 559 560 if (argc != 3) 561 return CMD_RET_USAGE; 562 563 requested_partitions[0] = argv[1]; 564 n = simple_strtoul(argv[2], NULL, 16); 565 ops = avb_ops_user_new(); 566 flags = AVB_SLOT_VERIFY_FLAGS_NONE; 567 verify_result = 568 avb_slot_verify(ops, 569 requested_partitions, 570 slot_suffixes[n], 571 flags, 572 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, 573 &slot_data[n]); 574 if (verify_result != 0) 575 return CMD_RET_FAILURE; 576 577 avb_ops_user_free(ops); 578 579 return CMD_RET_SUCCESS; 580 } 581 582 int do_avb_flow(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 583 { 584 char slot_partition[2][20] = {{0}, {0}}; 585 unsigned long load_address; 586 AvbOps *ops; 587 const char *avb_version; 588 AvbSlotVerifyData *slot_data; 589 AvbSlotVerifyFlags flags; 590 const char *requested_partitions[] = {"boot", "system", NULL}; 591 char *command_line; 592 bool unlocked = true; 593 const char *mode_cmdline = NULL; 594 char root_data[70] = "root=PARTUUID="; 595 mode_cmdline = "skip_initramfs"; 596 size_t guid_buf_size = 37; 597 char guid_buf[37]; 598 char verify_flag; 599 char boot_slot_select[5]; 600 601 if (argc != 2) 602 return CMD_RET_USAGE; 603 avb_version = avb_version_string(); 604 printf("Android avb version is %s.\n", avb_version); 605 ops = avb_ops_user_new(); 606 if (ops == NULL) 607 printf("avb_ops_user_new() failed!\n"); 608 609 if (ops->read_is_device_unlocked(ops, &unlocked) != 0) 610 printf("Error determining whether device is unlocked.\n"); 611 612 printf("read_is_device_unlocked() ops returned that device is %s\n", 613 unlocked ? "UNLOCKED" : "LOCKED"); 614 615 flags = AVB_SLOT_VERIFY_FLAGS_NONE; 616 if (unlocked) 617 flags |= AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR; 618 619 verify_flag = argv[1][0]; 620 if (verify_flag == 'v') { 621 debug("start with verify!\n"); 622 if (avb_ab_flow(ops->ab_ops, 623 requested_partitions, 624 flags, 625 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, 626 &slot_data)) { 627 printf("avb_ab_flow() error!\n"); 628 return CMD_RET_FAILURE; 629 } 630 631 strcat(slot_partition[1], requested_partitions[1]); 632 strcat(slot_partition[1], slot_data->ab_suffix); 633 ops->get_unique_guid_for_partition(ops, 634 slot_partition[1], 635 guid_buf, 636 guid_buf_size); 637 strcat(root_data, guid_buf); 638 command_line = android_assemble_cmdline(slot_data->ab_suffix, 639 mode_cmdline); 640 strcat(root_data, " "); 641 strcat(root_data, command_line); 642 env_set("bootargs", root_data); 643 load_address = CONFIG_SYS_LOAD_ADDR; 644 memcpy((uint8_t*)load_address, 645 slot_data->loaded_partitions->data, 646 slot_data->loaded_partitions->data_size); 647 android_bootloader_boot_kernel(load_address); 648 avb_slot_verify_data_free(slot_data); 649 avb_ops_user_free(ops); 650 } else if (verify_flag == 'n') { 651 load_address = CONFIG_SYS_LOAD_ADDR; 652 avb_ab_slot_select(ops->ab_ops, boot_slot_select); 653 strcat(slot_partition[1], requested_partitions[1]); 654 strcat(slot_partition[1], boot_slot_select); 655 printf("%s\n", slot_partition[1]); 656 ops->get_unique_guid_for_partition(ops, 657 slot_partition[1], 658 guid_buf, 659 guid_buf_size); 660 strcat(root_data, guid_buf); 661 command_line = android_assemble_cmdline(boot_slot_select, 662 mode_cmdline); 663 strcat(root_data, " "); 664 strcat(root_data, command_line); 665 env_set("bootargs", root_data); 666 android_avb_boot_flow(boot_slot_select, load_address); 667 } else { 668 return CMD_RET_USAGE; 669 } 670 671 return CMD_RET_SUCCESS; 672 } 673 674 static cmd_tbl_t cmd_avb[] = { 675 U_BOOT_CMD_MKENT(init, 1, 1, do_avb_init_ab_metadata, "", ""), 676 U_BOOT_CMD_MKENT(version, 1, 1, do_avb_version, "", ""), 677 U_BOOT_CMD_MKENT(slot_active, 2, 1, 678 do_avb_ab_mark_slot_active, "", ""), 679 U_BOOT_CMD_MKENT(slot_unbootable, 2, 1, 680 do_avb_ab_mark_slot_unbootable, "", ""), 681 U_BOOT_CMD_MKENT(slot_successful, 2, 1, 682 do_avb_ab_mark_slot_successful, "", ""), 683 U_BOOT_CMD_MKENT(read_rollback, 2, 1, 684 do_avb_read_rollback_index, "", ""), 685 U_BOOT_CMD_MKENT(write_rollback, 3, 1, 686 do_avb_write_rollback_index, "", ""), 687 U_BOOT_CMD_MKENT(read_lock_status, 1, 1, 688 do_avb_read_is_device_unlocked, "", ""), 689 U_BOOT_CMD_MKENT(write_lock_status, 2, 1, 690 do_avb_write_is_device_unlocked, "", ""), 691 U_BOOT_CMD_MKENT(part_size, 2, 1, 692 do_avb_get_size_of_partition, "", ""), 693 U_BOOT_CMD_MKENT(part_guid, 2, 1, 694 do_avb_get_get_unique_guid_for_partition, "", ""), 695 U_BOOT_CMD_MKENT(read, 4, 1, do_avb_read, "", ""), 696 U_BOOT_CMD_MKENT(write, 4, 1, do_avb_write, "", ""), 697 U_BOOT_CMD_MKENT(loadabmisc, 1, 1, do_avb_load_ab_metadata, "", ""), 698 U_BOOT_CMD_MKENT(readabmisc, 1, 1, do_avb_read_ab_metadata, "", ""), 699 U_BOOT_CMD_MKENT(writeabmisc, 1, 1, do_avb_write_ab_metadata, "", ""), 700 U_BOOT_CMD_MKENT(verify, 3, 1, do_avb_verify_partition, "", ""), 701 U_BOOT_CMD_MKENT(flow, 2, 1, do_avb_flow, "", "") 702 }; 703 704 static int do_boot_avb(cmd_tbl_t *cmdtp, 705 int flag, 706 int argc, 707 char * const argv[]) 708 { 709 cmd_tbl_t *cp; 710 711 cp = find_cmd_tbl(argv[1], cmd_avb, ARRAY_SIZE(cmd_avb)); 712 713 argc--; 714 argv++; 715 716 if (cp == NULL || argc > cp->maxargs) 717 return CMD_RET_USAGE; 718 if (flag == CMD_FLAG_REPEAT && !cp->repeatable) 719 return CMD_RET_SUCCESS; 720 721 return cp->cmd(cmdtp, flag, argc, argv); 722 } 723 724 U_BOOT_CMD( 725 bootavb, 29, 1, do_boot_avb, 726 "Execute the Android avb a/b boot flow.", 727 "init - initialize the avbabmeta\n" 728 "bootavb version - display info of bootavb version\n" 729 "bootavb slot_active cnt\n" 730 "bootavb slot_unbootable cnt\n" 731 "bootavb slot_successful cnt\n" 732 "bootavb read_rollback rollback_index_location\n" 733 "bootavb write_rollback rollback_index_location out_rollback_index\n" 734 "bootavb read_lock_status\n" 735 "bootavb write_lock_status 0 or 1\n" 736 "bootavb part_size partitions_name\n" 737 "bootavb part_guid partitions_name\n" 738 "bootavb read partition offset_blk cnt\n" 739 "bootavb write partition offset_blk cnt\n" 740 "bootavb loadabmisc\n" 741 "bootavb readabmisc\n" 742 "bootavb writeabmisc\n" 743 "bootavb verify partition slot_cnt;partion name without '_a' or '_b'\n" 744 "bootavb flow v/n\n" 745 ); 746 #endif 747