mgmt/MCUmgr/grp/img: Add img_mgmt_get_next_boot_slot

The commit adds functions:
 img_mgmt_get_next_boot_slot
 img_mgmt_get_opposite_slot

to simplify obtaining information on next boot slot.

Signed-off-by: Dominik Ermel <dominik.ermel@nordicsemi.no>
This commit is contained in:
Dominik Ermel 2023-06-02 14:06:36 +00:00 committed by Carles Cufí
commit 81e98d2487
3 changed files with 123 additions and 1 deletions

View file

@ -86,6 +86,55 @@ int img_mgmt_write_image_data(unsigned int offset, const void *data, unsigned in
*/ */
int img_mgmt_swap_type(int slot); int img_mgmt_swap_type(int slot);
/**
* @brief Returns image that the given slot belongs to.
*
* @param slot A slot number.
*
* @return 0 based image number.
*/
int img_mgmt_slot_to_image(int slot);
/**
* @brief Get slot number of alternate (inactive) image pair
*
* @param slot A slot number.
*
* @return Number of other slot in pair
*/
static inline int img_mgmt_get_opposite_slot(int slot)
{
__ASSERT(slot >= 0 && slot < (CONFIG_MCUMGR_GRP_IMG_UPDATABLE_IMAGE_NUMBER << 1),
"Impossible slot number");
return (slot ^ 1);
}
enum img_mgmt_next_boot_type {
/** The normal boot to active or non-active slot */
NEXT_BOOT_TYPE_NORMAL = 0,
/** The test/non-permanent boot to non-active slot */
NEXT_BOOT_TYPE_TEST = 1,
/** Next boot will be revert to already confirmed slot; this
* type of next boot means that active slot is not confirmed
* yet as it has been marked for test in previous boot.
*/
NEXT_BOOT_TYPE_REVERT = 2
};
/**
* @brief Get next boot slot number for a given image.
*
* @param image An image number.
* @param type Type of next boot
*
* @return Number of slot, from pair of slots assigned to image, that will
* boot on next reset. User needs to compare this slot against active slot
* to check whether application image will change for the next boot.
* @return -1 in case when next boot slot can not be established.
*/
int img_mgmt_get_next_boot_slot(int image, enum img_mgmt_next_boot_type *type);
/** /**
* Collects information about the specified image slot. * Collects information about the specified image slot.
* *

View file

@ -9,6 +9,7 @@
#include <zephyr/toolchain.h> #include <zephyr/toolchain.h>
#include <string.h> #include <string.h>
#include <zephyr/logging/log.h> #include <zephyr/logging/log.h>
#include <zephyr/dfu/mcuboot.h>
#include <zcbor_common.h> #include <zcbor_common.h>
#include <zcbor_decode.h> #include <zcbor_decode.h>
@ -133,6 +134,78 @@ img_mgmt_state_flags(int query_slot)
} }
#endif #endif
#ifndef CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP
int img_mgmt_get_next_boot_slot(int image, enum img_mgmt_next_boot_type *type)
{
const int active_slot = img_mgmt_active_slot(image);
const int state = mcuboot_swap_type_multi(image);
/* All cases except BOOT_SWAP_TYPE_NONE return opposite slot */
int slot = img_mgmt_get_opposite_slot(active_slot);
enum img_mgmt_next_boot_type lt = NEXT_BOOT_TYPE_NORMAL;
switch (state) {
case BOOT_SWAP_TYPE_NONE:
/* Booting to the same slot, keeping type to NEXT_BOOT_TYPE_NORMAL */
slot = active_slot;
break;
case BOOT_SWAP_TYPE_PERM:
/* For BOOT_SWAP_TYPE_PERM reported type will be NEXT_BOOT_TYPE_NORMAL,
* and only difference between this and BOOT_SWAP_TYPE_NONE is that
* the later boots to the application in currently active slot while the former
* to the application in the opposite to active slot.
* Normal here means that it is ordinary boot and slot has not been marked
* for revert or pending for test, and will change on reset.
*/
break;
case BOOT_SWAP_TYPE_REVERT:
/* Application is in test mode and has not yet been confirmed,
* which means that on the next boot the application will revert to
* the copy from reported slot.
*/
lt = NEXT_BOOT_TYPE_REVERT;
break;
case BOOT_SWAP_TYPE_TEST:
/* Reported next boot slot is set for one boot only and app needs to
* confirm itself or it will be reverted.
*/
lt = NEXT_BOOT_TYPE_TEST;
break;
default:
/* Should never, ever happen */
LOG_DBG("Unexpected swap state %d", state);
return -1;
}
LOG_DBG("(%d, *) => slot = %d, type = %d", image, slot, lt);
if (type != NULL) {
*type = lt;
}
return slot;
}
#else
int img_mgmt_get_next_boot_slot(int image, enum img_mgmt_next_boot_type *type)
{
struct image_version aver;
struct image_version over;
int active_slot = img_mgmt_active_slot(image);
int other_slot = img_mgmt_get_opposite_slot(active_slot);
if (type != NULL) {
*type = NEXT_BOOT_TYPE_NORMAL;
}
int rcs = img_mgmt_read_info(other_slot, &over, NULL, NULL);
int rca = img_mgmt_read_info(active_slot, &aver, NULL, NULL);
if (rcs == 0 && rca == 0 && img_mgmt_vercmp(&aver, &over) < 0) {
return other_slot;
}
return active_slot;
}
#endif
/** /**
* Indicates whether any image slot is pending (i.e., whether a test swap will * Indicates whether any image slot is pending (i.e., whether a test swap will
* happen on the next reboot. * happen on the next reboot.

View file

@ -51,7 +51,7 @@ BUILD_ASSERT(CONFIG_MCUMGR_GRP_IMG_UPDATABLE_IMAGE_NUMBER == 1 ||
#define ADD_SLOT_3_CONDITION 0 #define ADD_SLOT_3_CONDITION 0
#endif #endif
static int int
img_mgmt_slot_to_image(int slot) img_mgmt_slot_to_image(int slot)
{ {
switch (slot) { switch (slot) {