"Das U-Boot" Source Tree
at master 443 lines 13 kB view raw
1// SPDX-License-Identifier: BSD-2-Clause 2/* 3 * Copyright (C) 2017 The Android Open Source Project 4 */ 5#include <android_ab.h> 6#include <android_bootloader_message.h> 7#include <blk.h> 8#include <log.h> 9#include <malloc.h> 10#include <part.h> 11#include <memalign.h> 12#include <linux/err.h> 13#include <u-boot/crc.h> 14 15/** 16 * ab_control_compute_crc() - Compute the CRC32 of the bootloader control. 17 * 18 * @abc: Bootloader control block 19 * 20 * Only the bytes up to the crc32_le field are considered for the CRC-32 21 * calculation. 22 * 23 * Return: crc32 sum 24 */ 25static uint32_t ab_control_compute_crc(struct bootloader_control *abc) 26{ 27 return crc32(0, (void *)abc, offsetof(typeof(*abc), crc32_le)); 28} 29 30/** 31 * ab_control_default() - Initialize bootloader_control to the default value. 32 * 33 * @abc: Bootloader control block 34 * 35 * It allows us to boot all slots in order from the first one. This value 36 * should be used when the bootloader message is corrupted, but not when 37 * a valid message indicates that all slots are unbootable. 38 * 39 * Return: 0 on success and a negative on error 40 */ 41static int ab_control_default(struct bootloader_control *abc) 42{ 43 int i; 44 const struct slot_metadata metadata = { 45 .priority = 15, 46 .tries_remaining = 7, 47 .successful_boot = 0, 48 .verity_corrupted = 0, 49 .reserved = 0 50 }; 51 52 if (!abc) 53 return -EFAULT; 54 55 memcpy(abc->slot_suffix, "_a\0\0", 4); 56 abc->magic = BOOT_CTRL_MAGIC; 57 abc->version = BOOT_CTRL_VERSION; 58 abc->nb_slot = NUM_SLOTS; 59 memset(abc->reserved0, 0, sizeof(abc->reserved0)); 60 for (i = 0; i < abc->nb_slot; ++i) 61 abc->slot_info[i] = metadata; 62 63 memset(abc->reserved1, 0, sizeof(abc->reserved1)); 64 abc->crc32_le = ab_control_compute_crc(abc); 65 66 return 0; 67} 68 69/** 70 * ab_control_create_from_disk() - Load the boot_control from disk into memory. 71 * 72 * @dev_desc: Device where to read the boot_control struct from 73 * @part_info: Partition in 'dev_desc' where to read from, normally 74 * the "misc" partition should be used 75 * @abc: pointer to pointer to bootloader_control data 76 * @offset: boot_control struct offset 77 * 78 * This function allocates and returns an integer number of disk blocks, 79 * based on the block size of the passed device to help performing a 80 * read-modify-write operation on the boot_control struct. 81 * The boot_control struct offset (2 KiB) must be a multiple of the device 82 * block size, for simplicity. 83 * 84 * Return: 0 on success and a negative on error 85 */ 86static int ab_control_create_from_disk(struct blk_desc *dev_desc, 87 const struct disk_partition *part_info, 88 struct bootloader_control **abc, 89 ulong offset) 90{ 91 ulong abc_offset, abc_blocks, ret; 92 93 abc_offset = offset + 94 offsetof(struct bootloader_message_ab, slot_suffix); 95 if (abc_offset % part_info->blksz) { 96 log_err("ANDROID: Boot control block not block aligned.\n"); 97 return -EINVAL; 98 } 99 abc_offset /= part_info->blksz; 100 101 abc_blocks = DIV_ROUND_UP(sizeof(struct bootloader_control), 102 part_info->blksz); 103 if (abc_offset + abc_blocks > part_info->size) { 104 log_err("ANDROID: boot control partition too small. Need at"); 105 log_err(" least %lu blocks but have %lu blocks.\n", 106 abc_offset + abc_blocks, part_info->size); 107 return -EINVAL; 108 } 109 *abc = malloc_cache_aligned(abc_blocks * part_info->blksz); 110 if (!*abc) 111 return -ENOMEM; 112 113 ret = blk_dread(dev_desc, part_info->start + abc_offset, abc_blocks, 114 *abc); 115 if (IS_ERR_VALUE(ret)) { 116 log_err("ANDROID: Could not read from boot ctrl partition\n"); 117 free(*abc); 118 return -EIO; 119 } 120 121 log_debug("ANDROID: Loaded ABC, %lu blocks\n", abc_blocks); 122 123 return 0; 124} 125 126/** 127 * ab_control_store() - Store the loaded boot_control block. 128 * 129 * @dev_desc: Device where we should write the boot_control struct 130 * @part_info: Partition on the 'dev_desc' where to write 131 * @abc Pointer to the boot control struct and the extra bytes after 132 * it up to the nearest block boundary 133 * @offset: boot_control struct offset 134 * 135 * Store back to the same location it was read from with 136 * ab_control_create_from_misc(). 137 * 138 * Return: 0 on success and a negative on error 139 */ 140static int ab_control_store(struct blk_desc *dev_desc, 141 const struct disk_partition *part_info, 142 struct bootloader_control *abc, ulong offset) 143{ 144 ulong abc_offset, abc_blocks, ret; 145 146 if (offset % part_info->blksz) { 147 log_err("ANDROID: offset not block aligned\n"); 148 return -EINVAL; 149 } 150 151 abc_offset = (offset + 152 offsetof(struct bootloader_message_ab, slot_suffix)) / 153 part_info->blksz; 154 abc_blocks = DIV_ROUND_UP(sizeof(struct bootloader_control), 155 part_info->blksz); 156 ret = blk_dwrite(dev_desc, part_info->start + abc_offset, abc_blocks, 157 abc); 158 if (IS_ERR_VALUE(ret)) { 159 log_err("ANDROID: Could not write back the misc partition\n"); 160 return -EIO; 161 } 162 163 return 0; 164} 165 166/** 167 * ab_compare_slots() - Compare two slots. 168 * 169 * @a: The first bootable slot metadata 170 * @b: The second bootable slot metadata 171 * 172 * The function determines slot which is should we boot from among the two. 173 * 174 * Return: Negative if the slot "a" is better, positive of the slot "b" is 175 * better or 0 if they are equally good. 176 */ 177static int ab_compare_slots(const struct slot_metadata *a, 178 const struct slot_metadata *b) 179{ 180 /* Higher priority is better */ 181 if (a->priority != b->priority) 182 return b->priority - a->priority; 183 184 /* Higher successful_boot value is better, in case of same priority */ 185 if (a->successful_boot != b->successful_boot) 186 return b->successful_boot - a->successful_boot; 187 188 /* Higher tries_remaining is better to ensure round-robin */ 189 if (a->tries_remaining != b->tries_remaining) 190 return b->tries_remaining - a->tries_remaining; 191 192 return 0; 193} 194 195int ab_select_slot(struct blk_desc *dev_desc, struct disk_partition *part_info, 196 bool dec_tries) 197{ 198 struct bootloader_control *abc = NULL; 199 struct bootloader_control *backup_abc = NULL; 200 u32 crc32_le; 201 int slot, i, ret; 202 bool store_needed = false; 203 bool valid_backup = false; 204 char slot_suffix[4]; 205 206 ret = ab_control_create_from_disk(dev_desc, part_info, &abc, 0); 207 if (ret < 0) { 208 /* 209 * This condition represents an actual problem with the code or 210 * the board setup, like an invalid partition information. 211 * Signal a repair mode and do not try to boot from either slot. 212 */ 213 return ret; 214 } 215 216 if (CONFIG_ANDROID_AB_BACKUP_OFFSET) { 217 ret = ab_control_create_from_disk(dev_desc, part_info, &backup_abc, 218 CONFIG_ANDROID_AB_BACKUP_OFFSET); 219 if (ret < 0) { 220 free(abc); 221 return ret; 222 } 223 } 224 225 crc32_le = ab_control_compute_crc(abc); 226 if (abc->crc32_le != crc32_le) { 227 log_err("ANDROID: Invalid CRC-32 (expected %.8x, found %.8x),", 228 crc32_le, abc->crc32_le); 229 if (CONFIG_ANDROID_AB_BACKUP_OFFSET) { 230 crc32_le = ab_control_compute_crc(backup_abc); 231 if (backup_abc->crc32_le != crc32_le) { 232 log_err(" ANDROID: Invalid backup CRC-32 "); 233 log_err("(expected %.8x, found %.8x),", 234 crc32_le, backup_abc->crc32_le); 235 } else { 236 valid_backup = true; 237 log_info(" copying A/B metadata from backup.\n"); 238 memcpy(abc, backup_abc, sizeof(*abc)); 239 } 240 } 241 242 if (!valid_backup) { 243 log_err(" re-initializing A/B metadata.\n"); 244 ret = ab_control_default(abc); 245 if (ret < 0) { 246 if (CONFIG_ANDROID_AB_BACKUP_OFFSET) 247 free(backup_abc); 248 free(abc); 249 return -ENODATA; 250 } 251 } 252 store_needed = true; 253 } 254 255 if (abc->magic != BOOT_CTRL_MAGIC) { 256 log_err("ANDROID: Unknown A/B metadata: %.8x\n", abc->magic); 257 if (CONFIG_ANDROID_AB_BACKUP_OFFSET) 258 free(backup_abc); 259 free(abc); 260 return -ENODATA; 261 } 262 263 if (abc->version > BOOT_CTRL_VERSION) { 264 log_err("ANDROID: Unsupported A/B metadata version: %.8x\n", 265 abc->version); 266 if (CONFIG_ANDROID_AB_BACKUP_OFFSET) 267 free(backup_abc); 268 free(abc); 269 return -ENODATA; 270 } 271 272 /* 273 * At this point a valid boot control metadata is stored in abc, 274 * followed by other reserved data in the same block. We select a with 275 * the higher priority slot that 276 * - is not marked as corrupted and 277 * - either has tries_remaining > 0 or successful_boot is true. 278 * If the selected slot has a false successful_boot, we also decrement 279 * the tries_remaining until it eventually becomes unbootable because 280 * tries_remaining reaches 0. This mechanism produces a bootloader 281 * induced rollback, typically right after a failed update. 282 */ 283 284 /* Safety check: limit the number of slots. */ 285 if (abc->nb_slot > ARRAY_SIZE(abc->slot_info)) { 286 abc->nb_slot = ARRAY_SIZE(abc->slot_info); 287 store_needed = true; 288 } 289 290 slot = -1; 291 for (i = 0; i < abc->nb_slot; ++i) { 292 if (abc->slot_info[i].verity_corrupted || 293 !abc->slot_info[i].tries_remaining) { 294 log_debug("ANDROID: unbootable slot %d tries: %d, ", 295 i, abc->slot_info[i].tries_remaining); 296 log_debug("corrupt: %d\n", 297 abc->slot_info[i].verity_corrupted); 298 continue; 299 } 300 log_debug("ANDROID: bootable slot %d pri: %d, tries: %d, ", 301 i, abc->slot_info[i].priority, 302 abc->slot_info[i].tries_remaining); 303 log_debug("corrupt: %d, successful: %d\n", 304 abc->slot_info[i].verity_corrupted, 305 abc->slot_info[i].successful_boot); 306 307 if (slot < 0 || 308 ab_compare_slots(&abc->slot_info[i], 309 &abc->slot_info[slot]) < 0) { 310 slot = i; 311 } 312 } 313 314 if (slot >= 0 && !abc->slot_info[slot].successful_boot) { 315 log_err("ANDROID: Attempting slot %c, tries remaining %d\n", 316 BOOT_SLOT_NAME(slot), 317 abc->slot_info[slot].tries_remaining); 318 if (dec_tries) { 319 abc->slot_info[slot].tries_remaining--; 320 store_needed = true; 321 } 322 } 323 324 if (slot >= 0) { 325 /* 326 * Legacy user-space requires this field to be set in the BCB. 327 * Newer releases load this slot suffix from the command line 328 * or the device tree. 329 */ 330 memset(slot_suffix, 0, sizeof(slot_suffix)); 331 slot_suffix[0] = '_'; 332 slot_suffix[1] = BOOT_SLOT_NAME(slot); 333 if (memcmp(abc->slot_suffix, slot_suffix, 334 sizeof(slot_suffix))) { 335 memcpy(abc->slot_suffix, slot_suffix, 336 sizeof(slot_suffix)); 337 store_needed = true; 338 } 339 } 340 341 if (store_needed) { 342 abc->crc32_le = ab_control_compute_crc(abc); 343 ret = ab_control_store(dev_desc, part_info, abc, 0); 344 if (ret < 0) { 345 if (CONFIG_ANDROID_AB_BACKUP_OFFSET) 346 free(backup_abc); 347 free(abc); 348 return ret; 349 } 350 } 351 352 if (CONFIG_ANDROID_AB_BACKUP_OFFSET) { 353 /* 354 * If the backup doesn't match the primary, write the primary 355 * to the backup offset 356 */ 357 if (memcmp(backup_abc, abc, sizeof(*abc)) != 0) { 358 ret = ab_control_store(dev_desc, part_info, abc, 359 CONFIG_ANDROID_AB_BACKUP_OFFSET); 360 if (ret < 0) { 361 free(backup_abc); 362 free(abc); 363 return ret; 364 } 365 } 366 free(backup_abc); 367 } 368 369 free(abc); 370 371 if (slot < 0) 372 return -EINVAL; 373 374 return slot; 375} 376 377int ab_dump_abc(struct blk_desc *dev_desc, struct disk_partition *part_info) 378{ 379 struct bootloader_control *abc; 380 u32 crc32_le; 381 int i, ret; 382 struct slot_metadata *slot; 383 384 if (!dev_desc || !part_info) { 385 log_err("ANDROID: Empty device descriptor or partition info\n"); 386 return -EINVAL; 387 } 388 389 ret = ab_control_create_from_disk(dev_desc, part_info, &abc, 0); 390 if (ret < 0) { 391 log_err("ANDROID: Cannot create bcb from disk %d\n", ret); 392 return ret; 393 } 394 395 if (abc->magic != BOOT_CTRL_MAGIC) { 396 log_err("ANDROID: Unknown A/B metadata: %.8x\n", abc->magic); 397 ret = -ENODATA; 398 goto error; 399 } 400 401 if (abc->version > BOOT_CTRL_VERSION) { 402 log_err("ANDROID: Unsupported A/B metadata version: %.8x\n", 403 abc->version); 404 ret = -ENODATA; 405 goto error; 406 } 407 408 if (abc->nb_slot > ARRAY_SIZE(abc->slot_info)) { 409 log_err("ANDROID: Wrong number of slots %u, expected %zu\n", 410 abc->nb_slot, ARRAY_SIZE(abc->slot_info)); 411 ret = -ENODATA; 412 goto error; 413 } 414 415 printf("Bootloader Control: [%s]\n", part_info->name); 416 printf("Active Slot: %s\n", abc->slot_suffix); 417 printf("Magic Number: 0x%x\n", abc->magic); 418 printf("Version: %u\n", abc->version); 419 printf("Number of Slots: %u\n", abc->nb_slot); 420 printf("Recovery Tries Remaining: %u\n", abc->recovery_tries_remaining); 421 422 printf("CRC: 0x%.8x", abc->crc32_le); 423 424 crc32_le = ab_control_compute_crc(abc); 425 if (abc->crc32_le != crc32_le) 426 printf(" (Invalid, Expected: 0x%.8x)\n", crc32_le); 427 else 428 printf(" (Valid)\n"); 429 430 for (i = 0; i < abc->nb_slot; ++i) { 431 slot = &abc->slot_info[i]; 432 printf("\nSlot[%d] Metadata:\n", i); 433 printf("\t- Priority: %u\n", slot->priority); 434 printf("\t- Tries Remaining: %u\n", slot->tries_remaining); 435 printf("\t- Successful Boot: %u\n", slot->successful_boot); 436 printf("\t- Verity Corrupted: %u\n", slot->verity_corrupted); 437 } 438 439error: 440 free(abc); 441 442 return ret; 443}