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 #include <android_avb/rk_avb_ops_user.h> 18 #include <android_avb/avb_atx_ops.h> 19 20 static int do_boot_android(cmd_tbl_t *cmdtp, int flag, int argc, 21 char * const argv[]) 22 { 23 unsigned long load_address; 24 int ret = CMD_RET_SUCCESS; 25 char *addr_arg_endp, *addr_str; 26 struct blk_desc *dev_desc; 27 28 if (argc < 3) 29 return CMD_RET_USAGE; 30 if (argc > 5) 31 return CMD_RET_USAGE; 32 33 if (argc >= 5) { 34 load_address = simple_strtoul(argv[4], &addr_arg_endp, 16); 35 if (addr_arg_endp == argv[4] || *addr_arg_endp != '\0') 36 return CMD_RET_USAGE; 37 } else { 38 addr_str = env_get("kernel_addr_r"); 39 if (addr_str) 40 load_address = simple_strtoul(addr_str, NULL, 16); 41 else 42 load_address = CONFIG_SYS_LOAD_ADDR; 43 } 44 45 #if defined(CONFIG_ARM64) 46 /* ARM64 kernel load addr need to align to 0x80000, and android boot.img 47 * have a 2KB header, need to reserve space for it. 48 */ 49 load_address &= ~0x7ffff; 50 #endif 51 52 dev_desc = blk_get_dev(argv[1], simple_strtoul(argv[2], NULL, 16)); 53 if (!dev_desc) { 54 printf("Could not get %s %s\n", argv[1], argv[2]); 55 return CMD_RET_FAILURE; 56 } 57 58 ret = android_bootloader_boot_flow(dev_desc, load_address); 59 if (ret < 0) { 60 printf("Android boot failed, error %d.\n", ret); 61 return CMD_RET_FAILURE; 62 } 63 return CMD_RET_SUCCESS; 64 } 65 66 U_BOOT_CMD( 67 boot_android, 5, 0, do_boot_android, 68 "Execute the Android Bootloader flow.", 69 "<interface> <dev[:part|;part_name]> <slot> [<kernel_addr>]\n" 70 " - Load the Boot Control Block (BCB) from the partition 'part' on\n" 71 " device type 'interface' instance 'dev' to determine the boot\n" 72 " mode, and load and execute the appropriate kernel.\n" 73 " In normal and recovery mode, the kernel will be loaded from\n" 74 " the corresponding \"boot\" partition. In bootloader mode, the\n" 75 " command defined in the \"fastbootcmd\" variable will be\n" 76 " executed.\n" 77 " On Android devices with multiple slots, the pass 'slot' is\n" 78 " used to load the appropriate kernel. The standard slot names\n" 79 " are 'a' and 'b'.\n" 80 " - If 'part_name' is passed, preceded with a ; instead of :, the\n" 81 " partition name whose label is 'part_name' will be looked up in\n" 82 " the partition table. This is commonly the \"misc\" partition.\n" 83 ); 84 85 #ifdef CONFIG_ANDROID_AB 86 int do_avb_init_ab_metadata(cmd_tbl_t *cmdtp, int flag, 87 int argc, char * const argv[]) 88 { 89 AvbOps *ops; 90 AvbABData ab_data; 91 92 memset(&ab_data, 0, sizeof(AvbABData)); 93 debug("sizeof(AvbABData) = %d\n", (int)(size_t)sizeof(AvbABData)); 94 if (argc != 1) 95 return CMD_RET_USAGE; 96 97 ops = avb_ops_user_new(); 98 if (ops == NULL) { 99 printf("avb_ops_user_new() failed!\n"); 100 return CMD_RET_FAILURE; 101 } 102 103 avb_ab_data_init(&ab_data); 104 if (ops->ab_ops->write_ab_metadata(ops->ab_ops, &ab_data) != 0) { 105 printf("do_avb_init_ab_metadata error!\n"); 106 avb_ops_user_free(ops); 107 return CMD_RET_FAILURE; 108 } 109 110 printf("Initialize ab data to misc partition success.\n"); 111 avb_ops_user_free(ops); 112 113 return CMD_RET_SUCCESS; 114 } 115 116 int do_avb_ab_mark_slot_active(cmd_tbl_t *cmdtp, int flag, 117 int argc, char * const argv[]) 118 { 119 AvbOps *ops; 120 unsigned int slot_number; 121 122 if (argc != 2) 123 return CMD_RET_USAGE; 124 125 ops = avb_ops_user_new(); 126 if (ops == NULL) { 127 printf("avb_ops_user_new() failed!\n"); 128 return CMD_RET_FAILURE; 129 } 130 131 slot_number = simple_strtoul(argv[1], NULL, 16); 132 if (avb_ab_mark_slot_active(ops->ab_ops, slot_number) != 0) { 133 printf("avb_ab_mark_slot_active error!\n"); 134 avb_ops_user_free(ops); 135 return CMD_RET_FAILURE; 136 } 137 138 printf("Mark slot %d active successfully.\n", slot_number); 139 avb_ops_user_free(ops); 140 141 return CMD_RET_SUCCESS; 142 } 143 144 int do_avb_ab_mark_slot_unbootable(cmd_tbl_t *cmdtp, int flag, 145 int argc, char * const argv[]) 146 { 147 AvbOps *ops; 148 unsigned int slot_number; 149 150 if (argc != 2) 151 return CMD_RET_USAGE; 152 153 ops = avb_ops_user_new(); 154 if (ops == NULL) { 155 printf("avb_ops_user_new() failed!\n"); 156 return CMD_RET_FAILURE; 157 } 158 159 slot_number = simple_strtoul(argv[1], NULL, 16); 160 if (avb_ab_mark_slot_unbootable(ops->ab_ops, slot_number) != 0) { 161 printf("do_avb_ab_mark_slot_unbootable error!\n"); 162 avb_ops_user_free(ops); 163 return CMD_RET_FAILURE; 164 } 165 166 printf("Mark slot %d unbootable successfully.\n", slot_number); 167 avb_ops_user_free(ops); 168 169 return CMD_RET_SUCCESS; 170 } 171 172 int do_avb_ab_mark_slot_successful(cmd_tbl_t *cmdtp, int flag, 173 int argc, char * const argv[]) 174 { 175 AvbOps *ops; 176 unsigned int slot_number; 177 178 if (argc != 2) 179 return CMD_RET_USAGE; 180 181 ops = avb_ops_user_new(); 182 if (ops == NULL) { 183 printf("avb_ops_user_new() failed!\n"); 184 return CMD_RET_FAILURE; 185 } 186 187 slot_number = simple_strtoul(argv[1], NULL, 16); 188 if (avb_ab_mark_slot_successful(ops->ab_ops, slot_number) != 0) { 189 printf("do_avb_ab_mark_slot_successful error!\n"); 190 avb_ops_user_free(ops); 191 return CMD_RET_FAILURE; 192 } 193 194 avb_ops_user_free(ops); 195 196 return CMD_RET_SUCCESS; 197 } 198 199 int do_avb_read_ab_metadata(cmd_tbl_t *cmdtp, int flag, 200 int argc, char * const argv[]) 201 { 202 AvbOps *ops; 203 AvbABData ab_data; 204 205 if (argc != 1) 206 return CMD_RET_USAGE; 207 208 ops = avb_ops_user_new(); 209 if (ops == NULL) { 210 printf("avb_ops_user_new() failed!\n"); 211 return CMD_RET_FAILURE; 212 } 213 214 if (ops->ab_ops->read_ab_metadata(ops->ab_ops, &ab_data) != 0) { 215 printf("do_avb_write_ab_metadata error!\n"); 216 avb_ops_user_free(ops); 217 return CMD_RET_FAILURE; 218 } 219 220 printf("Slot A information:\n"); 221 printf("slot A: priority = %d, tries_remaining = %d,\ 222 successful_boot = %d\n", 223 ab_data.slots[0].priority, 224 ab_data.slots[0].tries_remaining, 225 ab_data.slots[0].successful_boot); 226 printf("Slot B information:\n"); 227 printf("slot B: priority = %d, tries_remaining = %d,\ 228 successful_boot = %d\n", 229 ab_data.slots[1].priority, 230 ab_data.slots[1].tries_remaining, 231 ab_data.slots[1].successful_boot); 232 avb_ops_user_free(ops); 233 234 return CMD_RET_SUCCESS; 235 } 236 237 int do_avb_write_ab_metadata(cmd_tbl_t *cmdtp, int flag, 238 int argc, char * const argv[]) 239 { 240 AvbOps *ops; 241 AvbABData ab_data; 242 243 if (argc != 1) 244 return CMD_RET_USAGE; 245 246 ops = avb_ops_user_new(); 247 if (ops == NULL) { 248 printf("avb_ops_user_new() failed!\n"); 249 return CMD_RET_FAILURE; 250 } 251 252 if (ops->ab_ops->write_ab_metadata(ops->ab_ops, &ab_data) != 0) { 253 printf("do_avb_write_ab_metadata 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 #endif 263 264 #ifdef CONFIG_ANDROID_AVB 265 int do_avb_version(cmd_tbl_t *cmdtp, int flag, int argc, 266 char * const argv[]) 267 { 268 const char *avb_version; 269 270 if (argc != 1) 271 return CMD_RET_USAGE; 272 273 avb_version = avb_version_string(); 274 printf("Android avb version is %s.\n", avb_version); 275 276 return CMD_RET_SUCCESS; 277 } 278 279 int do_avb_read_rollback_index(cmd_tbl_t *cmdtp, int flag, 280 int argc, char * const argv[]) 281 { 282 AvbOps *ops; 283 uint64_t out_rollback_index; 284 size_t rollback_index_location; 285 286 if (argc != 2) 287 return CMD_RET_USAGE; 288 289 ops = avb_ops_user_new(); 290 if (ops == NULL) { 291 printf("avb_ops_user_new() failed!\n"); 292 return CMD_RET_FAILURE; 293 } 294 295 rollback_index_location = simple_strtoul(argv[1], NULL, 16); 296 if (ops->read_rollback_index(ops, rollback_index_location, 297 &out_rollback_index) != 0) { 298 printf("do_avb_read_rollback_index error!\n"); 299 avb_ops_user_free(ops); 300 return CMD_RET_FAILURE; 301 } 302 303 printf("\nout_rollback_index = %llx\n", out_rollback_index); 304 avb_ops_user_free(ops); 305 306 return CMD_RET_SUCCESS; 307 } 308 309 int do_avb_write_rollback_index(cmd_tbl_t *cmdtp, int flag, 310 int argc, char * const argv[]) 311 { 312 AvbOps *ops; 313 uint64_t out_rollback_index; 314 size_t rollback_index_location; 315 316 if (argc != 3) 317 return CMD_RET_USAGE; 318 319 rollback_index_location = simple_strtoul(argv[1], NULL, 16); 320 out_rollback_index = simple_strtoull(argv[2], NULL, 16); 321 debug("out_rollback_index = %llx\n", out_rollback_index); 322 ops = avb_ops_user_new(); 323 if (ops == NULL) { 324 printf("avb_ops_user_new() failed!\n"); 325 return CMD_RET_FAILURE; 326 } 327 328 if (ops->write_rollback_index(ops, rollback_index_location, 329 out_rollback_index) != 0) { 330 printf("do_avb_write_rollback_index error!\n"); 331 avb_ops_user_free(ops); 332 return CMD_RET_FAILURE; 333 } 334 335 printf("\nWrite rollback index successfully.\n"); 336 avb_ops_user_free(ops); 337 338 return CMD_RET_SUCCESS; 339 } 340 341 int do_avb_read_is_device_unlocked(cmd_tbl_t *cmdtp, int flag, 342 int argc, char * const argv[]) 343 { 344 AvbOps *ops; 345 bool out_is_unlocked; 346 347 if (argc != 1) 348 return CMD_RET_USAGE; 349 350 ops = avb_ops_user_new(); 351 if (ops == NULL) { 352 printf("avb_ops_user_new() failed!\n"); 353 return CMD_RET_FAILURE; 354 } 355 356 if (ops->read_is_device_unlocked(ops, &out_is_unlocked) != 0) { 357 printf("do_avb_read_is_device_unlocked error!\n"); 358 avb_ops_user_free(ops); 359 return CMD_RET_FAILURE; 360 } 361 362 printf("\n The device is %s\n", 363 out_is_unlocked ? "UNLOCKED" : "LOCKED"); 364 avb_ops_user_free(ops); 365 366 return CMD_RET_SUCCESS; 367 } 368 int do_avb_write_is_device_unlocked(cmd_tbl_t *cmdtp, int flag, 369 int argc, char * const argv[]) 370 { 371 AvbOps *ops; 372 bool out_is_unlocked; 373 374 if (argc != 2) 375 return CMD_RET_USAGE; 376 377 out_is_unlocked = simple_strtoul(argv[1], NULL, 16); 378 if ((out_is_unlocked != 0) || (out_is_unlocked != 1)) 379 printf("enter out_is_unlocked value must is '0' or '1'\n"); 380 381 ops = avb_ops_user_new(); 382 if (ops == NULL) { 383 printf("avb_ops_user_new() failed!\n"); 384 return CMD_RET_FAILURE; 385 } 386 387 if (ops->write_is_device_unlocked(ops, &out_is_unlocked) != 0) { 388 printf("do_avb_write_is_device_unlocked error!\n"); 389 avb_ops_user_free(ops); 390 return CMD_RET_FAILURE; 391 } 392 393 debug("out_is_unlocked = %d\n", out_is_unlocked); 394 avb_ops_user_free(ops); 395 396 return CMD_RET_SUCCESS; 397 } 398 399 int do_avb_get_size_of_partition(cmd_tbl_t *cmdtp, int flag, 400 int argc, char * const argv[]) 401 { 402 AvbOps *ops; 403 char *requested_partitions; 404 uint64_t out_size_in_bytes; 405 406 if (argc != 2) 407 return CMD_RET_USAGE; 408 409 requested_partitions = argv[1]; 410 ops = avb_ops_user_new(); 411 if (ops == NULL) { 412 printf("avb_ops_user_new() failed!\n"); 413 return CMD_RET_FAILURE; 414 } 415 416 if (ops->get_size_of_partition(ops, requested_partitions, 417 &out_size_in_bytes) != 0) { 418 printf("Can not get %s partition size!\n", requested_partitions); 419 avb_ops_user_free(ops); 420 return CMD_RET_FAILURE; 421 } 422 423 printf("%s partition size = 0x%llx\n", requested_partitions, 424 out_size_in_bytes); 425 avb_ops_user_free(ops); 426 427 return CMD_RET_SUCCESS; 428 } 429 430 int do_avb_get_get_unique_guid_for_partition(cmd_tbl_t *cmdtp, int flag, 431 int argc, char * const argv[]) 432 { 433 AvbOps *ops; 434 char *requested_partitions; 435 size_t guid_buf_size = 37; 436 char guid_buf[37]; 437 438 if (argc != 2) 439 return CMD_RET_USAGE; 440 441 requested_partitions = argv[1]; 442 ops = avb_ops_user_new(); 443 if (ops == NULL) { 444 printf("avb_ops_user_new() failed!\n"); 445 return CMD_RET_FAILURE; 446 } 447 448 if (ops->get_unique_guid_for_partition(ops, requested_partitions, 449 guid_buf, guid_buf_size) != 0) { 450 printf("Can not get %s partition UUID!\n", 451 requested_partitions); 452 avb_ops_user_free(ops); 453 return CMD_RET_FAILURE; 454 } 455 456 printf("%s partition UUID is %s\n", requested_partitions, guid_buf); 457 avb_ops_user_free(ops); 458 459 return CMD_RET_SUCCESS; 460 } 461 462 int do_avb_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 463 { 464 AvbOps *ops; 465 char *requested_partitions; 466 int64_t offset_blk; 467 size_t blkcnt; 468 size_t out_num_read; 469 int i; 470 char *buffer; 471 472 if (argc != 4) 473 return CMD_RET_USAGE; 474 475 requested_partitions = argv[1]; 476 offset_blk = simple_strtoul(argv[2], NULL, 16); 477 blkcnt = simple_strtoul(argv[3], NULL, 16); 478 ops = avb_ops_user_new(); 479 buffer = (char *)malloc(blkcnt * 512); 480 if (buffer == NULL) 481 printf("malloc buffer failed!\n"); 482 483 if (ops == NULL) { 484 printf("avb_ops_user_new() failed!\n"); 485 return CMD_RET_FAILURE; 486 } 487 488 if (ops->read_from_partition(ops, requested_partitions, 489 offset_blk, blkcnt, buffer, 490 &out_num_read) != 0) { 491 printf("do avb read error!\n"); 492 free(buffer); 493 avb_ops_user_free(ops); 494 return CMD_RET_FAILURE; 495 } 496 497 for (i = 0; i < 512 * blkcnt; i++) { 498 printf("buffer %d = %x", i, buffer[i]); 499 if ((i + 1) % 4 == 0) 500 printf("\n"); 501 } 502 503 free(buffer); 504 avb_ops_user_free(ops); 505 506 return CMD_RET_SUCCESS; 507 } 508 509 int do_perm_attr_test(cmd_tbl_t *cmdtp, int flag, 510 int argc, char * const argv[]) 511 { 512 AvbOps *ops; 513 int i; 514 uint8_t hash[AVB_SHA256_DIGEST_SIZE]; 515 516 if (argc != 1) 517 return CMD_RET_USAGE; 518 519 ops = avb_ops_user_new(); 520 if (ops == NULL) { 521 printf("avb_ops_user_new() failed!\n"); 522 return CMD_RET_FAILURE; 523 } 524 525 if (ops->atx_ops->read_permanent_attributes_hash(ops->atx_ops, hash) != 0) { 526 printf("read_permanent_attributes_hash error!\n"); 527 avb_ops_user_free(ops); 528 return CMD_RET_FAILURE; 529 } 530 531 for (i = 0; i < AVB_SHA256_DIGEST_SIZE; i++) { 532 if (i % 4 == 0) 533 printf("\n"); 534 printf("0x%x ", hash[i]); 535 } 536 537 avb_ops_user_free(ops); 538 539 return CMD_RET_SUCCESS; 540 } 541 542 int do_avb_verify_partition(cmd_tbl_t *cmdtp, int flag, 543 int argc, char * const argv[]) 544 { 545 AvbOps *ops; 546 const char *requested_partitions[1]; 547 const char * slot_suffixes[2] = {"_a", "_b"}; 548 AvbSlotVerifyFlags flags; 549 AvbSlotVerifyData *slot_data[2] = {NULL, NULL}; 550 AvbSlotVerifyResult verify_result; 551 size_t n; 552 553 if (argc != 3) 554 return CMD_RET_USAGE; 555 556 requested_partitions[0] = argv[1]; 557 n = simple_strtoul(argv[2], NULL, 16); 558 ops = avb_ops_user_new(); 559 flags = AVB_SLOT_VERIFY_FLAGS_NONE; 560 verify_result = 561 avb_slot_verify(ops, 562 requested_partitions, 563 slot_suffixes[n], 564 flags, 565 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, 566 &slot_data[n]); 567 if (verify_result != 0) 568 return CMD_RET_FAILURE; 569 570 avb_ops_user_free(ops); 571 572 return CMD_RET_SUCCESS; 573 } 574 #endif 575 576 static cmd_tbl_t cmd_avb[] = { 577 #ifdef CONFIG_ANDROID_AB 578 U_BOOT_CMD_MKENT(init, 1, 1, do_avb_init_ab_metadata, "", ""), 579 U_BOOT_CMD_MKENT(slot_active, 2, 1, 580 do_avb_ab_mark_slot_active, "", ""), 581 U_BOOT_CMD_MKENT(slot_unbootable, 2, 1, 582 do_avb_ab_mark_slot_unbootable, "", ""), 583 U_BOOT_CMD_MKENT(slot_successful, 2, 1, 584 do_avb_ab_mark_slot_successful, "", ""), 585 U_BOOT_CMD_MKENT(readabmisc, 1, 1, do_avb_read_ab_metadata, "", ""), 586 #endif 587 #ifdef CONFIG_ANDROID_AVB 588 U_BOOT_CMD_MKENT(version, 1, 1, do_avb_version, "", ""), 589 U_BOOT_CMD_MKENT(read_rollback, 2, 1, 590 do_avb_read_rollback_index, "", ""), 591 U_BOOT_CMD_MKENT(write_rollback, 3, 1, 592 do_avb_write_rollback_index, "", ""), 593 U_BOOT_CMD_MKENT(read_lock_status, 1, 1, 594 do_avb_read_is_device_unlocked, "", ""), 595 U_BOOT_CMD_MKENT(write_lock_status, 2, 1, 596 do_avb_write_is_device_unlocked, "", ""), 597 U_BOOT_CMD_MKENT(part_size, 2, 1, 598 do_avb_get_size_of_partition, "", ""), 599 U_BOOT_CMD_MKENT(part_guid, 2, 1, 600 do_avb_get_get_unique_guid_for_partition, "", ""), 601 U_BOOT_CMD_MKENT(read, 4, 1, do_avb_read, "", ""), 602 U_BOOT_CMD_MKENT(perm_attr_test, 1, 1, do_perm_attr_test, "", ""), 603 U_BOOT_CMD_MKENT(verify, 3, 1, do_avb_verify_partition, "", ""), 604 #endif 605 }; 606 607 static int do_boot_avb(cmd_tbl_t *cmdtp, 608 int flag, 609 int argc, 610 char * const argv[]) 611 { 612 cmd_tbl_t *cp; 613 614 cp = find_cmd_tbl(argv[1], cmd_avb, ARRAY_SIZE(cmd_avb)); 615 616 argc--; 617 argv++; 618 619 if (cp == NULL || argc > cp->maxargs) 620 return CMD_RET_USAGE; 621 if (flag == CMD_FLAG_REPEAT && !cp->repeatable) 622 return CMD_RET_SUCCESS; 623 624 return cp->cmd(cmdtp, flag, argc, argv); 625 } 626 627 U_BOOT_CMD( 628 bootavb, 29, 1, do_boot_avb, 629 "Execute the Android avb a/b boot flow.", 630 "init - initialize the avbabmeta\n" 631 "bootavb version - display info of bootavb version\n" 632 "bootavb slot_active cnt\n" 633 "bootavb slot_unbootable cnt\n" 634 "bootavb slot_successful cnt\n" 635 "bootavb read_rollback rollback_index_location\n" 636 "bootavb write_rollback rollback_index_location rollback_index\n" 637 "bootavb read_lock_status\n" 638 "bootavb write_lock_status 0 or 1\n" 639 "bootavb part_size partitions_name\n" 640 "bootavb part_guid partitions_name\n" 641 "bootavb read partition offset_blk cnt\n" 642 "bootavb readabmisc\n" 643 "bootavb perm_attr_test\n" 644 "bootavb verify partition slot_cnt;partion name without '_a' or '_b'\n" 645 ); 646