Skip to content

Commit 22f577d

Browse files
committed
[nrf fromtree] bootutil: Provide boot_set_next function
Commit provides boot_set_next function that allows to set next application slot to boot by flash area object pointer, describing the slot. The function also takes active which is supposed to indicate whether running application is being set for next boot and confirm parameter that allows to confirm the image. Signed-off-by: Dominik Ermel <[email protected]> (cherry picked from commit 918da26) (cherry picked from commit ba0dc61)
1 parent 9da6438 commit 22f577d

File tree

2 files changed

+102
-77
lines changed

2 files changed

+102
-77
lines changed

boot/bootutil/include/bootutil/bootutil_public.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#define H_BOOTUTIL_PUBLIC
4040

4141
#include <inttypes.h>
42+
#include <stdbool.h>
4243
#include <string.h>
4344
#include <flash_map_backend/flash_map_backend.h>
4445
#include <mcuboot_config/mcuboot_config.h>
@@ -266,6 +267,33 @@ int
266267
boot_read_swap_state(const struct flash_area *fa,
267268
struct boot_swap_state *state);
268269

270+
/**
271+
* @brief Set next image application slot by flash area pointer
272+
*
273+
* @param fa pointer to flash_area representing image to set for next boot;
274+
* @param active should be true if @fa points to currently running image
275+
* slot, false otherwise;
276+
* @param confirm confirms image; when @p active is true, this is considered
277+
* true, regardless of passed value.
278+
*
279+
* It is users responsibility to identify whether @p fa provided as parameter
280+
* is currently running/active image and provide proper value to @p active.
281+
* Failing to do so may render device non-upgradeable.
282+
*
283+
* Note that in multi-image setup running/active application is the one
284+
* that is currently being executed by any MCU core, from the pair of
285+
* slots dedicated to that MCU core. As confirming application currently
286+
* running on a given slot should be, preferably, done after functional
287+
* tests prove application to function correctly, it may not be a good idea
288+
* to cross-confirm running images.
289+
* An application should only confirm slots designated to MCU core it is
290+
* running on.
291+
*
292+
* @return 0 on success; non-zero error code on failure.
293+
*/
294+
int
295+
boot_set_next(const struct flash_area *fa, bool active, bool confirm);
296+
269297
#ifdef __cplusplus
270298
}
271299
#endif

boot/bootutil/src/bootutil_public.c

Lines changed: 74 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* Copyright (c) 2017-2019 Linaro LTD
55
* Copyright (c) 2016-2019 JUUL Labs
66
* Copyright (c) 2019-2021 Arm Limited
7-
* Copyright (c) 2020 Nordic Semiconductor ASA
7+
* Copyright (c) 2020-2023 Nordic Semiconductor ASA
88
*
99
* Original license:
1010
*
@@ -458,6 +458,77 @@ boot_swap_type_multi(int image_index)
458458
return BOOT_SWAP_TYPE_NONE;
459459
}
460460

461+
int
462+
boot_set_next(const struct flash_area *fa, bool active, bool confirm)
463+
{
464+
struct boot_swap_state slot_state;
465+
int rc;
466+
467+
if (active) {
468+
confirm = true;
469+
}
470+
471+
rc = boot_read_swap_state(fa, &slot_state);
472+
if (rc != 0) {
473+
return rc;
474+
}
475+
476+
switch (slot_state.magic) {
477+
case BOOT_MAGIC_GOOD:
478+
/* If non-active then swap already scheduled, else confirm needed.*/
479+
480+
if (active && slot_state.image_ok == BOOT_FLAG_UNSET) {
481+
/* Intentionally do not check copy_done flag to be able to
482+
* confirm a padded image which has been programmed using
483+
* a programming interface.
484+
*/
485+
rc = boot_write_image_ok(fa);
486+
}
487+
488+
break;
489+
490+
case BOOT_MAGIC_UNSET:
491+
if (!active) {
492+
rc = boot_write_magic(fa);
493+
494+
if (rc == 0 && confirm) {
495+
rc = boot_write_image_ok(fa);
496+
}
497+
498+
if (rc == 0) {
499+
uint8_t swap_type;
500+
501+
if (confirm) {
502+
swap_type = BOOT_SWAP_TYPE_PERM;
503+
} else {
504+
swap_type = BOOT_SWAP_TYPE_TEST;
505+
}
506+
rc = boot_write_swap_info(fa, swap_type, 0);
507+
}
508+
}
509+
break;
510+
511+
case BOOT_MAGIC_BAD:
512+
if (active) {
513+
rc = BOOT_EBADVECT;
514+
} else {
515+
/* The image slot is corrupt. There is no way to recover, so erase the
516+
* slot to allow future upgrades.
517+
*/
518+
flash_area_erase(fa, 0, flash_area_get_size(fa));
519+
rc = BOOT_EBADIMAGE;
520+
}
521+
break;
522+
523+
default:
524+
/* Something is not OK, this should never happen */
525+
assert(0);
526+
rc = BOOT_EBADIMAGE;
527+
}
528+
529+
return rc;
530+
}
531+
461532
/*
462533
* This function is not used by the bootloader itself, but its required API
463534
* by external tooling like mcumgr.
@@ -486,57 +557,15 @@ int
486557
boot_set_pending_multi(int image_index, int permanent)
487558
{
488559
const struct flash_area *fap;
489-
struct boot_swap_state state_secondary_slot;
490-
uint8_t swap_type;
491560
int rc;
492561

493562
rc = flash_area_open(FLASH_AREA_IMAGE_SECONDARY(image_index), &fap);
494563
if (rc != 0) {
495564
return BOOT_EFLASH;
496565
}
497566

498-
rc = boot_read_swap_state(fap, &state_secondary_slot);
499-
if (rc != 0) {
500-
goto done;
501-
}
502-
503-
switch (state_secondary_slot.magic) {
504-
case BOOT_MAGIC_GOOD:
505-
/* Swap already scheduled. */
506-
break;
507-
508-
case BOOT_MAGIC_UNSET:
509-
rc = boot_write_magic(fap);
510-
511-
if (rc == 0 && permanent) {
512-
rc = boot_write_image_ok(fap);
513-
}
567+
rc = boot_set_next(fap, false, !(permanent == 0));
514568

515-
if (rc == 0) {
516-
if (permanent) {
517-
swap_type = BOOT_SWAP_TYPE_PERM;
518-
} else {
519-
swap_type = BOOT_SWAP_TYPE_TEST;
520-
}
521-
rc = boot_write_swap_info(fap, swap_type, 0);
522-
}
523-
524-
break;
525-
526-
case BOOT_MAGIC_BAD:
527-
/* The image slot is corrupt. There is no way to recover, so erase the
528-
* slot to allow future upgrades.
529-
*/
530-
flash_area_erase(fap, 0, flash_area_get_size(fap));
531-
rc = BOOT_EBADIMAGE;
532-
break;
533-
534-
default:
535-
assert(0);
536-
rc = BOOT_EBADIMAGE;
537-
}
538-
539-
done:
540569
flash_area_close(fap);
541570
return rc;
542571
}
@@ -573,47 +602,15 @@ int
573602
boot_set_confirmed_multi(int image_index)
574603
{
575604
const struct flash_area *fap = NULL;
576-
struct boot_swap_state state_primary_slot;
577605
int rc;
578606

579607
rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(image_index), &fap);
580608
if (rc != 0) {
581609
return BOOT_EFLASH;
582610
}
583611

584-
rc = boot_read_swap_state(fap, &state_primary_slot);
585-
if (rc != 0) {
586-
goto done;
587-
}
588-
589-
switch (state_primary_slot.magic) {
590-
case BOOT_MAGIC_GOOD:
591-
/* Confirm needed; proceed. */
592-
break;
593-
594-
case BOOT_MAGIC_UNSET:
595-
/* Already confirmed. */
596-
goto done;
597-
598-
case BOOT_MAGIC_BAD:
599-
/* Unexpected state. */
600-
rc = BOOT_EBADVECT;
601-
goto done;
602-
}
603-
604-
/* Intentionally do not check copy_done flag
605-
* so can confirm a padded image which was programed using a programing
606-
* interface.
607-
*/
608-
609-
if (state_primary_slot.image_ok != BOOT_FLAG_UNSET) {
610-
/* Already confirmed. */
611-
goto done;
612-
}
613-
614-
rc = boot_write_image_ok(fap);
612+
rc = boot_set_next(fap, true, true);
615613

616-
done:
617614
flash_area_close(fap);
618615
return rc;
619616
}

0 commit comments

Comments
 (0)