Skip to content

Commit e5b8952

Browse files
committed
boot: boot_serial: Add support for swap using offset mode
Adds support for serial recovery of images when MCUboot is set to swap using offset mode Signed-off-by: Jamie McCrae <jamie.mccrae@nordicsemi.no>
1 parent fecf7e8 commit e5b8952

File tree

8 files changed

+261
-16
lines changed

8 files changed

+261
-16
lines changed

boot/boot_serial/include/boot_serial/boot_serial_encryption.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,18 @@
1515
* @param[in] hdr boot image header pointer
1616
* @param[in] buf buffer which is used for validating data
1717
* @param[in] buf_size size of input buffer
18+
* @param[in] start_off start offset inside of image (swap using offset only)
1819
*
1920
* @return FIH_SUCCESS on success, error code otherwise
2021
*/
2122
fih_ret
2223
boot_image_validate_encrypted(const struct flash_area *fa_p,
2324
struct image_header *hdr, uint8_t *buf,
24-
uint16_t buf_size);
25+
uint16_t buf_size
26+
#ifdef MCUBOOT_SWAP_USING_OFFSET
27+
, uint32_t start_off
28+
#endif
29+
);
2530

2631
/**
2732
* Handle an encrypted firmware in the main flash.

boot/boot_serial/src/boot_serial.c

Lines changed: 156 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,9 @@ BOOT_LOG_MODULE_DECLARE(mcuboot);
154154
#define IMAGES_ITER(x)
155155
#endif
156156

157+
#define SWAP_USING_OFFSET_SECTOR_UPDATE_BEGIN 1
158+
#define BOOT_DIRECT_UPLOAD_SECONDARY_SLOT_ID_REMAINDER 0
159+
157160
static char in_buf[MCUBOOT_SERIAL_MAX_RECEIVE_SIZE + 1];
158161
static char dec_buf[MCUBOOT_SERIAL_MAX_RECEIVE_SIZE + 1];
159162
const struct boot_uart_funcs *boot_uf;
@@ -165,9 +168,14 @@ static char bs_obuf[BOOT_SERIAL_OUT_MAX];
165168
static void boot_serial_output(void);
166169

167170
#ifdef MCUBOOT_SERIAL_IMG_GRP_HASH
171+
#ifdef MCUBOOT_SWAP_USING_OFFSET
172+
static int boot_serial_get_hash(const struct image_header *hdr,
173+
const struct flash_area *fap, uint8_t *hash, uint32_t start_off);
174+
#else
168175
static int boot_serial_get_hash(const struct image_header *hdr,
169176
const struct flash_area *fap, uint8_t *hash);
170177
#endif
178+
#endif
171179

172180
static zcbor_state_t cbor_state[2];
173181

@@ -288,6 +296,7 @@ bs_list(char *buf, int len)
288296

289297
for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
290298
FIH_DECLARE(fih_rc, FIH_FAILURE);
299+
int rc;
291300
uint8_t tmpbuf[64];
292301

293302
#ifdef MCUBOOT_SERIAL_IMG_GRP_IMAGE_STATE
@@ -297,16 +306,41 @@ bs_list(char *buf, int len)
297306
bool permanent = false;
298307
#endif
299308

309+
#ifdef MCUBOOT_SWAP_USING_OFFSET
310+
uint32_t start_off = 0;
311+
#endif
312+
300313
area_id = flash_area_id_from_multi_image_slot(image_index, slot);
301314
if (flash_area_open(area_id, &fap)) {
302315
continue;
303316
}
304317

305-
int rc = BOOT_HOOK_CALL(boot_read_image_header_hook,
306-
BOOT_HOOK_REGULAR, image_index, slot, &hdr);
318+
#ifdef MCUBOOT_SWAP_USING_OFFSET
319+
if (slot == BOOT_SECONDARY_SLOT && swap_status != BOOT_SWAP_TYPE_REVERT) {
320+
uint32_t num_sectors = SWAP_USING_OFFSET_SECTOR_UPDATE_BEGIN;
321+
struct flash_sector sector_data;
322+
323+
rc = flash_area_sectors(fap, &num_sectors, &sector_data);
324+
325+
if ((rc != 0 && rc != -ENOMEM) ||
326+
num_sectors != SWAP_USING_OFFSET_SECTOR_UPDATE_BEGIN) {
327+
flash_area_close(fap);
328+
continue;
329+
}
330+
331+
start_off = sector_data.fs_size;
332+
}
333+
#endif
334+
335+
rc = BOOT_HOOK_CALL(boot_read_image_header_hook,
336+
BOOT_HOOK_REGULAR, image_index, slot, &hdr);
307337
if (rc == BOOT_HOOK_REGULAR)
308338
{
339+
#ifdef MCUBOOT_SWAP_USING_OFFSET
340+
flash_area_read(fap, start_off, &hdr, sizeof(hdr));
341+
#else
309342
flash_area_read(fap, 0, &hdr, sizeof(hdr));
343+
#endif
310344
}
311345

312346
if (hdr.ih_magic == IMAGE_MAGIC)
@@ -319,8 +353,13 @@ bs_list(char *buf, int len)
319353
#if defined(MCUBOOT_ENC_IMAGES)
320354
#if !defined(MCUBOOT_SINGLE_APPLICATION_SLOT)
321355
if (IS_ENCRYPTED(&hdr) && MUST_DECRYPT(fap, image_index, &hdr)) {
356+
#ifdef MCUBOOT_SWAP_USING_OFFSET
357+
FIH_CALL(boot_image_validate_encrypted, fih_rc, fap,
358+
&hdr, tmpbuf, sizeof(tmpbuf), start_off);
359+
#else
322360
FIH_CALL(boot_image_validate_encrypted, fih_rc, fap,
323361
&hdr, tmpbuf, sizeof(tmpbuf));
362+
#endif
324363
} else {
325364
#endif
326365
if (IS_ENCRYPTED(&hdr)) {
@@ -333,8 +372,13 @@ bs_list(char *buf, int len)
333372
}
334373
#endif
335374

375+
#ifdef MCUBOOT_SWAP_USING_OFFSET
376+
FIH_CALL(bootutil_img_validate, fih_rc, NULL, &hdr,
377+
fap, tmpbuf, sizeof(tmpbuf), NULL, 0, NULL, start_off);
378+
#else
336379
FIH_CALL(bootutil_img_validate, fih_rc, NULL, &hdr,
337380
fap, tmpbuf, sizeof(tmpbuf), NULL, 0, NULL);
381+
#endif
338382
#if defined(MCUBOOT_ENC_IMAGES) && !defined(MCUBOOT_SINGLE_APPLICATION_SLOT)
339383
}
340384
#endif
@@ -348,7 +392,11 @@ bs_list(char *buf, int len)
348392

349393
#ifdef MCUBOOT_SERIAL_IMG_GRP_HASH
350394
/* Retrieve hash of image for identification */
395+
#ifdef MCUBOOT_SWAP_USING_OFFSET
396+
rc = boot_serial_get_hash(&hdr, fap, hash, start_off);
397+
#else
351398
rc = boot_serial_get_hash(&hdr, fap, hash);
399+
#endif
352400
#endif
353401

354402
flash_area_close(fap);
@@ -494,17 +542,39 @@ bs_set(char *buf, int len)
494542
const struct flash_area *fap;
495543
uint8_t tmpbuf[64];
496544

545+
#ifdef MCUBOOT_SWAP_USING_OFFSET
546+
uint32_t num_sectors = SWAP_USING_OFFSET_SECTOR_UPDATE_BEGIN;
547+
struct flash_sector sector_data;
548+
uint32_t start_off = 0;
549+
#endif
550+
497551
area_id = flash_area_id_from_multi_image_slot(image_index, 1);
498552
if (flash_area_open(area_id, &fap)) {
499553
BOOT_LOG_ERR("Failed to open flash area ID %d", area_id);
500554
continue;
501555
}
502556

557+
#ifdef MCUBOOT_SWAP_USING_OFFSET
558+
rc = flash_area_sectors(fap, &num_sectors, &sector_data);
559+
560+
if ((rc != 0 && rc != -ENOMEM) ||
561+
num_sectors != SWAP_USING_OFFSET_SECTOR_UPDATE_BEGIN) {
562+
flash_area_close(fap);
563+
continue;
564+
}
565+
566+
start_off = sector_data.fs_size;
567+
#endif
568+
503569
rc = BOOT_HOOK_CALL(boot_read_image_header_hook,
504570
BOOT_HOOK_REGULAR, image_index, 1, &hdr);
505571
if (rc == BOOT_HOOK_REGULAR)
506572
{
573+
#ifdef MCUBOOT_SWAP_USING_OFFSET
574+
flash_area_read(fap, start_off, &hdr, sizeof(hdr));
575+
#else
507576
flash_area_read(fap, 0, &hdr, sizeof(hdr));
577+
#endif
508578
}
509579

510580
if (hdr.ih_magic == IMAGE_MAGIC)
@@ -518,12 +588,22 @@ bs_set(char *buf, int len)
518588
{
519589
#ifdef MCUBOOT_ENC_IMAGES
520590
if (IS_ENCRYPTED(&hdr)) {
591+
#ifdef MCUBOOT_SWAP_USING_OFFSET
592+
FIH_CALL(boot_image_validate_encrypted, fih_rc, fap,
593+
&hdr, tmpbuf, sizeof(tmpbuf), start_off);
594+
#else
521595
FIH_CALL(boot_image_validate_encrypted, fih_rc, fap,
522596
&hdr, tmpbuf, sizeof(tmpbuf));
597+
#endif
523598
} else {
524599
#endif
600+
#ifdef MCUBOOT_SWAP_USING_OFFSET
601+
FIH_CALL(bootutil_img_validate, fih_rc, NULL, &hdr,
602+
fap, tmpbuf, sizeof(tmpbuf), NULL, 0, NULL, start_off);
603+
#else
525604
FIH_CALL(bootutil_img_validate, fih_rc, NULL, &hdr,
526605
fap, tmpbuf, sizeof(tmpbuf), NULL, 0, NULL);
606+
#endif
527607
#ifdef MCUBOOT_ENC_IMAGES
528608
}
529609
#endif
@@ -534,8 +614,14 @@ bs_set(char *buf, int len)
534614
}
535615
}
536616

617+
#ifdef MCUBOOT_SERIAL_IMG_GRP_HASH
537618
/* Retrieve hash of image for identification */
619+
#ifdef MCUBOOT_SWAP_USING_OFFSET
620+
rc = boot_serial_get_hash(&hdr, fap, hash, start_off);
621+
#else
538622
rc = boot_serial_get_hash(&hdr, fap, hash);
623+
#endif
624+
#endif
539625
flash_area_close(fap);
540626

541627
if (rc == 0 && memcmp(hash, img_hash.value, sizeof(hash)) == 0) {
@@ -811,6 +897,9 @@ bs_upload(char *buf, int len)
811897
*/
812898
static struct flash_sector status_sector;
813899
#endif
900+
#ifdef MCUBOOT_SWAP_USING_OFFSET
901+
static uint32_t start_off = 0;
902+
#endif
814903

815904
zcbor_state_t zsd[4];
816905
zcbor_new_state(zsd, sizeof(zsd) / sizeof(zcbor_state_t), (uint8_t *)buf, len, 1, NULL, 0);
@@ -874,6 +963,11 @@ bs_upload(char *buf, int len)
874963
*/
875964
const size_t area_size = flash_area_get_size(fap);
876965

966+
#ifdef MCUBOOT_SWAP_USING_OFFSET
967+
uint32_t num_sectors = SWAP_USING_OFFSET_SECTOR_UPDATE_BEGIN;
968+
struct flash_sector sector_data;
969+
#endif
970+
877971
curr_off = 0;
878972
#ifdef MCUBOOT_ERASE_PROGRESSIVELY
879973
/* Get trailer sector information; this is done early because inability to get
@@ -915,6 +1009,35 @@ bs_upload(char *buf, int len)
9151009
#endif
9161010

9171011
img_size = img_size_tmp;
1012+
1013+
#ifdef MCUBOOT_SWAP_USING_OFFSET
1014+
#ifdef MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD
1015+
if (img_num > 0 &&
1016+
(img_num % BOOT_NUM_SLOTS) == BOOT_DIRECT_UPLOAD_SECONDARY_SLOT_ID_REMAINDER) {
1017+
rc = flash_area_sectors(fap, &num_sectors, &sector_data);
1018+
1019+
if ((rc != 0 && rc != -ENOMEM) ||
1020+
num_sectors != SWAP_USING_OFFSET_SECTOR_UPDATE_BEGIN) {
1021+
rc = MGMT_ERR_ENOENT;
1022+
goto out;
1023+
}
1024+
1025+
start_off = sector_data.fs_size;
1026+
} else {
1027+
start_off = 0;
1028+
}
1029+
#else
1030+
rc = flash_area_sectors(fap, &num_sectors, &sector_data);
1031+
1032+
if ((rc != 0 && rc != -ENOMEM) ||
1033+
num_sectors != SWAP_USING_OFFSET_SECTOR_UPDATE_BEGIN) {
1034+
rc = MGMT_ERR_ENOENT;
1035+
goto out;
1036+
}
1037+
1038+
start_off = sector_data.fs_size;
1039+
#endif
1040+
#endif
9181041
} else if (img_chunk_off != curr_off) {
9191042
/* If received chunk offset does not match expected one jump, pretend
9201043
* success and jump to out; out will respond to client with success
@@ -931,8 +1054,13 @@ bs_upload(char *buf, int len)
9311054
/* Progressive erase will erase enough flash, aligned to sector size,
9321055
* as needed for the current chunk to be written.
9331056
*/
1057+
#ifdef MCUBOOT_SWAP_USING_OFFSET
1058+
not_yet_erased = erase_range(fap, not_yet_erased,
1059+
curr_off + img_chunk_len - 1 + start_off);
1060+
#else
9341061
not_yet_erased = erase_range(fap, not_yet_erased,
9351062
curr_off + img_chunk_len - 1);
1063+
#endif
9361064

9371065
if (not_yet_erased < 0) {
9381066
rc = MGMT_ERR_EINVAL;
@@ -969,7 +1097,11 @@ bs_upload(char *buf, int len)
9691097
memset(wbs_aligned, flash_area_erased_val(fap), sizeof(wbs_aligned));
9701098
memcpy(wbs_aligned, img_chunk, write_size);
9711099

1100+
#ifdef MCUBOOT_SWAP_USING_OFFSET
1101+
rc = flash_area_write(fap, curr_off + start_off, wbs_aligned, write_size);
1102+
#else
9721103
rc = flash_area_write(fap, curr_off, wbs_aligned, write_size);
1104+
#endif
9731105

9741106
if (rc != 0) {
9751107
goto out;
@@ -980,10 +1112,18 @@ bs_upload(char *buf, int len)
9801112
img_chunk_len -= write_size;
9811113
}
9821114
} else {
1115+
#ifdef MCUBOOT_SWAP_USING_OFFSET
1116+
rc = flash_area_write(fap, curr_off + start_off, img_chunk, img_chunk_len);
1117+
#else
9831118
rc = flash_area_write(fap, curr_off, img_chunk, img_chunk_len);
1119+
#endif
9841120
}
1121+
#else
1122+
#ifdef MCUBOOT_SWAP_USING_OFFSET
1123+
rc = flash_area_write(fap, curr_off + start_off, img_chunk, img_chunk_len);
9851124
#else
9861125
rc = flash_area_write(fap, curr_off, img_chunk, img_chunk_len);
1126+
#endif
9871127
#endif
9881128

9891129
if (rc == 0 && rem_bytes) {
@@ -996,8 +1136,13 @@ bs_upload(char *buf, int len)
9961136
memset(wbs_aligned, flash_area_erased_val(fap), sizeof(wbs_aligned));
9971137
memcpy(wbs_aligned, img_chunk + img_chunk_len, rem_bytes);
9981138

1139+
#ifdef MCUBOOT_SWAP_USING_OFFSET
1140+
rc = flash_area_write(fap, curr_off + img_chunk_len + start_off, wbs_aligned,
1141+
flash_area_align(fap));
1142+
#else
9991143
rc = flash_area_write(fap, curr_off + img_chunk_len, wbs_aligned,
10001144
flash_area_align(fap));
1145+
#endif
10011146
}
10021147

10031148
if (rc == 0) {
@@ -1452,8 +1597,13 @@ boot_serial_check_start(const struct boot_uart_funcs *f, int timeout_in_ms)
14521597

14531598
#ifdef MCUBOOT_SERIAL_IMG_GRP_HASH
14541599
/* Function to find the hash of an image, returns 0 on success. */
1600+
#ifdef MCUBOOT_SWAP_USING_OFFSET
1601+
static int boot_serial_get_hash(const struct image_header *hdr,
1602+
const struct flash_area *fap, uint8_t *hash, uint32_t start_off)
1603+
#else
14551604
static int boot_serial_get_hash(const struct image_header *hdr,
14561605
const struct flash_area *fap, uint8_t *hash)
1606+
#endif
14571607
{
14581608
struct image_tlv_iter it;
14591609
uint32_t offset;
@@ -1464,6 +1614,10 @@ static int boot_serial_get_hash(const struct image_header *hdr,
14641614
/* Manifest data is concatenated to the end of the image.
14651615
* It is encoded in TLV format.
14661616
*/
1617+
#if defined(MCUBOOT_SWAP_USING_OFFSET)
1618+
it.start_off = start_off;
1619+
#endif
1620+
14671621
rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, false);
14681622
if (rc) {
14691623
return -1;

0 commit comments

Comments
 (0)