1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7 #include <android_ab.h> 8 9 #include <android_bootloader_message.h> 10 #include <android_image.h> 11 #include <boot_rkimg.h> 12 #include <common.h> 13 #include <malloc.h> 14 #include <android_avb/avb_ops_user.h> 15 #include <android_avb/rk_avb_ops_user.h> 16 #include <u-boot/crc.h> 17 #include <boot_rkimg.h> 18 19 /** android_boot_control_compute_crc - Compute the CRC-32 of the bootloader 20 * control struct. Only the bytes up to the crc32_le field are considered for 21 * the CRC-32 calculation. 22 */ 23 static uint32_t android_boot_control_compute_crc( 24 struct android_bootloader_control *abc) 25 { 26 return crc32(0, (void *)abc, offsetof(typeof(*abc), crc32_le)); 27 } 28 29 /** android_boot_control_default - Initialize android_bootloader_control to the 30 * default value which allows to boot all slots in order from the first one. 31 * This value should be used when the bootloader message is corrupted, but not 32 * when a valid message indicates that all slots are unbootable. 33 */ 34 void android_boot_control_default(struct android_bootloader_control *abc) 35 { 36 int i; 37 const struct android_slot_metadata metadata = { 38 .priority = 15, 39 .tries_remaining = 7, 40 .successful_boot = 0, 41 .verity_corrupted = 0, 42 .reserved = 0 43 }; 44 memcpy(abc->slot_suffix, "a\0\0\0", 4); 45 abc->magic = ANDROID_BOOT_CTRL_MAGIC; 46 abc->version = ANDROID_BOOT_CTRL_VERSION; 47 abc->nb_slot = ARRAY_SIZE(abc->slot_info); 48 memset(abc->reserved0, 0, sizeof(abc->reserved0)); 49 for (i = 0; i < abc->nb_slot; ++i) { 50 abc->slot_info[i] = metadata; 51 } 52 memset(abc->reserved1, 0, sizeof(abc->reserved1)); 53 abc->crc32_le = android_boot_control_compute_crc(abc); 54 } 55 56 /** android_boot_control_create_from_disk 57 * Load the boot_control struct from disk into newly allocated memory. This 58 * function allocates and returns an integer number of disk blocks, based on the 59 * block size of the passed device to help performing a read-modify-write 60 * operation on the boot_control struct. The boot_control struct offset (2 KiB) 61 * must be a multiple of the device block size, for simplicity. 62 * @dev_desc: device where to read the boot_control struct from. 63 * @part_info: partition in 'dev_desc' where to read from, normally the "misc" 64 * partition should be used. 65 */ 66 static void *android_boot_control_create_from_disk( 67 struct blk_desc *dev_desc, 68 const disk_partition_t *part_info) 69 { 70 ulong abc_offset, abc_blocks; 71 void *buf; 72 73 abc_offset = offsetof(struct android_bootloader_message_ab, 74 slot_suffix); 75 if (abc_offset % part_info->blksz) { 76 printf("ANDROID: Boot control block not block aligned.\n"); 77 return NULL; 78 } 79 abc_offset /= part_info->blksz; 80 81 abc_blocks = DIV_ROUND_UP(sizeof(struct android_bootloader_control), 82 part_info->blksz); 83 if (abc_offset + abc_blocks > part_info->size) { 84 printf("ANDROID: boot control partition too small. Need at" 85 " least %lu blocks but have %lu blocks.\n", 86 abc_offset + abc_blocks, part_info->size); 87 return NULL; 88 } 89 buf = malloc(abc_blocks * part_info->blksz); 90 if (!buf) 91 return NULL; 92 93 if (blk_dread(dev_desc, part_info->start + abc_offset, abc_blocks, 94 buf) != abc_blocks) { 95 printf("ANDROID: Could not read from boot control partition\n"); 96 free(buf); 97 return NULL; 98 } 99 debug("ANDROID: Loaded ABC, %lu blocks.\n", abc_blocks); 100 return buf; 101 } 102 103 /** android_boot_control_store 104 * Store the loaded boot_control block back to the same location it was read 105 * from with android_boot_control_create_from_misc(). 106 * 107 * @abc_data_block: pointer to the boot_control struct and the extra bytes after 108 * it up to the nearest block boundary. 109 * @dev_desc: device where we should write the boot_control struct. 110 * @part_info: partition on the 'dev_desc' where to write. 111 * @return 0 on success and -1 on error. 112 */ 113 static int android_boot_control_store(void *abc_data_block, 114 struct blk_desc *dev_desc, 115 const disk_partition_t *part_info) 116 { 117 ulong abc_offset, abc_blocks; 118 119 abc_offset = offsetof(struct android_bootloader_message_ab, 120 slot_suffix) / part_info->blksz; 121 abc_blocks = DIV_ROUND_UP(sizeof(struct android_bootloader_control), 122 part_info->blksz); 123 if (blk_dwrite(dev_desc, part_info->start + abc_offset, abc_blocks, 124 abc_data_block) != abc_blocks) { 125 printf("ANDROID: Could not write back the misc partition\n"); 126 return -1; 127 } 128 return 0; 129 } 130 131 /** android_boot_compare_slots - compares two slots returning which slot is 132 * should we boot from among the two. 133 * @a: The first bootable slot metadata 134 * @b: The second bootable slot metadata 135 * @return negative if the slot "a" is better, positive of the slot "b" is 136 * better or 0 if they are equally good. 137 */ 138 static int android_ab_compare_slots(const struct android_slot_metadata *a, 139 const struct android_slot_metadata *b) 140 { 141 /* Higher priority is better */ 142 if (a->priority != b->priority) 143 return b->priority - a->priority; 144 145 /* Higher successful_boot value is better, in case of same priority. */ 146 if (a->successful_boot != b->successful_boot) 147 return b->successful_boot - a->successful_boot; 148 149 /* Higher tries_remaining is better to ensure round-robin. */ 150 if (a->tries_remaining != b->tries_remaining) 151 return b->tries_remaining - a->tries_remaining; 152 153 return 0; 154 } 155 156 int android_ab_select(struct blk_desc *dev_desc, disk_partition_t *part_info) 157 { 158 struct android_bootloader_control *abc; 159 u32 crc32_le; 160 int slot, i; 161 bool store_needed = false; 162 char slot_suffix[4]; 163 164 abc = android_boot_control_create_from_disk(dev_desc, part_info); 165 if (!abc) { 166 /* This condition represents an actual problem with the code 167 * or the board setup, like an invalid partition information. 168 * Signal a repair mode and do not try to boot from either 169 * slot. 170 */ 171 return -1; 172 } 173 174 crc32_le = android_boot_control_compute_crc(abc); 175 if (abc->crc32_le != crc32_le) { 176 printf("ANDROID: Invalid CRC-32 (expected %.8x, found %.8x), " 177 "re-initializing A/B metadata.\n", 178 crc32_le, abc->crc32_le); 179 android_boot_control_default(abc); 180 store_needed = true; 181 } 182 183 if (abc->magic != ANDROID_BOOT_CTRL_MAGIC) { 184 printf("ANDROID: Unknown A/B metadata: %.8x\n", abc->magic); 185 free(abc); 186 return -1; 187 } 188 189 if (abc->version > ANDROID_BOOT_CTRL_VERSION) { 190 printf("ANDROID: Unsupported A/B metadata version: %.8x\n", 191 abc->version); 192 free(abc); 193 return -1; 194 } 195 196 /* At this point a valid boot control metadata is stored in abc, 197 * followed by other reserved data in the same block. 198 * We select a with the higher priority slot that 199 * - is not marked as corrupted and 200 * - either has tries_remaining > 0 or successful_boot is true. 201 * If the slot selected has a false successful_boot, we also decrement 202 * the tries_remaining until it eventually becomes unbootable because 203 * tries_remaining reaches 0. This mechanism produces a bootloader 204 * induced rollback, typically right after a failed update. 205 */ 206 207 /* Safety check: limit the number of slots. */ 208 if (abc->nb_slot > ARRAY_SIZE(abc->slot_info)) { 209 abc->nb_slot = ARRAY_SIZE(abc->slot_info); 210 store_needed = true; 211 } 212 213 slot = -1; 214 for (i = 0; i < abc->nb_slot; ++i) { 215 if (abc->slot_info[i].verity_corrupted || 216 !abc->slot_info[i].tries_remaining) { 217 debug("ANDROID: unbootable slot %d tries: %d, " 218 "corrupt: %d\n", 219 i, 220 abc->slot_info[i].tries_remaining, 221 abc->slot_info[i].verity_corrupted); 222 continue; 223 } 224 debug("ANDROID: bootable slot %d pri: %d, tries: %d, " 225 "corrupt: %d, successful: %d\n", 226 i, 227 abc->slot_info[i].priority, 228 abc->slot_info[i].tries_remaining, 229 abc->slot_info[i].verity_corrupted, 230 abc->slot_info[i].successful_boot); 231 232 if (slot < 0 || 233 android_ab_compare_slots(&abc->slot_info[i], 234 &abc->slot_info[slot]) < 0) { 235 slot = i; 236 } 237 } 238 239 if (slot >= 0 && !abc->slot_info[slot].successful_boot) { 240 printf("ANDROID: Attempting slot %c, tries remaining %d\n", 241 ANDROID_BOOT_SLOT_NAME(slot), 242 abc->slot_info[slot].tries_remaining); 243 abc->slot_info[slot].tries_remaining--; 244 store_needed = true; 245 } 246 247 if (slot >= 0) { 248 /* Legacy user-space requires this field to be set in the BCB. 249 * Newer releases load this the slot suffix from the command 250 * line or the device tree. 251 */ 252 memset(slot_suffix, 0, sizeof(slot_suffix)); 253 slot_suffix[0] = ANDROID_BOOT_SLOT_NAME(slot); 254 if (memcmp(abc->slot_suffix, slot_suffix, 255 sizeof(slot_suffix))) { 256 memcpy(abc->slot_suffix, slot_suffix, 257 sizeof(slot_suffix)); 258 store_needed = true; 259 } 260 } 261 262 if (store_needed) { 263 abc->crc32_le = android_boot_control_compute_crc(abc); 264 android_boot_control_store(abc, dev_desc, part_info); 265 } 266 free(abc); 267 268 if (slot < 0) 269 return -1; 270 return slot; 271 } 272 273 int read_misc_virtual_ab_message(struct misc_virtual_ab_message *message) 274 { 275 struct blk_desc *dev_desc; 276 disk_partition_t part_info; 277 u32 bcb_offset = (ANDROID_VIRTUAL_AB_METADATA_OFFSET_IN_MISC >> 9); 278 int cnt, ret; 279 280 if (!message) { 281 debug("%s: message is NULL!\n", __func__); 282 return -1; 283 } 284 285 dev_desc = rockchip_get_bootdev(); 286 if (!dev_desc) { 287 debug("%s: dev_desc is NULL!\n", __func__); 288 return -1; 289 } 290 291 ret = part_get_info_by_name(dev_desc, PART_MISC, &part_info); 292 if (ret < 0) { 293 debug("%s: Could not found misc partition\n", 294 __func__); 295 return -1; 296 } 297 298 cnt = DIV_ROUND_UP(sizeof(struct misc_virtual_ab_message), dev_desc->blksz); 299 if (blk_dread(dev_desc, part_info.start + bcb_offset, cnt, message) != cnt) { 300 debug("%s: could not read from misc partition\n", __func__); 301 return -1; 302 } 303 304 return 0; 305 } 306 307 int write_misc_virtual_ab_message(struct misc_virtual_ab_message *message) 308 { 309 struct blk_desc *dev_desc; 310 disk_partition_t part_info; 311 u32 bcb_offset = (ANDROID_VIRTUAL_AB_METADATA_OFFSET_IN_MISC >> 9); 312 int cnt, ret; 313 314 if (!message) { 315 debug("%s: message is NULL!\n", __func__); 316 return -1; 317 } 318 319 dev_desc = rockchip_get_bootdev(); 320 if (!dev_desc) { 321 debug("%s: dev_desc is NULL!\n", __func__); 322 return -1; 323 } 324 325 ret = part_get_info_by_name(dev_desc, PART_MISC, &part_info); 326 if (ret < 0) { 327 debug("%s: Could not found misc partition\n", 328 __func__); 329 return -1; 330 } 331 332 cnt = DIV_ROUND_UP(sizeof(struct misc_virtual_ab_message), dev_desc->blksz); 333 ret = blk_dwrite(dev_desc, part_info.start + bcb_offset, cnt, message); 334 if (ret != cnt) 335 debug("%s: blk_dwrite write failed, ret=%d\n", __func__, ret); 336 337 return 0; 338 } 339 340 int ab_is_support_dynamic_partition(struct blk_desc *dev_desc) 341 { 342 disk_partition_t super_part_info; 343 disk_partition_t boot_part_info; 344 int part_num; 345 int is_dp = 0; 346 char *super_dp = NULL; 347 char *super_info = "androidboot.super_partition="; 348 349 memset(&super_part_info, 0x0, sizeof(super_part_info)); 350 part_num = part_get_info_by_name(dev_desc, ANDROID_PARTITION_SUPER, 351 &super_part_info); 352 if (part_num < 0) { 353 memset(&boot_part_info, 0x0, sizeof(boot_part_info)); 354 part_num = part_get_info_by_name(dev_desc, ANDROID_PARTITION_BOOT, 355 &boot_part_info); 356 if (part_num < 0) { 357 is_dp = 0; 358 } else { 359 andr_img_hdr hdr; 360 ulong hdr_blocks = sizeof(struct andr_img_hdr) / 361 boot_part_info.blksz; 362 363 memset(&hdr, 0x0, sizeof(hdr)); 364 if (blk_dread(dev_desc, boot_part_info.start, hdr_blocks, &hdr) != 365 hdr_blocks) { 366 is_dp = 0; 367 } else { 368 debug("hdr cmdline=%s\n", hdr.cmdline); 369 super_dp = strstr(hdr.cmdline, super_info); 370 if (super_dp) 371 is_dp = 1; 372 else 373 is_dp = 0; 374 } 375 } 376 } else { 377 debug("Find super partition, the firmware support dynamic partition\n"); 378 is_dp = 1; 379 } 380 381 debug("%s is_dp=%d\n", __func__, is_dp); 382 return is_dp; 383 } 384 385 static int get_partition_unique_uuid(char *partition, 386 char *guid_buf, 387 size_t guid_buf_size) 388 { 389 struct blk_desc *dev_desc; 390 disk_partition_t part_info; 391 392 dev_desc = rockchip_get_bootdev(); 393 if (!dev_desc) { 394 printf("%s: Could not find device\n", __func__); 395 return -1; 396 } 397 398 if (part_get_info_by_name(dev_desc, partition, &part_info) < 0) { 399 printf("Could not find \"%s\" partition\n", partition); 400 return -1; 401 } 402 403 if (guid_buf && guid_buf_size > 0) 404 memcpy(guid_buf, part_info.uuid, guid_buf_size); 405 406 return 0; 407 } 408 409 static void ab_update_root_uuid(void) 410 { 411 /* 412 * In android a/b & avb process, the system.img is mandory and the 413 * "root=" will be added in vbmeta.img. 414 * 415 * In linux a/b & avb process, the system is NOT mandory and the 416 * "root=" will not be added in vbmeta.img but in kernel dts bootargs. 417 * (Parsed and dropped late, i.e. "root=" is not available now/always). 418 * 419 * To compatible with the above two processes, test the existence of 420 * "root=" and create it for linux ab & avb. 421 */ 422 char root_partuuid[70] = "root=PARTUUID="; 423 char *boot_args = env_get("bootargs"); 424 char guid_buf[UUID_SIZE] = {0}; 425 struct blk_desc *dev_desc; 426 427 dev_desc = rockchip_get_bootdev(); 428 if (!dev_desc) { 429 printf("%s: Could not find device\n", __func__); 430 return; 431 } 432 433 if (ab_is_support_dynamic_partition(dev_desc)) 434 return; 435 436 if (!strstr(boot_args, "root=")) { 437 get_partition_unique_uuid(ANDROID_PARTITION_SYSTEM, 438 guid_buf, UUID_SIZE); 439 strcat(root_partuuid, guid_buf); 440 env_update("bootargs", root_partuuid); 441 } 442 } 443 444 void ab_update_root_partition(void) 445 { 446 char *boot_args = env_get("bootargs"); 447 char root_part_dev[64] = {0}; 448 disk_partition_t part_info; 449 struct blk_desc *dev_desc; 450 const char *part_type; 451 int part_num; 452 453 dev_desc = rockchip_get_bootdev(); 454 if (!dev_desc) 455 return; 456 457 if (ab_is_support_dynamic_partition(dev_desc)) 458 return; 459 460 /* Get 'system' partition device number. */ 461 part_num = part_get_info_by_name(dev_desc, ANDROID_PARTITION_SYSTEM, &part_info); 462 if (part_num < 0) { 463 printf("%s: Failed to get partition '%s'.\n", __func__, ANDROID_PARTITION_SYSTEM); 464 return; 465 } 466 467 /* Get partition type. */ 468 part_type = part_get_type(dev_desc); 469 if (!part_type) 470 return; 471 472 /* Judge the partition device type. */ 473 switch (dev_desc->if_type) { 474 case IF_TYPE_MMC: 475 if (strstr(part_type, "ENV")) 476 snprintf(root_part_dev, 64, "root=/dev/mmcblk0p%d", part_num); 477 else if (strstr(part_type, "EFI")) 478 ab_update_root_uuid(); 479 break; 480 case IF_TYPE_SPINAND: 481 if (strstr(part_type, "ENV")) 482 /* TODO */ 483 printf("%s: TODO: ENV partition for 'IF_TYPE_SPINAND'.\n", __func__); 484 else if (strstr(part_type, "EFI")) 485 ab_update_root_uuid(); 486 break; 487 case IF_TYPE_MTD: 488 if (dev_desc->devnum == BLK_MTD_NAND || dev_desc->devnum == BLK_MTD_SPI_NAND) { 489 if (strstr(boot_args, "rootfstype=squashfs") || strstr(boot_args, "rootfstype=erofs")) 490 snprintf(root_part_dev, 64, "ubi.mtd=%d root=/dev/ubiblock0_0", part_num - 1); 491 else if (strstr(boot_args, "rootfstype=ubifs")) 492 snprintf(root_part_dev, 64, "ubi.mtd=%d root=ubi0:system", part_num - 1); 493 } else if (dev_desc->devnum == BLK_MTD_SPI_NOR) { 494 snprintf(root_part_dev, 64, "root=/dev/mtdblock%d", part_num - 1); 495 } 496 break; 497 default: 498 printf("%s: Not found part type, failed to set root part device.\n", __func__); 499 return; 500 } 501 502 env_update("bootargs", root_part_dev); 503 } 504 505 int ab_get_slot_suffix(char *slot_suffix) 506 { 507 /* TODO: get from pre-loader or misc partition */ 508 if (rk_avb_get_current_slot(slot_suffix)) { 509 printf("rk_avb_get_current_slot() failed\n"); 510 return -1; 511 } 512 513 if (slot_suffix[0] != '_') { 514 #ifndef CONFIG_ANDROID_AVB 515 printf("###There is no bootable slot, bring up lastboot!###\n"); 516 if (rk_get_lastboot() == 1) 517 memcpy(slot_suffix, "_b", 2); 518 else if (rk_get_lastboot() == 0) 519 memcpy(slot_suffix, "_a", 2); 520 else 521 #endif 522 return -1; 523 } 524 525 return 0; 526 } 527 528 int ab_decrease_tries(void) 529 { 530 AvbABData ab_data_orig; 531 AvbABData ab_data; 532 char slot_suffix[3] = {0}; 533 AvbOps *ops; 534 size_t slot_index = 0; 535 536 if (ab_get_slot_suffix(slot_suffix)) 537 return -1; 538 539 if (!strncmp(slot_suffix, "_a", 2)) 540 slot_index = 0; 541 else if (!strncmp(slot_suffix, "_b", 2)) 542 slot_index = 1; 543 else 544 slot_index = 0; 545 546 ops = avb_ops_user_new(); 547 if (!ops) { 548 printf("avb_ops_user_new() failed!\n"); 549 return -1; 550 } 551 552 if (load_metadata(ops->ab_ops, &ab_data, &ab_data_orig)) { 553 printf("Can not load metadata\n"); 554 return -1; 555 } 556 557 /* ... and decrement tries remaining, if applicable. */ 558 if (!ab_data.slots[slot_index].successful_boot && 559 ab_data.slots[slot_index].tries_remaining > 0) 560 ab_data.slots[slot_index].tries_remaining -= 1; 561 562 if (save_metadata_if_changed(ops->ab_ops, &ab_data, &ab_data_orig)) { 563 printf("Can not save metadata\n"); 564 return -1; 565 } 566 567 return 0; 568 } 569 570 /* 571 * In android A/B system, there is no recovery partition, 572 * but in the linux system, we need the recovery to update system. 573 * This function is used to find firmware in recovery partition 574 * when enable CONFIG_ANDROID_AB. 575 */ 576 bool ab_can_find_recovery_part(void) 577 { 578 disk_partition_t part_info; 579 struct blk_desc *dev_desc; 580 int part_num; 581 582 dev_desc = rockchip_get_bootdev(); 583 if (!dev_desc) { 584 printf("%s: Could not find device\n", __func__); 585 return false; 586 } 587 588 part_num = part_get_info_by_name(dev_desc, ANDROID_PARTITION_RECOVERY, 589 &part_info); 590 if (part_num < 0) 591 return false; 592 else 593 return true; 594 } 595