Commit 3016d00c authored by Jamie McCrae's avatar Jamie McCrae Committed by Jamie
Browse files

bootutil: Add active slot number and max app size to shared data



This allows the currently executing slot number to be checked by
the external function, which can be used by XIP images to know
which slot is currently being executed from to allow for correct
uploading/positioning of firmware files, and also provides the
maximum size of an upgrade that can be loaded so that applications
can reject images that are too large.

Signed-off-by: default avatarJamie McCrae <jamie.mccrae@nordicsemi.no>
parent 0540d0fb
Loading
Loading
Loading
Loading
+8 −4
Original line number Diff line number Diff line
@@ -61,11 +61,15 @@ int boot_save_boot_status(uint8_t sw_module,
 *
 * @param[in]  hdr           Pointer to the image header stored in RAM.
 * @param[in]  fap           Pointer to the flash area where image is stored.
 * @param[in]  slot          The currently active slot being booted.
 * @param[in]  max_app_size  The maximum size of an image that can be loaded.
 *
 * @return                    0 on success; nonzero on failure.
 */
int boot_save_shared_data(const struct image_header *hdr,
                          const struct flash_area *fap);
                          const struct flash_area *fap,
                          const uint8_t active_slot,
                          const int max_app_size);

#ifdef __cplusplus
}
+9 −3
Original line number Diff line number Diff line
@@ -129,11 +129,15 @@ boot_read_image_headers(struct boot_loader_state *state, bool require_all,
 */
static int
boot_add_shared_data(struct boot_loader_state *state,
                     uint32_t active_slot)
                     uint8_t active_slot)
{
#if defined(MCUBOOT_MEASURED_BOOT) || defined(MCUBOOT_DATA_SHARING)
    int rc;

#ifdef MCUBOOT_DATA_SHARING
    int max_app_size;
#endif

#ifdef MCUBOOT_MEASURED_BOOT
    rc = boot_save_boot_status(BOOT_CURR_IMG(state),
                                boot_img_hdr(state, active_slot),
@@ -145,8 +149,10 @@ boot_add_shared_data(struct boot_loader_state *state,
#endif /* MCUBOOT_MEASURED_BOOT */

#ifdef MCUBOOT_DATA_SHARING
    max_app_size = app_max_size(state);
    rc = boot_save_shared_data(boot_img_hdr(state, active_slot),
                                BOOT_IMG_AREA(state, active_slot));
                                BOOT_IMG_AREA(state, active_slot),
                                active_slot, max_app_size);
    if (rc != 0) {
        BOOT_LOG_ERR("Failed to add data to shared memory area.");
        return rc;
@@ -3278,7 +3284,7 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp)
            goto out;
        }

        rc = boot_add_shared_data(state, state->slot_usage[BOOT_CURR_IMG(state)].active_slot);
        rc = boot_add_shared_data(state, (uint8_t)state->slot_usage[BOOT_CURR_IMG(state)].active_slot);
        if (rc != 0) {
            FIH_SET(fih_rc, FIH_FAILURE);
            goto out;
+22 −0
Original line number Diff line number Diff line
@@ -542,4 +542,26 @@ swap_run(struct boot_loader_state *state, struct boot_status *bs,
    flash_area_close(fap_sec);
}

int app_max_size(struct boot_loader_state *state)
{
    uint32_t sz = 0;
    uint32_t sector_sz;
    uint32_t trailer_sz;
    uint32_t first_trailer_idx;

    sector_sz = boot_img_sector_size(state, BOOT_PRIMARY_SLOT, 0);
    trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state));
    first_trailer_idx = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT) - 1;

    while (1) {
        sz += sector_sz;
        if  (sz >= trailer_sz) {
            break;
        }
        first_trailer_idx--;
    }

    return (first_trailer_idx * sector_sz);
}

#endif
+5 −0
Original line number Diff line number Diff line
@@ -101,4 +101,9 @@ static inline size_t boot_scratch_area_size(const struct boot_loader_state *stat

#endif /* defined(MCUBOOT_SWAP_USING_SCRATCH) || defined(MCUBOOT_SWAP_USING_MOVE) */

/**
 * Returns the maximum size of an application that can be loaded to a slot.
 */
int app_max_size(struct boot_loader_state *state);

#endif /* H_SWAP_PRIV_ */
+112 −0
Original line number Diff line number Diff line
@@ -743,6 +743,118 @@ swap_run(struct boot_loader_state *state, struct boot_status *bs,
}
#endif /* !MCUBOOT_OVERWRITE_ONLY */

int app_max_size(struct boot_loader_state *state)
{
    size_t num_sectors_primary;
    size_t num_sectors_secondary;
    size_t sz0, sz1;
    size_t primary_slot_sz, secondary_slot_sz;
#ifndef MCUBOOT_OVERWRITE_ONLY
    size_t scratch_sz;
#endif
    size_t i, j;
    int8_t smaller;

    num_sectors_primary = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT);
    num_sectors_secondary = boot_img_num_sectors(state, BOOT_SECONDARY_SLOT);

#ifndef MCUBOOT_OVERWRITE_ONLY
    scratch_sz = boot_scratch_area_size(state);
#endif

    /*
     * The following loop scans all sectors in a linear fashion, assuring that
     * for each possible sector in each slot, it is able to fit in the other
     * slot's sector or sectors. Slot's should be compatible as long as any
     * number of a slot's sectors are able to fit into another, which only
     * excludes cases where sector sizes are not a multiple of each other.
     */
    i = sz0 = primary_slot_sz = 0;
    j = sz1 = secondary_slot_sz = 0;
    smaller = 0;
    while (i < num_sectors_primary || j < num_sectors_secondary) {
        if (sz0 == sz1) {
            sz0 += boot_img_sector_size(state, BOOT_PRIMARY_SLOT, i);
            sz1 += boot_img_sector_size(state, BOOT_SECONDARY_SLOT, j);
            i++;
            j++;
        } else if (sz0 < sz1) {
            sz0 += boot_img_sector_size(state, BOOT_PRIMARY_SLOT, i);
            /* Guarantee that multiple sectors of the secondary slot
             * fit into the primary slot.
             */
            if (smaller == 2) {
                BOOT_LOG_WRN("Cannot upgrade: slots have non-compatible sectors");
                return 0;
            }
            smaller = 1;
            i++;
        } else {
            sz1 += boot_img_sector_size(state, BOOT_SECONDARY_SLOT, j);
            /* Guarantee that multiple sectors of the primary slot
             * fit into the secondary slot.
             */
            if (smaller == 1) {
                BOOT_LOG_WRN("Cannot upgrade: slots have non-compatible sectors");
                return 0;
            }
            smaller = 2;
            j++;
        }
#ifndef MCUBOOT_OVERWRITE_ONLY
        if (sz0 == sz1) {
            primary_slot_sz += sz0;
            secondary_slot_sz += sz1;
            /* Scratch has to fit each swap operation to the size of the larger
             * sector among the primary slot and the secondary slot.
             */
            if (sz0 > scratch_sz || sz1 > scratch_sz) {
                BOOT_LOG_WRN("Cannot upgrade: not all sectors fit inside scratch");
                return 0;
            }
            smaller = sz0 = sz1 = 0;
        }
#endif
    }

#ifdef MCUBOOT_OVERWRITE_ONLY
    return (sz1 < sz0 ? sz1 : sz0);
#else
    return (secondary_slot_sz < primary_slot_sz ? secondary_slot_sz : primary_slot_sz);
#endif
}
#else
int app_max_size(struct boot_loader_state *state)
{
    const struct flash_area *fap;
    int fa_id;
    int rc;
    uint32_t active_slot;
    int primary_sz, secondary_sz;

    active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot;

    fa_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), active_slot);
    rc = flash_area_open(fa_id, &fap);
    assert(rc == 0);
    primary_sz = flash_area_get_size(fap);
    flash_area_close(fap);

    if (active_slot == BOOT_PRIMARY_SLOT) {
        active_slot = BOOT_SECONDARY_SLOT;
    } else {
        active_slot = BOOT_PRIMARY_SLOT;
    }

    fa_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), active_slot);
    rc = flash_area_open(fa_id, &fap);
    assert(rc == 0);
    secondary_sz = flash_area_get_size(fap);
    flash_area_close(fap);

    return (secondary_sz < primary_sz ? secondary_sz : primary_sz);
}

#endif /* !MCUBOOT_DIRECT_XIP && !MCUBOOT_RAM_LOAD */

#endif /* !MCUBOOT_SWAP_USING_MOVE */