Skip to content

Commit 4649072

Browse files
utzigd3zd3z
authored andcommitted
Adds total size of a swap to the trailer
When starting a swap upgrade, the total size of data to be swapped is calculated only at the beginning and saved to the trailer. This avoids having to use complicated heuristics to find the total swap size, which might depend on data that was already moved. When resuming a swap, the size is found in the trailer and used. Also includes some small comment fixes and refactors. Signed-off-by: Fabio Utzig <utzig@apache.org> Signed-off-by: David Brown <david.brown@linaro.org>
1 parent 2eebf11 commit 4649072

File tree

3 files changed

+155
-59
lines changed

3 files changed

+155
-59
lines changed

boot/bootutil/src/bootutil_misc.c

Lines changed: 105 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,15 +120,15 @@ boot_slots_trailer_sz(uint8_t min_write_sz)
120120
{
121121
return /* state for all sectors */
122122
BOOT_STATUS_MAX_ENTRIES * BOOT_STATUS_STATE_COUNT * min_write_sz +
123-
BOOT_MAX_ALIGN * 2 /* copy_done + image_ok */ +
123+
BOOT_MAX_ALIGN * 3 /* copy_done + image_ok + swap_size */ +
124124
BOOT_MAGIC_SZ;
125125
}
126126

127127
static uint32_t
128128
boot_scratch_trailer_sz(uint8_t min_write_sz)
129129
{
130130
return BOOT_STATUS_STATE_COUNT * min_write_sz + /* state for one sector */
131-
BOOT_MAX_ALIGN + /* image_ok */
131+
BOOT_MAX_ALIGN * 2 + /* image_ok + swap_size */
132132
BOOT_MAGIC_SZ;
133133
}
134134

@@ -186,6 +186,20 @@ boot_image_ok_off(const struct flash_area *fap)
186186
return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN;
187187
}
188188

189+
static uint32_t
190+
boot_swap_size_off(const struct flash_area *fap)
191+
{
192+
/*
193+
* The "swap_size" field if located just before the trailer.
194+
* The scratch slot doesn't store "copy_done"...
195+
*/
196+
if (fap->fa_id == FLASH_AREA_IMAGE_SCRATCH) {
197+
return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 2;
198+
}
199+
200+
return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 3;
201+
}
202+
189203
int
190204
boot_read_swap_state(const struct flash_area *fap,
191205
struct boot_swap_state *state)
@@ -203,14 +217,14 @@ boot_read_swap_state(const struct flash_area *fap,
203217

204218
if (fap->fa_id != FLASH_AREA_IMAGE_SCRATCH) {
205219
off = boot_copy_done_off(fap);
206-
rc = flash_area_read(fap, off, &state->copy_done, 1);
220+
rc = flash_area_read(fap, off, &state->copy_done, sizeof state->copy_done);
207221
if (rc != 0) {
208222
return BOOT_EFLASH;
209223
}
210224
}
211225

212226
off = boot_image_ok_off(fap);
213-
rc = flash_area_read(fap, off, &state->image_ok, 1);
227+
rc = flash_area_read(fap, off, &state->image_ok, sizeof state->image_ok);
214228
if (rc != 0) {
215229
return BOOT_EFLASH;
216230
}
@@ -245,6 +259,68 @@ boot_read_swap_state_by_id(int flash_area_id, struct boot_swap_state *state)
245259
return rc;
246260
}
247261

262+
int
263+
boot_read_swap_size(uint32_t *swap_size)
264+
{
265+
uint32_t magic[BOOT_MAGIC_SZ];
266+
uint32_t off;
267+
const struct flash_area *fap;
268+
int rc;
269+
270+
/*
271+
* In the middle a swap, tries to locate the saved swap size. Looks
272+
* for a valid magic, first on Slot 0, then on scratch. Both "slots"
273+
* can end up being temporary storage for a swap and it is assumed
274+
* that if magic is valid then swap size is too, because magic is
275+
* always written in the last step.
276+
*/
277+
278+
rc = flash_area_open(FLASH_AREA_IMAGE_0, &fap);
279+
if (rc != 0) {
280+
return BOOT_EFLASH;
281+
}
282+
283+
off = boot_magic_off(fap);
284+
rc = flash_area_read(fap, off, magic, BOOT_MAGIC_SZ);
285+
if (rc != 0) {
286+
rc = BOOT_EFLASH;
287+
goto out;
288+
}
289+
290+
if (memcmp(magic, boot_img_magic, BOOT_MAGIC_SZ) != 0) {
291+
/*
292+
* If Slot 0 's magic is not valid, try scratch...
293+
*/
294+
295+
flash_area_close(fap);
296+
297+
rc = flash_area_open(FLASH_AREA_IMAGE_SCRATCH, &fap);
298+
if (rc != 0) {
299+
return BOOT_EFLASH;
300+
}
301+
302+
off = boot_magic_off(fap);
303+
rc = flash_area_read(fap, off, magic, BOOT_MAGIC_SZ);
304+
if (rc != 0) {
305+
rc = BOOT_EFLASH;
306+
goto out;
307+
}
308+
309+
assert(memcmp(magic, boot_img_magic, BOOT_MAGIC_SZ) == 0);
310+
}
311+
312+
off = boot_swap_size_off(fap);
313+
rc = flash_area_read(fap, off, swap_size, sizeof *swap_size);
314+
if (rc != 0) {
315+
rc = BOOT_EFLASH;
316+
}
317+
318+
out:
319+
flash_area_close(fap);
320+
return rc;
321+
}
322+
323+
248324
int
249325
boot_write_magic(const struct flash_area *fap)
250326
{
@@ -305,6 +381,31 @@ boot_write_image_ok(const struct flash_area *fap)
305381
return boot_write_flag(BOOT_FLAG_IMAGE_OK, fap);
306382
}
307383

384+
int
385+
boot_write_swap_size(const struct flash_area *fap, uint32_t swap_size)
386+
{
387+
uint32_t off;
388+
int rc;
389+
uint8_t buf[BOOT_MAX_ALIGN];
390+
uint8_t align;
391+
392+
off = boot_swap_size_off(fap);
393+
align = hal_flash_align(fap->fa_device_id);
394+
assert(align <= BOOT_MAX_ALIGN);
395+
if (align < sizeof swap_size) {
396+
align = sizeof swap_size;
397+
}
398+
memset(buf, 0xFF, BOOT_MAX_ALIGN);
399+
memcpy(buf, (uint8_t *)&swap_size, sizeof swap_size);
400+
401+
rc = flash_area_write(fap, off, buf, align);
402+
if (rc != 0) {
403+
return BOOT_EFLASH;
404+
}
405+
406+
return 0;
407+
}
408+
308409
int
309410
boot_swap_type(void)
310411
{

boot/bootutil/src/bootutil_priv.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ struct boot_status {
4747
uint32_t idx; /* Which area we're operating on */
4848
uint8_t state; /* Which part of the swapping process are we at */
4949
uint8_t use_scratch; /* Are status bytes ever written to scratch? */
50+
uint32_t swap_size; /* Total size of swapped image */
5051
};
5152

5253
#define BOOT_MAGIC_GOOD 1
@@ -59,15 +60,19 @@ struct boot_status {
5960
* 0 1 2 3
6061
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
6162
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
62-
* ~ MAGIC (16 octets) ~
63-
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6463
* ~ ~
6564
* ~ Swap status (variable, aligned) ~
6665
* ~ ~
6766
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
68-
* | Copy done | 0xff padding (up to min-write-sz - 1) ~
67+
* | Swap size |
68+
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
69+
* ~ 0xff padding (MAX ALIGN - 4) ~
6970
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
70-
* | Image OK | 0xff padding (up to min-write-sz - 1) ~
71+
* | Copy done | 0xff padding (MAX ALIGN - 1) ~
72+
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
73+
* | Image OK | 0xff padding (MAX ALIGN - 1) ~
74+
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
75+
* ~ MAGIC (16 octets) ~
7176
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
7277
*/
7378

@@ -140,6 +145,8 @@ int boot_write_status(struct boot_status *bs);
140145
int boot_schedule_test_swap(void);
141146
int boot_write_copy_done(const struct flash_area *fap);
142147
int boot_write_image_ok(const struct flash_area *fap);
148+
int boot_write_swap_size(const struct flash_area *fap, uint32_t swap_size);
149+
int boot_read_swap_size(uint32_t *swap_size);
143150

144151
/*
145152
* Accessors for the contents of struct boot_loader_state.

boot/bootutil/src/loader.c

Lines changed: 39 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -206,28 +206,6 @@ boot_previous_swap_type(void)
206206
return BOOT_SWAP_TYPE_FAIL;
207207
}
208208

209-
#ifndef MCUBOOT_OVERWRITE_ONLY
210-
static int
211-
boot_read_header_from_scratch(struct image_header *out_hdr)
212-
{
213-
const struct flash_area *fap;
214-
int rc;
215-
216-
rc = flash_area_open(FLASH_AREA_IMAGE_SCRATCH, &fap);
217-
if (rc != 0) {
218-
return BOOT_EFLASH;
219-
}
220-
221-
rc = flash_area_read(fap, 0, out_hdr, sizeof *out_hdr);
222-
if (rc != 0) {
223-
rc = BOOT_EFLASH;
224-
}
225-
226-
flash_area_close(fap);
227-
return rc;
228-
}
229-
#endif /* !MCUBOOT_OVERWRITE_ONLY */
230-
231209
/*
232210
* Compute the total size of the given image. Includes the size of
233211
* the TLVs.
@@ -477,7 +455,10 @@ boot_read_status(struct boot_status *bs)
477455
return BOOT_EFLASH;
478456
}
479457

480-
return boot_read_status_bytes(fap, bs);
458+
rc = boot_read_status_bytes(fap, bs);
459+
460+
flash_area_close(fap);
461+
return rc;
481462
}
482463

483464
/**
@@ -797,7 +778,7 @@ boot_copy_sector(int flash_area_id_src, int flash_area_id_dst,
797778
}
798779

799780
static inline int
800-
boot_status_init_by_id(int flash_area_id)
781+
boot_status_init_by_id(int flash_area_id, const struct boot_status *bs)
801782
{
802783
const struct flash_area *fap;
803784
struct boot_swap_state swap_state;
@@ -814,6 +795,9 @@ boot_status_init_by_id(int flash_area_id)
814795
assert(rc == 0);
815796
}
816797

798+
rc = boot_write_swap_size(fap, bs->swap_size);
799+
assert(rc == 0);
800+
817801
rc = boot_write_magic(fap);
818802
assert(rc == 0);
819803

@@ -907,7 +891,7 @@ boot_swap_sectors(int idx, uint32_t sz, struct boot_status *bs)
907891

908892
if (bs->idx == 0) {
909893
if (bs->use_scratch) {
910-
boot_status_init_by_id(FLASH_AREA_IMAGE_SCRATCH);
894+
boot_status_init_by_id(FLASH_AREA_IMAGE_SCRATCH, bs);
911895
} else {
912896
/* Prepare the status area... here it is known that the
913897
* last sector is not being used by the image data so it's
@@ -916,7 +900,7 @@ boot_swap_sectors(int idx, uint32_t sz, struct boot_status *bs)
916900
rc = boot_erase_last_sector_by_id(FLASH_AREA_IMAGE_0);
917901
assert(rc == 0);
918902

919-
boot_status_init_by_id(FLASH_AREA_IMAGE_0);
903+
boot_status_init_by_id(FLASH_AREA_IMAGE_0, bs);
920904
}
921905
}
922906

@@ -982,6 +966,9 @@ boot_swap_sectors(int idx, uint32_t sz, struct boot_status *bs)
982966
assert(rc == 0);
983967
}
984968

969+
rc = boot_write_swap_size(fap, bs->swap_size);
970+
assert(rc == 0);
971+
985972
rc = boot_write_magic(fap);
986973
assert(rc == 0);
987974

@@ -1057,42 +1044,43 @@ boot_copy_image(struct boot_status *bs)
10571044
struct image_header *hdr;
10581045
uint32_t size;
10591046
uint32_t copy_size;
1060-
struct image_header tmp_hdr;
10611047
int rc;
10621048

10631049
/* FIXME: just do this if asked by user? */
10641050

10651051
size = copy_size = 0;
10661052

1067-
hdr = boot_img_hdr(&boot_data, 0);
1068-
if (hdr->ih_magic == IMAGE_MAGIC) {
1069-
rc = boot_read_image_size(0, hdr, &copy_size);
1070-
assert(rc == 0);
1071-
}
1072-
1073-
hdr = boot_img_hdr(&boot_data, 1);
1074-
if (hdr->ih_magic == IMAGE_MAGIC) {
1075-
rc = boot_read_image_size(1, hdr, &size);
1076-
assert(rc == 0);
1077-
}
1078-
1079-
if (!size || !copy_size || size == copy_size) {
1080-
rc = boot_read_header_from_scratch(&tmp_hdr);
1081-
assert(rc == 0);
1053+
if (bs->idx == 0 && bs->state == 0) {
1054+
/*
1055+
* No swap ever happened, so need to find the largest image which
1056+
* will be used to determine the amount of sectors to swap.
1057+
*/
1058+
hdr = boot_img_hdr(&boot_data, 0);
1059+
if (hdr->ih_magic == IMAGE_MAGIC) {
1060+
rc = boot_read_image_size(0, hdr, &copy_size);
1061+
assert(rc == 0);
1062+
}
10821063

1083-
hdr = &tmp_hdr;
1064+
hdr = boot_img_hdr(&boot_data, 1);
10841065
if (hdr->ih_magic == IMAGE_MAGIC) {
1085-
if (!size) {
1086-
rc = boot_read_image_size(2, hdr, &size);
1087-
} else {
1088-
rc = boot_read_image_size(2, hdr, &size);
1089-
}
1066+
rc = boot_read_image_size(1, hdr, &size);
10901067
assert(rc == 0);
10911068
}
1092-
}
10931069

1094-
if (size > copy_size) {
1095-
copy_size = size;
1070+
if (size > copy_size) {
1071+
copy_size = size;
1072+
}
1073+
1074+
bs->swap_size = copy_size;
1075+
} else {
1076+
/*
1077+
* If a swap was under way, the swap_size should already be present
1078+
* in the trailer...
1079+
*/
1080+
rc = boot_read_swap_size(&bs->swap_size);
1081+
assert(rc == 0);
1082+
1083+
copy_size = bs->swap_size;
10961084
}
10971085

10981086
size = 0;

0 commit comments

Comments
 (0)