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