Skip to content

Commit 2a2b562

Browse files
de-nordicnordicjm
authored andcommitted
bootutil: Add support for devices without erase and reduced erases
The commit adds two MCUboot configuration options: - MCUBOOT_SUPPORT_DEV_WITHOUT_ERASE - MCUBOOT_SUPPORT_DEV_WITH_ERASE - MCUBOOT_MINIMAL_SCRAMBLE The first one should be enabled to support devices that do not require erase. When such devices are used in system then MCUboot will avoid erasing such device, which is not needed by hardware, and will just write data to it. This allows to both improve device lifetime and reduce time of operations like swap. The second option is just bringing a configuration option for already existing support for deviceses with erase. The third option allows to reduce amount of removed data. When enabled, MCUboot will remove enough of data, depending on the purpose of the removal, to just fulfill the purpose; for example if removal of data is done to make image unrecognizable for MCUboot, with this option, it will only remove header. Signed-off-by: Dominik Ermel <dominik.ermel@nordicsemi.no>
1 parent 1ead4a6 commit 2a2b562

File tree

11 files changed

+401
-52
lines changed

11 files changed

+401
-52
lines changed

boot/boot_serial/src/boot_serial.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -856,7 +856,7 @@ static off_t erase_range(const struct flash_area *fap, off_t start, off_t end)
856856
BOOT_LOG_DBG("Erasing range 0x%jx:0x%jx", (intmax_t)start,
857857
(intmax_t)(start + size - 1));
858858

859-
rc = flash_area_erase(fap, start, size);
859+
rc = boot_erase_region(fap, start, size);
860860
if (rc != 0) {
861861
BOOT_LOG_ERR("Error %d while erasing range", rc);
862862
return -EINVAL;
@@ -1000,7 +1000,7 @@ bs_upload(char *buf, int len)
10001000
/* Non-progressive erase erases entire image slot when first chunk of
10011001
* an image is received.
10021002
*/
1003-
rc = flash_area_erase(fap, 0, area_size);
1003+
rc = boot_erase_region(fap, 0, area_size);
10041004
if (rc) {
10051005
goto out_invalid_data;
10061006
}

boot/boot_serial/src/boot_serial_encryption.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ decrypt_region_inplace(struct boot_loader_state *state,
187187
(off + bytes_copied + idx) - hdr->ih_hdr_size, blk_sz,
188188
blk_off, &buf[idx]);
189189
}
190-
rc = flash_area_erase(fap, off + bytes_copied, chunk_sz);
190+
rc = boot_erase_region(fap, off + bytes_copied, chunk_sz);
191191
if (rc != 0) {
192192
return BOOT_EFLASH;
193193
}

boot/bootutil/src/bootutil_misc.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,74 @@ boot_trailer_sz(uint32_t min_write_sz)
135135
return boot_status_sz(min_write_sz) + boot_trailer_info_sz();
136136
}
137137

138+
int boot_trailer_scramble_offset(const struct flash_area *fa, size_t alignment,
139+
size_t *off)
140+
{
141+
int ret = 0;
142+
143+
/* Not allowed to enforce alignment smaller than device allows */
144+
if (alignment < flash_area_align(fa)) {
145+
alignment = flash_area_align(fa);
146+
}
147+
148+
if (device_requires_erase(fa)) {
149+
/* For device requiring erase align to erase unit */
150+
struct flash_sector sector;
151+
152+
ret = flash_area_get_sector(fa, flash_area_get_size(fa) - boot_trailer_sz(alignment),
153+
&sector);
154+
if (ret < 0) {
155+
return ret;
156+
}
157+
158+
*off = flash_sector_get_off(&sector);
159+
} else {
160+
/* For device not requiring erase align to write block */
161+
*off = flash_area_get_size(fa) - ALIGN_DOWN(boot_trailer_sz(alignment), alignment);
162+
}
163+
164+
return ret;
165+
}
166+
167+
int boot_header_scramble_off_sz(const struct flash_area *fa, int slot, size_t *off,
168+
size_t *size)
169+
{
170+
int ret = 0;
171+
const size_t write_block = flash_area_align(fa);
172+
size_t loff = 0;
173+
struct flash_sector sector;
174+
175+
(void)slot;
176+
#if defined(MCUBOOT_SWAP_USING_OFFSET)
177+
/* In case of swap offset, header of secondary slot image is positioned
178+
* in second sector of slot.
179+
*/
180+
if (slot == BOOT_SECONDARY_SLOT) {
181+
ret = flash_area_get_sector(fa, 0, &sector);
182+
if (ret < 0) {
183+
return ret;
184+
}
185+
loff = flash_sector_get_off(&sector);
186+
}
187+
#endif
188+
189+
if (device_requires_erase(fa)) {
190+
/* For device requiring erase align to erase unit */
191+
ret = flash_area_get_sector(fa, loff, &sector);
192+
if (ret < 0) {
193+
return ret;
194+
}
195+
196+
*size = flash_sector_get_size(&sector);
197+
} else {
198+
/* For device not requiring erase align to write block */
199+
*size = ALIGN_UP(sizeof(((struct image_header *)0)->ih_magic), write_block);
200+
}
201+
*off = loff;
202+
203+
return ret;
204+
}
205+
138206
#if MCUBOOT_SWAP_USING_SCRATCH
139207
/*
140208
* Similar to `boot_trailer_sz` but this function returns the space used to

boot/bootutil/src/bootutil_priv.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,16 @@ const struct flash_area *boot_find_status(const struct boot_loader_state *state,
302302
int boot_magic_compatible_check(uint8_t tbl_val, uint8_t val);
303303
uint32_t boot_status_sz(uint32_t min_write_sz);
304304
uint32_t boot_trailer_sz(uint32_t min_write_sz);
305+
/* Get offset of trailer aligned to either device erase unit or alignment
306+
* depending on whether device has erase or not.
307+
*/
308+
int boot_trailer_scramble_offset(const struct flash_area *fa, size_t alignment,
309+
size_t *off);
310+
/* Get size of header aligned to device erase unit or write block,
311+
* depending on whether device has erase or not.
312+
*/
313+
int boot_header_scramble_off_sz(const struct flash_area *fa, int slot, size_t *off,
314+
size_t *size);
305315
int boot_status_entries(int image_index, const struct flash_area *fap);
306316
uint32_t boot_status_off(const struct flash_area *fap);
307317
int boot_read_swap_state(const struct flash_area *fap,
@@ -333,7 +343,19 @@ int boot_copy_region(struct boot_loader_state *state,
333343
const struct flash_area *fap_dst,
334344
uint32_t off_src, uint32_t off_dst, uint32_t sz);
335345
#endif
346+
/* Prepare for write device that requires erase prior to write. This will
347+
* do nothing on devices without erase requirement.
348+
*/
336349
int boot_erase_region(const struct flash_area *fap, uint32_t off, uint32_t sz);
350+
/* Similar to boot_erase_region but will always remove data */
351+
int boot_scramble_region(const struct flash_area *fap, uint32_t off, uint32_t sz);
352+
/* Similar to boot_scramble_region but works backwards */
353+
int boot_scramble_region_backwards(const struct flash_area *fap, uint32_t off, uint32_t sz);
354+
/* Makes slot unbootable, either by scrambling header magic, header sector
355+
* or entire slot, depending on settings.
356+
* Note: slot is passed here becuase at this point there is no function
357+
* matching flash_area object to slot */
358+
int boot_scramble_slot(const struct flash_area *fap, int slot);
337359
bool boot_status_is_reset(const struct boot_status *bs);
338360

339361
#ifdef MCUBOOT_ENC_IMAGES
@@ -529,6 +551,20 @@ uint32_t bootutil_max_image_size(struct boot_loader_state *state, const struct f
529551
int boot_read_image_size(struct boot_loader_state *state, int slot,
530552
uint32_t *size);
531553

554+
/* Helper macro to avoid compile errors with systems that do not
555+
* provide function to check device type.
556+
* Note: it used to be inline, but somehow compiler would not
557+
* optimize out branches that were impossible when this evaluated to
558+
* just "true".
559+
*/
560+
#if defined(MCUBOOT_SUPPORT_DEV_WITHOUT_ERASE) && defined(MCUBOOT_SUPPORT_DEV_WITH_ERASE)
561+
#define device_requires_erase(fa) (flash_area_erase_required(fa))
562+
#elif defined(MCUBOOT_SUPPORT_DEV_WITHOUT_ERASE)
563+
#define device_requires_erase(fa) (false)
564+
#else
565+
#define device_requires_erase(fa) (true)
566+
#endif
567+
532568
#ifdef __cplusplus
533569
}
534570
#endif

0 commit comments

Comments
 (0)