diff --git a/boot/bootutil/include/bootutil/boot_hooks.h b/boot/bootutil/include/bootutil/boot_hooks.h index 96414e3dfa..aeeba261c6 100644 --- a/boot/bootutil/include/bootutil/boot_hooks.h +++ b/boot/bootutil/include/bootutil/boot_hooks.h @@ -36,6 +36,7 @@ #include "bootutil/bootutil.h" #include "bootutil/fault_injection_hardening.h" +#include #define DO_HOOK_CALL(f, ret_default, ...) \ f(__VA_ARGS__) @@ -284,4 +285,84 @@ int flash_area_get_device_id_hook(const struct flash_area *fa, */ int boot_find_next_slot_hook(struct boot_loader_state *state, uint8_t image, enum boot_slot *active_slot); +/* Swap-status hook family. Uses the same DO_HOOK_CALL / HOOK_CALL_NOP dispatch + * machinery as the other hook families (image-access, boot-go, find-slot, ...): + * when MCUBOOT_SWAP_STATUS_HOOKS is enabled BOOT_STATUS_HOOK_CALL invokes the + * hook and yields its return value; when disabled it evaluates to ret_default + * with no call (and no link dependency on the hook symbol). + * + * Semantics are REPLACE: when the payload is compiled in it fully owns status + * bookkeeping, so a hook, once present, always handles the call -- it never + * defers to the built-in path. Callers use the upstream idiom: + * + * int rc = BOOT_STATUS_HOOK_CALL(f, BOOT_STATUS_HOOK_REGULAR, ...); + * if (rc != BOOT_STATUS_HOOK_REGULAR) { + * return rc; // hook owned it: success or a real error + * } + * ... built-in implementation ... + * + * The amend variant (built-in runs first, hook augments at a defined point) + * passes ret_default = 0, i.e. "nothing to amend" when the family is disabled: + * + * rc = BOOT_STATUS_HOOK_CALL(f, 0, ...); + * + * BOOT_STATUS_HOOK_REGULAR is the family's "not handled" sentinel. It is NOT + * BOOT_HOOK_REGULAR: BOOT_HOOK_REGULAR == BOOT_EFLASH == 1 (bootutil_public.h) + * and these hooks return BOOT_EFLASH on real flash errors, so reusing it would + * misread a flash error as "defer to the built-in status-byte path" and run it + * after a flash fault. INT_MIN is distinct from 0 and every BOOT_E* code, so no + * hook return value can collide with it. */ +#define BOOT_STATUS_HOOK_REGULAR INT_MIN + +#ifdef MCUBOOT_SWAP_STATUS_HOOKS +#define BOOT_STATUS_HOOK_CALL(f, ret_default, ...) \ + DO_HOOK_CALL(f, ret_default, __VA_ARGS__) +#else +#define BOOT_STATUS_HOOK_CALL(f, ret_default, ...) \ + HOOK_CALL_NOP(f, ret_default, __VA_ARGS__) +#endif + +/* boot_hooks.h is a PUBLIC header with consumers that never include the private + * bootutil_priv.h (e.g. boot/zephyr/flash_map_extended.c) -- struct boot_status + * is defined only there, so forward-declare it or the prototypes below create + * prototype-scope tags (warning / incompatible-declaration risk). */ +struct boot_status; + +/** + * Swap-status hook implementations are strong symbols that MUST be linked + * whenever MCUBOOT_SWAP_STATUS_HOOKS is defined. + * + * @return 0 on success, or a BOOT_E* error which the upstream caller returns + * verbatim. BOOT_HOOK_REGULAR has no meaning for this family because + * there is no runtime fallthrough. + */ +int boot_write_status_hook(const struct boot_loader_state *state, + struct boot_status *bs); +int swap_status_init_hook(struct boot_loader_state *state, + const struct flash_area *fap, + const struct boot_status *bs); +int swap_read_status_bytes_hook(const struct flash_area *fap, + struct boot_loader_state *state, + struct boot_status *bs); + +/** + * Commits primary trailer authority before the SCRATCH area is erased. + * + * @return 0 on success, or a BOOT_E* error. The caller must not erase the + * SCRATCH area after an error. + */ +int swap_status_before_scratch_erase_hook(const struct boot_loader_state *state, + const struct flash_area *fap_pri, + const struct flash_area *fap_scratch, + struct boot_status *bs); + +/** + * Amends boot_swap_image after swap_run(): finalizes the swap when the overlay + * tracks progress out-of-band. + * + * @return 0 on success, or a BOOT_E* error which the caller asserts on. + */ +int boot_swap_complete_hook(struct boot_loader_state *state, + struct boot_status *bs); + #endif /*H_BOOTUTIL_HOOKS*/ diff --git a/boot/bootutil/src/bootutil_misc.h b/boot/bootutil/src/bootutil_misc.h index 9c3a2d2f81..a72158b735 100644 --- a/boot/bootutil/src/bootutil_misc.h +++ b/boot/bootutil/src/bootutil_misc.h @@ -2,6 +2,7 @@ * SPDX-License-Identifier: Apache-2.0 * * Copyright (c) 2023 Nordic Semiconductor ASA + * Copyright (c) 2026 Infineon Technologies AG * */ #ifndef H_BOOTUTIL_MISC_ diff --git a/boot/bootutil/src/bootutil_priv.h b/boot/bootutil/src/bootutil_priv.h index 77bce24ec1..7385cf2728 100644 --- a/boot/bootutil/src/bootutil_priv.h +++ b/boot/bootutil/src/bootutil_priv.h @@ -4,6 +4,7 @@ * Copyright (c) 2017-2020 Linaro LTD * Copyright (c) 2017-2019 JUUL Labs * Copyright (c) 2019-2021 Arm Limited + * Copyright (c) 2026 Infineon Technologies AG * * Original license: * @@ -344,6 +345,21 @@ int boot_slots_compatible(struct boot_loader_state *state); uint32_t boot_status_internal_off(const struct boot_status *bs, int elem_sz); int boot_read_image_header(struct boot_loader_state *state, int slot, struct image_header *out_hdr, struct boot_status *bs); +#ifdef MCUBOOT_ENC_IMAGES +/* + * Apply, in place, the exact content transform boot_copy_region applies to one + * chunk being written to `fap_dst` at absolute offset `abs_off` within the + * destination image area (not a device address). The primitive recomputes + * encrypted_src / encrypted_dst / only_copy / source_slot from `state`, + * `fap_src`, and `fap_dst` and selects the governing header itself -- primary + * header when encrypting, secondary header when decrypting. No-op for a + * non-encrypted image or a same-slot (only_copy) move. + */ +void boot_transform_chunk(struct boot_loader_state *state, + const struct flash_area *fap_src, + const struct flash_area *fap_dst, + uint32_t abs_off, uint8_t *buf, uint32_t chunk_sz); +#endif #if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_ENC_IMAGES) int boot_copy_region(struct boot_loader_state *state, const struct flash_area *fap_src, diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 6b0e84a03e..ba91d3cb83 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -5,6 +5,7 @@ * Copyright (c) 2016-2019 JUUL Labs * Copyright (c) 2019-2023 Arm Limited * Copyright (c) 2024-2025 Nordic Semiconductor ASA + * Copyright (c) 2026 Infineon Technologies AG * * Original license: * @@ -413,6 +414,11 @@ boot_status_is_reset(const struct boot_status *bs) int boot_write_status(const struct boot_loader_state *state, struct boot_status *bs) { + int hook_rc = BOOT_STATUS_HOOK_CALL(boot_write_status_hook, + BOOT_STATUS_HOOK_REGULAR, state, bs); + if (hook_rc != BOOT_STATUS_HOOK_REGULAR) { + return hook_rc; + } const struct flash_area *fap; uint32_t off; int rc = 0; @@ -754,40 +760,13 @@ boot_validated_swap_type(struct boot_loader_state *state, #if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) -/** - * Copies the contents of one flash region to another. You must erase the - * destination region prior to calling this function. - * - * @param flash_area_id_src The ID of the source flash area. - * @param flash_area_id_dst The ID of the destination flash area. - * @param off_src The offset within the source flash area to - * copy from. - * @param off_dst The offset within the destination flash area to - * copy to. - * @param sz The number of bytes to copy. - * @param sector_off (Swap using offset with encryption only) the - * sector offset for encryption/decryption - * - * @return 0 on success; nonzero on failure. - */ -int -#if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_ENC_IMAGES) -boot_copy_region(struct boot_loader_state *state, - const struct flash_area *fap_src, - const struct flash_area *fap_dst, - uint32_t off_src, uint32_t off_dst, uint32_t sz, uint32_t sector_off) -#else -boot_copy_region(struct boot_loader_state *state, - const struct flash_area *fap_src, - const struct flash_area *fap_dst, - uint32_t off_src, uint32_t off_dst, uint32_t sz) -#endif -{ - uint32_t bytes_copied; - int chunk_sz; - int rc; #ifdef MCUBOOT_ENC_IMAGES - uint32_t off = off_dst; +void +boot_transform_chunk(struct boot_loader_state *state, + const struct flash_area *fap_src, + const struct flash_area *fap_dst, + uint32_t abs_off, uint8_t *buf, uint32_t chunk_sz) +{ uint32_t tlv_off; size_t blk_off; struct image_header *hdr; @@ -805,13 +784,7 @@ boot_copy_region(struct boot_loader_state *state, /* In case of encryption enabled, we may have to do more work than * just copy bytes */ bool only_copy = false; -#else - (void)state; -#endif - TARGET_STATIC uint8_t buf[BUF_SZ] __attribute__((aligned(4))); - -#ifdef MCUBOOT_ENC_IMAGES encrypted_src = (flash_area_get_id(fap_src) != FLASH_AREA_IMAGE_PRIMARY(image_index)); encrypted_dst = (flash_area_get_id(fap_dst) != FLASH_AREA_IMAGE_PRIMARY(image_index)); @@ -831,8 +804,92 @@ boot_copy_region(struct boot_loader_state *state, */ only_copy = true; } + + /* If only copy, then does not matter if header indicates need for + * encryption/decryption, we just copy data. */ + if (!only_copy && IS_ENCRYPTED(hdr)) { + if (abs_off < hdr->ih_hdr_size) { + /* do not decrypt header */ + if (abs_off + chunk_sz > hdr->ih_hdr_size) { + /* The lower part of the chunk contains header data */ + blk_off = 0; + blk_sz = chunk_sz - (hdr->ih_hdr_size - abs_off); + idx = hdr->ih_hdr_size - abs_off; + } else { + /* The chunk contains exclusively header data */ + blk_sz = 0; /* nothing to decrypt */ + } + } else { + idx = 0; + blk_sz = chunk_sz; + blk_off = (abs_off - hdr->ih_hdr_size) & 0xf; + } + + if (blk_sz > 0) + { + tlv_off = BOOT_TLV_OFF(hdr); + if (abs_off + chunk_sz > tlv_off) { + /* do not decrypt TLVs */ + if (abs_off >= tlv_off) { + blk_sz = 0; + } else { + blk_sz = tlv_off - abs_off - idx; + } + } + if (source_slot == 0) { + boot_enc_encrypt(BOOT_CURR_ENC_SLOT(state, source_slot), + (abs_off + idx) - hdr->ih_hdr_size, blk_sz, + blk_off, &buf[idx]); + } else { + boot_enc_decrypt(BOOT_CURR_ENC_SLOT(state, source_slot), + (abs_off + idx) - hdr->ih_hdr_size, blk_sz, + blk_off, &buf[idx]); + } + } + } +} #endif +/** + * Copies the contents of one flash region to another. You must erase the + * destination region prior to calling this function. + * + * @param flash_area_id_src The ID of the source flash area. + * @param flash_area_id_dst The ID of the destination flash area. + * @param off_src The offset within the source flash area to + * copy from. + * @param off_dst The offset within the destination flash area to + * copy to. + * @param sz The number of bytes to copy. + * @param sector_off (Swap using offset with encryption only) the + * sector offset for encryption/decryption + * + * @return 0 on success; nonzero on failure. + */ +int +#if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_ENC_IMAGES) +boot_copy_region(struct boot_loader_state *state, + const struct flash_area *fap_src, + const struct flash_area *fap_dst, + uint32_t off_src, uint32_t off_dst, uint32_t sz, uint32_t sector_off) +#else +boot_copy_region(struct boot_loader_state *state, + const struct flash_area *fap_src, + const struct flash_area *fap_dst, + uint32_t off_src, uint32_t off_dst, uint32_t sz) +#endif +{ + uint32_t bytes_copied; + int chunk_sz; + int rc; +#ifdef MCUBOOT_ENC_IMAGES + uint32_t off = off_dst; +#else + (void)state; +#endif + + TARGET_STATIC uint8_t buf[BUF_SZ] __attribute__((aligned(4))); + bytes_copied = 0; while (bytes_copied < sz) { if (sz - bytes_copied > sizeof buf) { @@ -847,53 +904,12 @@ boot_copy_region(struct boot_loader_state *state, } #ifdef MCUBOOT_ENC_IMAGES - /* If only copy, then does not matter if header indicates need for - * encryption/decryption, we just copy data. */ - if (!only_copy && IS_ENCRYPTED(hdr)) { #if defined(MCUBOOT_SWAP_USING_OFFSET) - uint32_t abs_off = off - sector_off + bytes_copied; + uint32_t abs_off = off - sector_off + bytes_copied; #else - uint32_t abs_off = off + bytes_copied; -#endif - if (abs_off < hdr->ih_hdr_size) { - /* do not decrypt header */ - if (abs_off + chunk_sz > hdr->ih_hdr_size) { - /* The lower part of the chunk contains header data */ - blk_off = 0; - blk_sz = chunk_sz - (hdr->ih_hdr_size - abs_off); - idx = hdr->ih_hdr_size - abs_off; - } else { - /* The chunk contains exclusively header data */ - blk_sz = 0; /* nothing to decrypt */ - } - } else { - idx = 0; - blk_sz = chunk_sz; - blk_off = (abs_off - hdr->ih_hdr_size) & 0xf; - } - - if (blk_sz > 0) - { - tlv_off = BOOT_TLV_OFF(hdr); - if (abs_off + chunk_sz > tlv_off) { - /* do not decrypt TLVs */ - if (abs_off >= tlv_off) { - blk_sz = 0; - } else { - blk_sz = tlv_off - abs_off - idx; - } - } - if (source_slot == 0) { - boot_enc_encrypt(BOOT_CURR_ENC_SLOT(state, source_slot), - (abs_off + idx) - hdr->ih_hdr_size, blk_sz, - blk_off, &buf[idx]); - } else { - boot_enc_decrypt(BOOT_CURR_ENC_SLOT(state, source_slot), - (abs_off + idx) - hdr->ih_hdr_size, blk_sz, - blk_off, &buf[idx]); - } - } - } + uint32_t abs_off = off + bytes_copied; +#endif + boot_transform_chunk(state, fap_src, fap_dst, abs_off, buf, chunk_sz); #endif rc = flash_area_write(fap_dst, off_dst + bytes_copied, buf, chunk_sz); @@ -1193,6 +1209,15 @@ boot_swap_image(struct boot_loader_state *state, struct boot_status *bs) swap_run(state, bs, copy_size); + /* Post-swap finalization. When the overlay tracks progress out-of-band + * this reconstructs any primary trailer field left uncommitted by an + * interrupted swap and erases a stale scratch trailer. + * BOOT_STATUS_HOOK_CALL evaluates to its ret_default (0, no-op) + * when the status-hook overlay is not compiled in, + * so builds without a swap-state-hook provider are unaffected. */ + rc = BOOT_STATUS_HOOK_CALL(boot_swap_complete_hook, 0, state, bs); + assert(rc == 0); + #ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT extern int boot_status_fails; if (boot_status_fails > 0) { diff --git a/boot/bootutil/src/swap_misc.c b/boot/bootutil/src/swap_misc.c index c00f281a70..2024e9f0e2 100644 --- a/boot/bootutil/src/swap_misc.c +++ b/boot/bootutil/src/swap_misc.c @@ -3,6 +3,7 @@ * * Copyright (c) 2019 JUUL Labs * Copyright (c) 2025 Nordic Semiconductor ASA + * Copyright (c) 2026 Infineon Technologies AG * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +24,7 @@ #include #include #include "bootutil/bootutil.h" +#include "bootutil/boot_hooks.h" #include "bootutil_priv.h" #include "swap_priv.h" #include "bootutil/bootutil_log.h" @@ -104,10 +106,15 @@ swap_scramble_trailer_sectors(const struct boot_loader_state *state, * twice on these devices. */ int -swap_status_init(const struct boot_loader_state *state, +swap_status_init(struct boot_loader_state *state, const struct flash_area *fap, const struct boot_status *bs) { + int hook_rc = BOOT_STATUS_HOOK_CALL(swap_status_init_hook, + BOOT_STATUS_HOOK_REGULAR, state, fap, bs); + if (hook_rc != BOOT_STATUS_HOOK_REGULAR) { + return hook_rc; + } struct boot_swap_state swap_state; uint8_t image_index; int rc; diff --git a/boot/bootutil/src/swap_move.c b/boot/bootutil/src/swap_move.c index c1b21d38ca..f33c86c8ae 100644 --- a/boot/bootutil/src/swap_move.c +++ b/boot/bootutil/src/swap_move.c @@ -22,6 +22,7 @@ #include #include #include "bootutil/bootutil.h" +#include "bootutil/boot_hooks.h" #include "bootutil_priv.h" #include "swap_priv.h" #include "bootutil/bootutil_log.h" @@ -138,6 +139,11 @@ int swap_read_status_bytes(const struct flash_area *fap, struct boot_loader_state *state, struct boot_status *bs) { + int hook_rc = BOOT_STATUS_HOOK_CALL(swap_read_status_bytes_hook, + BOOT_STATUS_HOOK_REGULAR, fap, state, bs); + if (hook_rc != BOOT_STATUS_HOOK_REGULAR) { + return hook_rc; + } uint32_t off; uint8_t status; int max_entries; @@ -447,7 +453,7 @@ boot_swap_sectors(int idx, uint32_t sz, struct boot_loader_state *state, * upgrade (by initializing the secondary slot). */ void -fixup_revert(const struct boot_loader_state *state, struct boot_status *bs, +fixup_revert(struct boot_loader_state *state, struct boot_status *bs, const struct flash_area *fap_sec) { struct boot_swap_state swap_state; diff --git a/boot/bootutil/src/swap_offset.c b/boot/bootutil/src/swap_offset.c index eda68ab91d..28f99e62ac 100644 --- a/boot/bootutil/src/swap_offset.c +++ b/boot/bootutil/src/swap_offset.c @@ -23,6 +23,7 @@ #include #include #include "bootutil/bootutil.h" +#include "bootutil/boot_hooks.h" #include "bootutil_priv.h" #include "swap_priv.h" #include "bootutil/bootutil_log.h" @@ -223,6 +224,11 @@ int boot_read_image_header(struct boot_loader_state *state, int slot, int swap_read_status_bytes(const struct flash_area *fap, struct boot_loader_state *state, struct boot_status *bs) { + int hook_rc = BOOT_STATUS_HOOK_CALL(swap_read_status_bytes_hook, + BOOT_STATUS_HOOK_REGULAR, fap, state, bs); + if (hook_rc != BOOT_STATUS_HOOK_REGULAR) { + return hook_rc; + } uint32_t off; uint8_t status; int max_entries; @@ -546,7 +552,7 @@ static void boot_swap_sectors_revert(int idx, uint32_t sz, struct boot_loader_st * This function handles the issue by making the revert look like a permanent * upgrade (by initializing the secondary slot). */ -void fixup_revert(const struct boot_loader_state *state, struct boot_status *bs, +void fixup_revert(struct boot_loader_state *state, struct boot_status *bs, const struct flash_area *fap_sec) { struct boot_swap_state swap_state; diff --git a/boot/bootutil/src/swap_priv.h b/boot/bootutil/src/swap_priv.h index b564ea99e0..0feb83ffce 100644 --- a/boot/bootutil/src/swap_priv.h +++ b/boot/bootutil/src/swap_priv.h @@ -45,7 +45,7 @@ int swap_scramble_trailer_sectors(const struct boot_loader_state *state, * Initialize the given flash_area with the metadata required to start a new * swap upgrade. */ -int swap_status_init(const struct boot_loader_state *state, +int swap_status_init(struct boot_loader_state *state, const struct flash_area *fap, const struct boot_status *bs); @@ -108,6 +108,30 @@ static inline size_t boot_scratch_area_size(const struct boot_loader_state *stat { return flash_area_get_size(BOOT_SCRATCH_AREA(state)); } + +/** + * Calculates the number of bytes to copy in a single swap step, grouping + * contiguous sectors that fit within the scratch area size. + * + * @param state Current bootloader's state. + * @param last_sector_idx Index of the last sector in the group (inclusive). + * @param out_first_sector_idx Output: index of the first sector (inclusive). + * + * @return The number of bytes comprised by the [first, last] sector range. + */ +uint32_t boot_copy_sz(const struct boot_loader_state *state, + int last_sector_idx, int *out_first_sector_idx); + +/** + * Finds the index of the last sector in the primary slot that needs swapping. + * + * @param state Current bootloader's state. + * @param copy_size Total number of bytes to swap. + * + * @return Index of the last sector that needs swapping. + */ +int find_last_sector_idx(const struct boot_loader_state *state, + uint32_t copy_size); #endif #endif /* defined(MCUBOOT_SWAP_USING_SCRATCH) || defined(MCUBOOT_SWAP_USING_MOVE) || defined(MCUBOOT_SWAP_USING_OFFSET) */ diff --git a/boot/bootutil/src/swap_scratch.c b/boot/bootutil/src/swap_scratch.c index 59b64ad438..56b4871599 100644 --- a/boot/bootutil/src/swap_scratch.c +++ b/boot/bootutil/src/swap_scratch.c @@ -2,6 +2,7 @@ * SPDX-License-Identifier: Apache-2.0 * * Copyright (c) 2019 JUUL Labs + * Copyright (c) 2026 Infineon Technologies AG * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +23,7 @@ #include #include #include "bootutil/bootutil.h" +#include "bootutil/boot_hooks.h" #include "bootutil_priv.h" #include "swap_priv.h" #include "bootutil/bootutil_log.h" @@ -187,6 +189,11 @@ int swap_read_status_bytes(const struct flash_area *fap, struct boot_loader_state *state, struct boot_status *bs) { + int hook_rc = BOOT_STATUS_HOOK_CALL(swap_read_status_bytes_hook, + BOOT_STATUS_HOOK_REGULAR, fap, state, bs); + if (hook_rc != BOOT_STATUS_HOOK_REGULAR) { + return hook_rc; + } uint32_t off; uint8_t status; int max_entries; @@ -551,7 +558,7 @@ swap_status_source(struct boot_loader_state *state) * @return The number of bytes comprised by the * [first-sector, last-sector] range. */ -static uint32_t +uint32_t boot_copy_sz(const struct boot_loader_state *state, int last_sector_idx, int *out_first_sector_idx) { @@ -591,7 +598,7 @@ boot_copy_sz(const struct boot_loader_state *state, int last_sector_idx, * * @return Index of the last sector in the primary slot that needs swapping. */ -static int +int find_last_sector_idx(const struct boot_loader_state *state, uint32_t copy_size) { int last_sector_idx_primary; @@ -746,6 +753,11 @@ boot_swap_sectors(int idx, uint32_t sz, struct boot_loader_state *state, bs->use_scratch = (bs->idx == BOOT_STATUS_IDX_0 && copy_sz != sz); if (bs->state == BOOT_STATUS_STATE_0) { + rc = BOOT_STATUS_HOOK_CALL( + swap_status_before_scratch_erase_hook, 0, + state, fap_primary_slot, fap_scratch, bs); + assert(rc == 0); + BOOT_LOG_DBG("erasing scratch area"); rc = boot_erase_region(fap_scratch, 0, flash_area_get_size(fap_scratch), false); assert(rc == 0); @@ -790,13 +802,11 @@ boot_swap_sectors(int idx, uint32_t sz, struct boot_loader_state *state, if (bs->idx == BOOT_STATUS_IDX_0) { /* Guarantee here that only the primary slot will have the state. - * - * This is necessary even though the current area being swapped contains part of the - * trailer since in case the trailer spreads over multiple sector erasing the [img_off, - * img_off + sz) might not erase the entire trailer. - */ + */ +#ifndef MCUBOOT_SWAP_STATUS_HOOKS rc = swap_scramble_trailer_sectors(state, fap_secondary_slot); assert(rc == 0); +#endif if (bs->use_scratch) { /* If the area being swapped contains the trailer or part of it, ensure the