"Das U-Boot" Source Tree
at master 624 lines 16 kB view raw
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Bootmeth for Android 4 * 5 * Copyright (C) 2024 BayLibre, SAS 6 * Written by Mattijs Korpershoek <mkorpershoek@baylibre.com> 7 */ 8#define LOG_CATEGORY UCLASS_BOOTSTD 9 10#include <android_ab.h> 11#include <android_image.h> 12#if CONFIG_IS_ENABLED(AVB_VERIFY) 13#include <avb_verify.h> 14#endif 15#include <bcb.h> 16#include <blk.h> 17#include <bootflow.h> 18#include <bootm.h> 19#include <bootmeth.h> 20#include <dm.h> 21#include <image.h> 22#include <malloc.h> 23#include <mapmem.h> 24#include <part.h> 25#include <version.h> 26#include "bootmeth_android.h" 27 28#define BCB_FIELD_COMMAND_SZ 32 29#define BCB_PART_NAME "misc" 30#define BOOT_PART_NAME "boot" 31#define VENDOR_BOOT_PART_NAME "vendor_boot" 32#define SLOT_LEN 2 33 34/** 35 * struct android_priv - Private data 36 * 37 * This is read from the disk and recorded for use when the full Android 38 * kernel must be loaded and booted 39 * 40 * @boot_mode: Requested boot mode (normal, recovery, bootloader) 41 * @slot: Nul-terminated partition slot suffix read from BCB ("a\0" or "b\0") 42 * @header_version: Android boot image header version 43 */ 44struct android_priv { 45 enum android_boot_mode boot_mode; 46 char *slot; 47 u32 header_version; 48 u32 boot_img_size; 49 u32 vendor_boot_img_size; 50}; 51 52static int android_check(struct udevice *dev, struct bootflow_iter *iter) 53{ 54 /* This only works on mmc devices */ 55 if (bootflow_iter_check_mmc(iter)) 56 return log_msg_ret("mmc", -ENOTSUPP); 57 58 /* 59 * This only works on whole devices, as multiple 60 * partitions are needed to boot Android 61 */ 62 if (iter->part != 0) 63 return log_msg_ret("mmc part", -ENOTSUPP); 64 65 return 0; 66} 67 68static int scan_boot_part(struct udevice *blk, struct android_priv *priv) 69{ 70 struct blk_desc *desc = dev_get_uclass_plat(blk); 71 struct disk_partition partition; 72 char partname[PART_NAME_LEN]; 73 ulong num_blks, bufsz; 74 char *buf; 75 int ret; 76 77 if (priv->slot) 78 sprintf(partname, BOOT_PART_NAME "_%s", priv->slot); 79 else 80 sprintf(partname, BOOT_PART_NAME); 81 82 ret = part_get_info_by_name(desc, partname, &partition); 83 if (ret < 0) 84 return log_msg_ret("part info", ret); 85 86 num_blks = DIV_ROUND_UP(sizeof(struct andr_boot_img_hdr_v0), desc->blksz); 87 bufsz = num_blks * desc->blksz; 88 buf = malloc(bufsz); 89 if (!buf) 90 return log_msg_ret("buf", -ENOMEM); 91 92 ret = blk_read(blk, partition.start, num_blks, buf); 93 if (ret != num_blks) { 94 free(buf); 95 return log_msg_ret("part read", -EIO); 96 } 97 98 if (!is_android_boot_image_header(buf)) { 99 free(buf); 100 return log_msg_ret("header", -ENOENT); 101 } 102 103 if (!android_image_get_bootimg_size(buf, &priv->boot_img_size)) { 104 free(buf); 105 return log_msg_ret("get bootimg size", -EINVAL); 106 } 107 108 priv->header_version = ((struct andr_boot_img_hdr_v0 *)buf)->header_version; 109 110 free(buf); 111 112 return 0; 113} 114 115static int scan_vendor_boot_part(struct udevice *blk, struct android_priv *priv) 116{ 117 struct blk_desc *desc = dev_get_uclass_plat(blk); 118 struct disk_partition partition; 119 char partname[PART_NAME_LEN]; 120 ulong num_blks, bufsz; 121 char *buf; 122 int ret; 123 124 if (priv->slot) 125 sprintf(partname, VENDOR_BOOT_PART_NAME "_%s", priv->slot); 126 else 127 sprintf(partname, VENDOR_BOOT_PART_NAME); 128 129 ret = part_get_info_by_name(desc, partname, &partition); 130 if (ret < 0) 131 return log_msg_ret("part info", ret); 132 133 num_blks = DIV_ROUND_UP(sizeof(struct andr_vnd_boot_img_hdr), desc->blksz); 134 bufsz = num_blks * desc->blksz; 135 buf = malloc(bufsz); 136 if (!buf) 137 return log_msg_ret("buf", -ENOMEM); 138 139 ret = blk_read(blk, partition.start, num_blks, buf); 140 if (ret != num_blks) { 141 free(buf); 142 return log_msg_ret("part read", -EIO); 143 } 144 145 if (!is_android_vendor_boot_image_header(buf)) { 146 free(buf); 147 return log_msg_ret("header", -ENOENT); 148 } 149 150 if (!android_image_get_vendor_bootimg_size(buf, &priv->vendor_boot_img_size)) { 151 free(buf); 152 return log_msg_ret("get vendor bootimg size", -EINVAL); 153 } 154 155 free(buf); 156 157 return 0; 158} 159 160static int android_read_slot_from_bcb(struct bootflow *bflow, bool decrement) 161{ 162 struct blk_desc *desc = dev_get_uclass_plat(bflow->blk); 163 struct android_priv *priv = bflow->bootmeth_priv; 164 struct disk_partition misc; 165 char slot_suffix[3]; 166 int ret; 167 168 if (!CONFIG_IS_ENABLED(ANDROID_AB)) { 169 priv->slot = NULL; 170 return 0; 171 } 172 173 ret = part_get_info_by_name(desc, BCB_PART_NAME, &misc); 174 if (ret < 0) 175 return log_msg_ret("part", ret); 176 177 ret = ab_select_slot(desc, &misc, decrement); 178 if (ret < 0) 179 return log_msg_ret("slot", ret); 180 181 priv->slot = malloc(SLOT_LEN); 182 priv->slot[0] = BOOT_SLOT_NAME(ret); 183 priv->slot[1] = '\0'; 184 185 sprintf(slot_suffix, "_%s", priv->slot); 186 ret = bootflow_cmdline_set_arg(bflow, "androidboot.slot_suffix", 187 slot_suffix, false); 188 if (ret < 0) 189 return log_msg_ret("cmdl", ret); 190 191 return 0; 192} 193 194static int configure_serialno(struct bootflow *bflow) 195{ 196 char *serialno = env_get("serial#"); 197 198 if (!serialno) 199 return log_msg_ret("serial", -ENOENT); 200 201 return bootflow_cmdline_set_arg(bflow, "androidboot.serialno", serialno, false); 202} 203 204static int configure_bootloader_version(struct bootflow *bflow) 205{ 206 return bootflow_cmdline_set_arg(bflow, "androidboot.bootloader", 207 PLAIN_VERSION, false); 208} 209 210static int android_read_bootflow(struct udevice *dev, struct bootflow *bflow) 211{ 212 struct blk_desc *desc = dev_get_uclass_plat(bflow->blk); 213 struct disk_partition misc; 214 struct android_priv *priv; 215 char command[BCB_FIELD_COMMAND_SZ]; 216 int ret; 217 218 bflow->state = BOOTFLOWST_MEDIA; 219 220 /* 221 * bcb_find_partition_and_load() will print errors to stdout 222 * if BCB_PART_NAME is not found. To avoid that, check if the 223 * partition exists first. 224 */ 225 ret = part_get_info_by_name(desc, BCB_PART_NAME, &misc); 226 if (ret < 0) 227 return log_msg_ret("part", ret); 228 229 ret = bcb_find_partition_and_load("mmc", desc->devnum, BCB_PART_NAME); 230 if (ret < 0) 231 return log_msg_ret("bcb load", ret); 232 233 ret = bcb_get(BCB_FIELD_COMMAND, command, sizeof(command)); 234 if (ret < 0) 235 return log_msg_ret("bcb read", ret); 236 237 priv = malloc(sizeof(struct android_priv)); 238 if (!priv) 239 return log_msg_ret("buf", -ENOMEM); 240 241 if (!strcmp("bootonce-bootloader", command)) { 242 priv->boot_mode = ANDROID_BOOT_MODE_BOOTLOADER; 243 bflow->os_name = strdup("Android (bootloader)"); 244 } else if (!strcmp("boot-fastboot", command)) { 245 priv->boot_mode = ANDROID_BOOT_MODE_RECOVERY; 246 bflow->os_name = strdup("Android (fastbootd)"); 247 } else if (!strcmp("boot-recovery", command)) { 248 priv->boot_mode = ANDROID_BOOT_MODE_RECOVERY; 249 bflow->os_name = strdup("Android (recovery)"); 250 } else { 251 priv->boot_mode = ANDROID_BOOT_MODE_NORMAL; 252 bflow->os_name = strdup("Android"); 253 } 254 if (!bflow->os_name) 255 return log_msg_ret("os", -ENOMEM); 256 257 if (priv->boot_mode == ANDROID_BOOT_MODE_BOOTLOADER) { 258 /* Clear BCB */ 259 memset(command, 0, sizeof(command)); 260 ret = bcb_set(BCB_FIELD_COMMAND, command); 261 if (ret < 0) { 262 free(priv); 263 return log_msg_ret("bcb set", ret); 264 } 265 ret = bcb_store(); 266 if (ret < 0) { 267 free(priv); 268 return log_msg_ret("bcb store", ret); 269 } 270 271 bflow->bootmeth_priv = priv; 272 bflow->state = BOOTFLOWST_READY; 273 return 0; 274 } 275 276 bflow->bootmeth_priv = priv; 277 278 /* For recovery and normal boot, we need to scan the partitions */ 279 ret = android_read_slot_from_bcb(bflow, false); 280 if (ret < 0) { 281 log_err("read slot: %d", ret); 282 goto free_priv; 283 } 284 285 ret = scan_boot_part(bflow->blk, priv); 286 if (ret < 0) { 287 log_debug("scan boot failed: err=%d\n", ret); 288 goto free_priv; 289 } 290 291 if (priv->header_version >= 3) { 292 ret = scan_vendor_boot_part(bflow->blk, priv); 293 if (ret < 0) { 294 log_debug("scan vendor_boot failed: err=%d\n", ret); 295 goto free_priv; 296 } 297 } 298 299 /* 300 * Ignoring return code for the following configurations: 301 * these are not mandatory for booting. 302 */ 303 configure_serialno(bflow); 304 configure_bootloader_version(bflow); 305 306 if (priv->boot_mode == ANDROID_BOOT_MODE_NORMAL && priv->slot) { 307 ret = bootflow_cmdline_set_arg(bflow, "androidboot.force_normal_boot", 308 "1", false); 309 if (ret < 0) { 310 log_debug("normal_boot %d", ret); 311 goto free_priv; 312 } 313 } 314 315 bflow->state = BOOTFLOWST_READY; 316 317 return 0; 318 319 free_priv: 320 free(priv); 321 bflow->bootmeth_priv = NULL; 322 return ret; 323} 324 325static int android_read_file(struct udevice *dev, struct bootflow *bflow, 326 const char *file_path, ulong addr, 327 enum bootflow_img_t type, ulong *sizep) 328{ 329 /* 330 * Reading individual files is not supported since we only 331 * operate on whole mmc devices (because we require multiple partitions) 332 */ 333 return log_msg_ret("Unsupported", -ENOSYS); 334} 335 336/** 337 * read_slotted_partition() - Read a partition by appending a slot suffix 338 * 339 * Most modern Android devices use Seamless Updates, where each partition 340 * is duplicated. For example, the boot partition has boot_a and boot_b. 341 * For more information, see: 342 * https://source.android.com/docs/core/ota/ab 343 * https://source.android.com/docs/core/ota/ab/ab_implement 344 * 345 * @blk: Block device to read 346 * @name: Partition name to read 347 * @slot: Nul-terminated slot suffixed to partition name ("a\0" or "b\0") 348 * @image_size: Image size in bytes used when reading the partition 349 * @addr: Address where the partition content is loaded into 350 * Return: 0 if OK, negative errno on failure. 351 */ 352static int read_slotted_partition(struct blk_desc *desc, const char *const name, 353 const char slot[2], ulong image_size, ulong addr) 354{ 355 struct disk_partition partition; 356 char partname[PART_NAME_LEN]; 357 size_t partname_len; 358 ulong num_blks = DIV_ROUND_UP(image_size, desc->blksz); 359 int ret; 360 u32 n; 361 362 /* 363 * Ensure name fits in partname. 364 * For A/B, it should be <name>_<slot>\0 365 * For non A/B, it should be <name>\0 366 */ 367 if (CONFIG_IS_ENABLED(ANDROID_AB)) 368 partname_len = PART_NAME_LEN - 2 - 1; 369 else 370 partname_len = PART_NAME_LEN - 1; 371 372 if (strlen(name) > partname_len) 373 return log_msg_ret("name too long", -EINVAL); 374 375 if (slot) 376 sprintf(partname, "%s_%s", name, slot); 377 else 378 sprintf(partname, "%s", name); 379 380 ret = part_get_info_by_name(desc, partname, &partition); 381 if (ret < 0) 382 return log_msg_ret("part", ret); 383 384 n = blk_dread(desc, partition.start, num_blks, map_sysmem(addr, 0)); 385 if (n < num_blks) 386 return log_msg_ret("part read", -EIO); 387 388 return 0; 389} 390 391#if CONFIG_IS_ENABLED(AVB_VERIFY) 392static int avb_append_commandline_arg(struct bootflow *bflow, char *arg) 393{ 394 char *key = strsep(&arg, "="); 395 char *value = arg; 396 int ret; 397 398 ret = bootflow_cmdline_set_arg(bflow, key, value, false); 399 if (ret < 0) 400 return log_msg_ret("avb cmdline", ret); 401 402 return 0; 403} 404 405static int avb_append_commandline(struct bootflow *bflow, char *cmdline) 406{ 407 char *arg = strsep(&cmdline, " "); 408 int ret; 409 410 while (arg) { 411 ret = avb_append_commandline_arg(bflow, arg); 412 if (ret < 0) 413 return ret; 414 415 arg = strsep(&cmdline, " "); 416 } 417 418 return 0; 419} 420 421static int run_avb_verification(struct bootflow *bflow) 422{ 423 struct blk_desc *desc = dev_get_uclass_plat(bflow->blk); 424 struct android_priv *priv = bflow->bootmeth_priv; 425 const char * const requested_partitions[] = {"boot", "vendor_boot", NULL}; 426 struct AvbOps *avb_ops; 427 AvbSlotVerifyResult result; 428 AvbSlotVerifyData *out_data; 429 enum avb_boot_state boot_state; 430 char *extra_args; 431 char slot_suffix[3] = ""; 432 bool unlocked = false; 433 int ret; 434 435 avb_ops = avb_ops_alloc(desc->devnum); 436 if (!avb_ops) 437 return log_msg_ret("avb ops", -ENOMEM); 438 439 if (priv->slot) 440 sprintf(slot_suffix, "_%s", priv->slot); 441 442 ret = avb_ops->read_is_device_unlocked(avb_ops, &unlocked); 443 if (ret != AVB_IO_RESULT_OK) 444 return log_msg_ret("avb lock", -EIO); 445 446 result = avb_slot_verify(avb_ops, 447 requested_partitions, 448 slot_suffix, 449 unlocked, 450 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, 451 &out_data); 452 453 if (!unlocked) { 454 /* When device is locked, we only accept AVB_SLOT_VERIFY_RESULT_OK */ 455 if (result != AVB_SLOT_VERIFY_RESULT_OK) { 456 printf("Verification failed, reason: %s\n", 457 str_avb_slot_error(result)); 458 avb_slot_verify_data_free(out_data); 459 return log_msg_ret("avb verify", -EIO); 460 } 461 boot_state = AVB_GREEN; 462 } else { 463 /* When device is unlocked, we also accept verification errors */ 464 if (result != AVB_SLOT_VERIFY_RESULT_OK && 465 result != AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION) { 466 printf("Unlocked verification failed, reason: %s\n", 467 str_avb_slot_error(result)); 468 avb_slot_verify_data_free(out_data); 469 return log_msg_ret("avb verify unlocked", -EIO); 470 } 471 boot_state = AVB_ORANGE; 472 } 473 474 extra_args = avb_set_state(avb_ops, boot_state); 475 if (extra_args) { 476 /* extra_args will be modified after this. This is fine */ 477 ret = avb_append_commandline_arg(bflow, extra_args); 478 if (ret < 0) 479 goto free_out_data; 480 } 481 482 if (result == AVB_SLOT_VERIFY_RESULT_OK) { 483 ret = avb_append_commandline(bflow, out_data->cmdline); 484 if (ret < 0) 485 goto free_out_data; 486 } 487 488 return 0; 489 490 free_out_data: 491 if (out_data) 492 avb_slot_verify_data_free(out_data); 493 494 return log_msg_ret("avb cmdline", ret); 495} 496#else 497static int run_avb_verification(struct bootflow *bflow) 498{ 499 int ret; 500 501 /* When AVB is unsupported, pass ORANGE state */ 502 ret = bootflow_cmdline_set_arg(bflow, 503 "androidboot.verifiedbootstate", 504 "orange", false); 505 if (ret < 0) 506 return log_msg_ret("avb cmdline", ret); 507 508 return 0; 509} 510#endif /* AVB_VERIFY */ 511 512static int boot_android_normal(struct bootflow *bflow) 513{ 514 struct blk_desc *desc = dev_get_uclass_plat(bflow->blk); 515 struct android_priv *priv = bflow->bootmeth_priv; 516 int ret; 517 ulong loadaddr = env_get_hex("loadaddr", 0); 518 ulong vloadaddr = env_get_hex("vendor_boot_comp_addr_r", 0); 519 520 ret = run_avb_verification(bflow); 521 if (ret < 0) 522 return log_msg_ret("avb", ret); 523 524 /* Read slot once more to decrement counter from BCB */ 525 ret = android_read_slot_from_bcb(bflow, true); 526 if (ret < 0) 527 return log_msg_ret("read slot", ret); 528 529 ret = read_slotted_partition(desc, "boot", priv->slot, priv->boot_img_size, 530 loadaddr); 531 if (ret < 0) 532 return log_msg_ret("read boot", ret); 533 534 if (priv->header_version >= 3) { 535 ret = read_slotted_partition(desc, "vendor_boot", priv->slot, 536 priv->vendor_boot_img_size, vloadaddr); 537 if (ret < 0) 538 return log_msg_ret("read vendor_boot", ret); 539 set_avendor_bootimg_addr(vloadaddr); 540 } 541 set_abootimg_addr(loadaddr); 542 543 if (priv->slot) 544 free(priv->slot); 545 546 ret = bootm_boot_start(loadaddr, bflow->cmdline); 547 548 return log_msg_ret("boot", ret); 549} 550 551static int boot_android_recovery(struct bootflow *bflow) 552{ 553 int ret; 554 555 ret = boot_android_normal(bflow); 556 557 return log_msg_ret("boot", ret); 558} 559 560static int boot_android_bootloader(struct bootflow *bflow) 561{ 562 int ret; 563 564 ret = run_command("fastboot usb 0", 0); 565 do_reset(NULL, 0, 0, NULL); 566 567 return log_msg_ret("boot", ret); 568} 569 570static int android_boot(struct udevice *dev, struct bootflow *bflow) 571{ 572 struct android_priv *priv = bflow->bootmeth_priv; 573 int ret; 574 575 switch (priv->boot_mode) { 576 case ANDROID_BOOT_MODE_NORMAL: 577 ret = boot_android_normal(bflow); 578 break; 579 case ANDROID_BOOT_MODE_RECOVERY: 580 ret = boot_android_recovery(bflow); 581 break; 582 case ANDROID_BOOT_MODE_BOOTLOADER: 583 ret = boot_android_bootloader(bflow); 584 break; 585 default: 586 printf("ANDROID: Unknown boot mode %d. Running fastboot...\n", 587 priv->boot_mode); 588 boot_android_bootloader(bflow); 589 /* Tell we failed to boot since boot mode is unknown */ 590 ret = -EFAULT; 591 } 592 593 return ret; 594} 595 596static int android_bootmeth_bind(struct udevice *dev) 597{ 598 struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev); 599 600 plat->desc = "Android boot"; 601 plat->flags = BOOTMETHF_ANY_PART; 602 603 return 0; 604} 605 606static struct bootmeth_ops android_bootmeth_ops = { 607 .check = android_check, 608 .read_bootflow = android_read_bootflow, 609 .read_file = android_read_file, 610 .boot = android_boot, 611}; 612 613static const struct udevice_id android_bootmeth_ids[] = { 614 { .compatible = "u-boot,android" }, 615 { } 616}; 617 618U_BOOT_DRIVER(bootmeth_android) = { 619 .name = "bootmeth_android", 620 .id = UCLASS_BOOTMETH, 621 .of_match = android_bootmeth_ids, 622 .ops = &android_bootmeth_ops, 623 .bind = android_bootmeth_bind, 624};