common: android_ab: do not attempt to round-robin bootable slots.
This feature does not quite fit within the A/B flow. The intent of A/B is to provide an automatic rollback option for broken OTAs. Once an OTA has been applied, the slot may not boot for a number of reasons (power loss, broken package, etc), and it is important to make consistent attempts to boot to the new slot rather than find *a* bootable slot (otherwise, the update may not take). Note that once a slot has been marked bootable, encryption keys are upgraded, and old slots will not work. Trying to rotate between slots is not likely to succeed. Note that Android ensures that the active slot always has the highest priority. In the current u-boot implementation, this affords no possibility of rollback. To match the expected A/B flow, this patch makes the following changes: - When initializing the BCB, set the "_a" slot to have the highest priority. - Pick the highest priority slot that has been marked successful OR has boot tries remaining. - If no such slot exists, the system is not bootable. Link: https://android-review.googlesource.com/c/platform/external/u-boot/+/1446442 Signed-off-by: Guillaume La Roque <glaroque@baylibre.com>
This commit is contained in:
parent
b7ab6e41f8
commit
a6a7bd8883
|
|
@ -59,9 +59,17 @@ static int ab_control_default(struct bootloader_control *abc)
|
|||
abc->version = BOOT_CTRL_VERSION;
|
||||
abc->nb_slot = NUM_SLOTS;
|
||||
memset(abc->reserved0, 0, sizeof(abc->reserved0));
|
||||
for (i = 0; i < abc->nb_slot; ++i)
|
||||
for (i = 0; i < abc->nb_slot; ++i) {
|
||||
abc->slot_info[i] = metadata;
|
||||
|
||||
/* One slot should always have higher priority than other slots,
|
||||
* otherwise we can ping-pong between slots based on tries_remaining.
|
||||
* Since the default slot is _a, make _a highest priority.
|
||||
*/
|
||||
if (i != 0)
|
||||
abc->slot_info[i].priority = metadata.priority - 1;
|
||||
}
|
||||
|
||||
memset(abc->reserved1, 0, sizeof(abc->reserved1));
|
||||
abc->crc32_le = ab_control_compute_crc(abc);
|
||||
|
||||
|
|
@ -153,6 +161,11 @@ static int ab_control_store(struct blk_desc *dev_desc,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool is_slot_bootable(const struct slot_metadata* slot)
|
||||
{
|
||||
return slot->tries_remaining > 0 || slot->successful_boot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two slots.
|
||||
*
|
||||
|
|
@ -166,19 +179,14 @@ static int ab_control_store(struct blk_desc *dev_desc,
|
|||
static int ab_compare_slots(const struct slot_metadata *a,
|
||||
const struct slot_metadata *b)
|
||||
{
|
||||
/* Higher priority is better */
|
||||
if (a->priority != b->priority)
|
||||
return b->priority - a->priority;
|
||||
/* Pick the highest priority slot that can be considered bootable. */
|
||||
if (a->priority > b->priority && is_slot_bootable(a))
|
||||
return -1;
|
||||
if (b->priority > a->priority && is_slot_bootable(b))
|
||||
return 1;
|
||||
|
||||
/* Higher successful_boot value is better, in case of same priority */
|
||||
if (a->successful_boot != b->successful_boot)
|
||||
/* The higher priority slot is not bootable, so pick the slot that is. */
|
||||
return b->successful_boot - a->successful_boot;
|
||||
|
||||
/* Higher tries_remaining is better to ensure round-robin */
|
||||
if (a->tries_remaining != b->tries_remaining)
|
||||
return b->tries_remaining - a->tries_remaining;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ab_select_slot(struct blk_desc *dev_desc, struct disk_partition *part_info,
|
||||
|
|
@ -269,6 +277,12 @@ int ab_select_slot(struct blk_desc *dev_desc, struct disk_partition *part_info,
|
|||
}
|
||||
}
|
||||
|
||||
/* Fail to boot normally if there is no bootable slot. */
|
||||
if (normal_boot && !is_slot_bootable(&abc->slot_info[slot])) {
|
||||
log_err("ANDROID: No bootable slot was found.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Note that we only count the boot attempt as a valid try when performing
|
||||
* normal boots to Android. Booting to recovery or fastboot does not count
|
||||
* as a normal boot.
|
||||
|
|
|
|||
Loading…
Reference in New Issue