From fe21044a6446dedf8696b988aaf8269da7889af9 Mon Sep 17 00:00:00 2001 From: Matt Madison Date: Fri, 12 Mar 2021 05:10:42 -0800 Subject: [PATCH] smd: fix priority handling when marking boot successful When marking a boot in the current slot as successful, make sure that the priorty level of the other slot remains below that of the current slot. Turns out that when the current slot is 1, and the priority of slot 0 gets to 13, the bootloader resets slot 0's priority to 15, and since the two slots have the same priority on the next reboot, we'll switch back to slot 0 again, which is not the desired behavior. So make sure that we force the other slot's priority to one less than the current slot's priority, to remain in the current slot on the next reboot. Signed-off-by: Matt Madison --- smd.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/smd.c b/smd.c index 1fe7c7f..6bd4fdb 100644 --- a/smd.c +++ b/smd.c @@ -113,7 +113,7 @@ smd_init (gpt_context_t *boot_gpt, int bootfd) } /* smd_init */ /* - * smd_init + * smd_new * * Initialize a new, clear SMD context * for redundancy at the specified level. @@ -346,7 +346,8 @@ smd_get_current_slot (void) * * Marks a boot slot as successful. If the slot is * also the current slot, it will be marked as active - * as well (i.e., priority set to 15). + * as well (i.e., priority set to 15), and we ensure + * that the alternate slot has a lower priority. * * Returns: 0 on success, -1 on failure */ @@ -354,7 +355,7 @@ int smd_slot_mark_successful (smd_context_t *ctx, unsigned int which) { int curslot; - struct slot_info_s *s; + struct slot_info_s *s, *other; if (which >= ctx->smd_ods.maxslots) { errno = EINVAL; @@ -366,12 +367,17 @@ smd_slot_mark_successful (smd_context_t *ctx, unsigned int which) return -1; s = &ctx->smd_ods.slot_info[which]; + other = &ctx->smd_ods.slot_info[1-which]; ctx->needs_update = (s->successful != 1 || s->retry_count != 7 || - ((unsigned int) curslot == which && s->priority != 15)); + ((unsigned int) curslot == which && + (s->priority != 15 || other->priority >= s->priority))); s->successful = 1; s->retry_count = 7; - if ((unsigned int) curslot == which) + if ((unsigned int) curslot == which) { s->priority = 15; + if (other->priority >= s->priority) + other->priority = s->priority - 1; + } return 0;