Skip to content

Commit c5bc7b9

Browse files
committed
bootutil: Support for logical sectors
The commit adds support for logical/software sectors. User can select size of sector by which image will be moved using configuration identifier MCUBOOT_LOGICAL_SECTOR_SIZE. Non-0 value set to MCUBOOT_LOGICAL_SECTOR_SIZE will be used as sector size for image swap algorithms. Note that the value provided here should be aligned to hardware erase page of device(s) used and may not be smaller than of such a device. There is also additional option provided, MCUBOOT_VERIFY_LOGICAL_SECTORS, that allows to enable validation of selected logical sector against true layout of a device. Signed-off-by: Dominik Ermel <[email protected]>
1 parent 8a07053 commit c5bc7b9

File tree

3 files changed

+201
-2
lines changed

3 files changed

+201
-2
lines changed

boot/bootutil/src/bootutil_misc.c

Lines changed: 164 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,15 @@ BOOT_LOG_MODULE_DECLARE(mcuboot);
5656
/* Currently only used by imgmgr */
5757
int boot_current_slot;
5858

59+
#if !defined(MCUBOOT_LOGICAL_SECTOR_SIZE) || MCUBOOT_LOGICAL_SECTOR_SIZE == 0
5960
#if (!defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)) || \
6061
defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO)
6162
/* Used for holding static buffers in multiple functions to work around issues
6263
* in older versions of gcc (e.g. 4.8.4)
6364
*/
6465
static struct boot_sector_buffer sector_buffers;
6566
#endif
67+
#endif /* !defined(MCUBOOT_LOGICAL_SECTOR_SIZE) || MCUBOOT_LOGICAL_SECTOR_SIZE == 0 */
6668

6769
/**
6870
* @brief Determine if the data at two memory addresses is equal
@@ -625,6 +627,7 @@ boot_erase_region(const struct flash_area *fa, uint32_t off, uint32_t size, bool
625627

626628
#if (!defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)) || \
627629
defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO)
630+
#if !defined(MCUBOOT_LOGICAL_SECTOR_SIZE) || MCUBOOT_LOGICAL_SECTOR_SIZE == 0
628631
int
629632
boot_initialize_area(struct boot_loader_state *state, int flash_area)
630633
{
@@ -665,6 +668,139 @@ boot_initialize_area(struct boot_loader_state *state, int flash_area)
665668
return 0;
666669
}
667670

671+
#else /* defined(MCUBOOT_LOGICAL_SECTOR_SIZE) && MCUBOOT_LOGICAL_SECTOR_SIZE != 0 */
672+
#if defined(MCUBOOT_VERIFY_LOGICAL_SECTORS)
673+
/* Validation can only run once all flash areas are open and pointers to
674+
* flash area objects are stored in state.
675+
*/
676+
static int
677+
boot_verify_logical_sectors(int faid, const struct flash_area *fa)
678+
{
679+
uint32_t slot_size;
680+
uint32_t slot_off;
681+
uint32_t sect_off = 0;
682+
int rc;
683+
int final_rc = 0;
684+
bool device_with_erase;
685+
uint32_t wbs;
686+
687+
assert(fa != NULL);
688+
assert(faid != 0);
689+
690+
slot_off = (uint32_t)flash_area_get_off(fa);
691+
slot_size = (uint32_t)flash_area_get_size(fa);
692+
693+
wbs = flash_area_align(fa);
694+
695+
device_with_erase = device_requires_erase(fa);
696+
/* Go till all verifications are complete or we face issue that does not allow
697+
* to precede with further tests.
698+
*/
699+
BOOT_LOG_INF("boot_verify_logical_sectors: verify flash area %p", fa);
700+
BOOT_LOG_INF("boot_verify_logical_sectors: MCUBOOT_LOGICAL_SECTOR_SIZE == 0x%x",
701+
MCUBOOT_LOGICAL_SECTOR_SIZE);
702+
BOOT_LOG_INF("boot_verify_logical_sectors: slot offset == 0x%x", slot_off);
703+
if (slot_size != 0) {
704+
BOOT_LOG_INF("boot_verify_logical_sectors: slot size == 0x%x", slot_size);
705+
} else {
706+
BOOT_LOG_ERR("boot_verify_logical_sectors: 0 size slot");
707+
return BOOT_EFLASH;
708+
}
709+
BOOT_LOG_INF("boot_verify_logical_sectors: write block size %u", wbs);
710+
BOOT_LOG_INF("boot_verify_logical_sectors: device with%s erase",
711+
device_with_erase ? "" : "out");
712+
713+
/* We are expecting slot size to be multiple of logical sector size.
714+
* Note though that we do not check alignment of the slot to logical sector.
715+
* as it does not matter, only alignment of slot to a real erase page
716+
* matters.
717+
*/
718+
if (slot_size % MCUBOOT_LOGICAL_SECTOR_SIZE) {
719+
BOOT_LOG_ERR("boot_verify_logical_sectors: area size not aligned");
720+
final_rc = BOOT_EFLASH;
721+
}
722+
723+
BOOT_LOG_INF("boot_verify_logical_sectors: max %d logical sectors",
724+
slot_size / MCUBOOT_LOGICAL_SECTOR_SIZE);
725+
726+
if (device_with_erase) {
727+
size_t total_scanned = 0;
728+
729+
/* Check all logical sectors pages against erase pages of a device */
730+
while (total_scanned < slot_size) {
731+
struct flash_sector fas;
732+
733+
MCUBOOT_WATCHDOG_FEED();
734+
735+
BOOT_LOG_INF("boot_verify_logical_sectors: page 0x%x:0x%x ", slot_off, sect_off);
736+
rc = flash_area_get_sector(fa, sect_off, &fas);
737+
if (rc < 0) {
738+
BOOT_LOG_ERR("boot_verify_logical_sectors: query err %d", rc);
739+
final_rc = BOOT_EFLASH;
740+
continue;
741+
}
742+
743+
/* Jumping by logical sector size should align us with real erase page
744+
* each time.
745+
*/
746+
if (sect_off != flash_sector_get_off(&fas)) {
747+
BOOT_LOG_ERR("boot_verify_logical_sectors: misaligned offset (0x%x)",
748+
(uint32_t)flash_sector_get_off(&fas));
749+
final_rc = BOOT_EFLASH;
750+
}
751+
752+
/* Jumping by logical sector size */
753+
sect_off += MCUBOOT_LOGICAL_SECTOR_SIZE;
754+
total_scanned += MCUBOOT_LOGICAL_SECTOR_SIZE;
755+
}
756+
} else {
757+
/* Devices with no-explicit erase require alignment to write block size */
758+
759+
if (MCUBOOT_LOGICAL_SECTOR_SIZE % wbs) {
760+
BOOT_LOG_ERR("boot_verify_logical_sectors: sector size not aligned to write block");
761+
final_rc = BOOT_EFLASH;
762+
}
763+
764+
if (slot_off % wbs) {
765+
BOOT_LOG_ERR("boot_verify_logical_sectors: slot not aligned to write block");
766+
final_rc = BOOT_EFLASH;
767+
}
768+
}
769+
770+
BOOT_LOG_INF("boot_verify_logical_sectors: completed (%d)", final_rc);
771+
772+
return final_rc;
773+
}
774+
#endif /* MCUBOOT_LOGICAL_SECTOR_VALIDATION */
775+
776+
static int
777+
boot_initialize_area(struct boot_loader_state *state, int flash_area)
778+
{
779+
size_t area_size;
780+
uint32_t *out_num_sectors;
781+
782+
if (flash_area == FLASH_AREA_IMAGE_PRIMARY(BOOT_CURR_IMG(state))) {
783+
area_size = flash_area_get_size(BOOT_IMG_AREA(state, BOOT_SLOT_PRIMARY));
784+
out_num_sectors = &BOOT_IMG(state, BOOT_SLOT_PRIMARY).num_sectors;
785+
} else if (flash_area == FLASH_AREA_IMAGE_SECONDARY(BOOT_CURR_IMG(state))) {
786+
area_size = flash_area_get_size(BOOT_IMG_AREA(state, BOOT_SLOT_SECONDARY));
787+
out_num_sectors = &BOOT_IMG(state, BOOT_SLOT_SECONDARY).num_sectors;
788+
#if MCUBOOT_SWAP_USING_SCRATCH
789+
} else if (flash_area == FLASH_AREA_IMAGE_SCRATCH) {
790+
area_size = flash_area_get_size(state->scratch.area);
791+
out_num_sectors = &state->scratch.num_sectors;
792+
#endif
793+
} else {
794+
return BOOT_EFLASH;
795+
}
796+
797+
*out_num_sectors = area_size / MCUBOOT_LOGICAL_SECTOR_SIZE;
798+
799+
return 0;
800+
}
801+
802+
#endif /* defined(MCUBOOT_LOGICAL_SECTOR_SIZE) && MCUBOOT_LOGICAL_SECTOR_SIZE != 0 */
803+
668804
static uint32_t
669805
boot_write_sz(struct boot_loader_state *state)
670806
{
@@ -694,12 +830,13 @@ boot_read_sectors(struct boot_loader_state *state, struct boot_sector_buffer *se
694830
uint8_t image_index;
695831
int rc;
696832

833+
image_index = BOOT_CURR_IMG(state);
834+
835+
#if !defined(MCUBOOT_LOGICAL_SECTOR_SIZE) || MCUBOOT_LOGICAL_SECTOR_SIZE == 0
697836
if (sectors == NULL) {
698837
sectors = &sector_buffers;
699838
}
700839

701-
image_index = BOOT_CURR_IMG(state);
702-
703840
BOOT_IMG(state, BOOT_SLOT_PRIMARY).sectors =
704841
sectors->primary[image_index];
705842
#if BOOT_NUM_SLOTS > 1
@@ -709,6 +846,9 @@ boot_read_sectors(struct boot_loader_state *state, struct boot_sector_buffer *se
709846
state->scratch.sectors = sectors->scratch;
710847
#endif
711848
#endif
849+
#else
850+
(void)sectors;
851+
#endif /* !defined(MCUBOOT_LOGICAL_SECTOR_SIZE) || MCUBOOT_LOGICAL_SECTOR_SIZE == 0 */
712852

713853
rc = boot_initialize_area(state, FLASH_AREA_IMAGE_PRIMARY(image_index));
714854
if (rc != 0) {
@@ -732,6 +872,28 @@ boot_read_sectors(struct boot_loader_state *state, struct boot_sector_buffer *se
732872

733873
BOOT_WRITE_SZ(state) = boot_write_sz(state);
734874

875+
#if defined(MCUBOOT_VERIFY_LOGICAL_SECTORS)
876+
BOOT_LOG_INF("boot_read_sectors: verify image %d slots", image_index);
877+
BOOT_LOG_INF("boot_read_sectors: BOOT_SLOT_PRIMARY");
878+
if (boot_verify_logical_sectors(FLASH_AREA_IMAGE_PRIMARY(image_index),
879+
BOOT_IMG_AREA(state, BOOT_SLOT_PRIMARY)) != 0) {
880+
rc = BOOT_EFLASH;
881+
}
882+
883+
BOOT_LOG_INF("boot_read_sectors: BOOT_SLOT_SECONDARY");
884+
if (boot_verify_logical_sectors(FLASH_AREA_IMAGE_SECONDARY(image_index),
885+
BOOT_IMG_AREA(state, BOOT_SLOT_SECONDARY)) != 0) {
886+
rc = BOOT_EFLASH_SEC;
887+
}
888+
889+
#if MCUBOOT_SWAP_USING_SCRATCH
890+
BOOT_LOG_INF("boot_read_sectors: SCRATCH");
891+
if (boot_verify_logical_sectors(FLASH_AREA_IMAGE_SCRATCH, state->scratch.area) != 0) {
892+
rc = BOOT_EFLASH;
893+
}
894+
#endif /* MCUBOOT_SWAP_USING_SCRATCH */
895+
#endif /* defined(MCUBOOT_LOGICAL_SECTOR_VALIDATION) */
896+
735897
return 0;
736898
}
737899
#endif

boot/bootutil/src/bootutil_priv.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,14 +240,18 @@ struct boot_loader_state {
240240
struct {
241241
struct image_header hdr;
242242
const struct flash_area *area;
243+
#if !defined(MCUBOOT_LOGICAL_SECTOR_SIZE) || MCUBOOT_LOGICAL_SECTOR_SIZE == 0
243244
boot_sector_t *sectors;
245+
#endif
244246
uint32_t num_sectors;
245247
} imgs[BOOT_IMAGE_NUMBER][BOOT_NUM_SLOTS];
246248

247249
#if MCUBOOT_SWAP_USING_SCRATCH
248250
struct {
249251
const struct flash_area *area;
252+
#if !defined(MCUBOOT_LOGICAL_SECTOR_SIZE) || MCUBOOT_LOGICAL_SECTOR_SIZE == 0
250253
boot_sector_t *sectors;
254+
#endif
251255
uint32_t num_sectors;
252256
} scratch;
253257
#endif
@@ -510,6 +514,7 @@ boot_img_slot_off(struct boot_loader_state *state, size_t slot)
510514
return flash_area_get_off(BOOT_IMG_AREA(state, slot));
511515
}
512516

517+
#if !defined(MCUBOOT_LOGICAL_SECTOR_SIZE) || MCUBOOT_LOGICAL_SECTOR_SIZE == 0
513518
#ifndef MCUBOOT_USE_FLASH_AREA_GET_SECTORS
514519

515520
static inline size_t
@@ -549,6 +554,32 @@ boot_img_sector_off(const struct boot_loader_state *state, size_t slot,
549554
}
550555

551556
#endif /* !defined(MCUBOOT_USE_FLASH_AREA_GET_SECTORS) */
557+
#else
558+
static inline size_t
559+
boot_img_sector_size(const struct boot_loader_state *state,
560+
size_t slot, size_t sector)
561+
{
562+
(void)state;
563+
(void)slot;
564+
(void)sector;
565+
566+
return MCUBOOT_LOGICAL_SECTOR_SIZE;
567+
}
568+
569+
/*
570+
* Offset of the sector from the beginning of the image, NOT the flash
571+
* device.
572+
*/
573+
static inline uint32_t
574+
boot_img_sector_off(const struct boot_loader_state *state, size_t slot,
575+
size_t sector)
576+
{
577+
(void)state;
578+
(void)slot;
579+
580+
return MCUBOOT_LOGICAL_SECTOR_SIZE * sector;
581+
}
582+
#endif
552583

553584
#ifdef MCUBOOT_RAM_LOAD
554585
# ifdef __BOOTSIM__

boot/bootutil/src/loader.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,7 @@ boot_image_check(struct boot_loader_state *state, struct image_header *hdr,
702702
}
703703

704704
#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)
705+
#if !defined(MCUBOOT_LOGICAL_SECTOR_SIZE) || MCUBOOT_LOGICAL_SECTOR_SIZE == 0
705706
static fih_ret
706707
split_image_check(struct image_header *app_hdr,
707708
const struct flash_area *app_fap,
@@ -732,6 +733,7 @@ split_image_check(struct image_header *app_hdr,
732733
out:
733734
FIH_RET(fih_rc);
734735
}
736+
#endif /* !defined(MCUBOOT_LOGICAL_SECTOR_SIZE) || MCUBOOT_LOGICAL_SECTOR_SIZE == 0 */
735737
#endif /* !MCUBOOT_DIRECT_XIP && !MCUBOOT_RAM_LOAD */
736738

737739
/*
@@ -2210,10 +2212,12 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp)
22102212

22112213
BOOT_LOG_DBG("context_boot_go");
22122214

2215+
#if !defined(MCUBOOT_LOGICAL_SECTOR_SIZE) || MCUBOOT_LOGICAL_SECTOR_SIZE == 0
22132216
#if defined(__BOOTSIM__)
22142217
struct boot_sector_buffer sector_buf;
22152218
sectors = &sector_buf;
22162219
#endif
2220+
#endif /* !defined(MCUBOOT_LOGICAL_SECTOR_SIZE) || MCUBOOT_LOGICAL_SECTOR_SIZE == 0 */
22172221

22182222
has_upgrade = false;
22192223

@@ -2473,6 +2477,7 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp)
24732477
FIH_RET(fih_rc);
24742478
}
24752479

2480+
#if !defined(MCUBOOT_LOGICAL_SECTOR_SIZE) || MCUBOOT_LOGICAL_SECTOR_SIZE == 0
24762481
fih_ret
24772482
split_go(int loader_slot, int split_slot, void **entry)
24782483
{
@@ -2538,6 +2543,7 @@ split_go(int loader_slot, int split_slot, void **entry)
25382543

25392544
FIH_RET(fih_rc);
25402545
}
2546+
#endif /* !defined(MCUBOOT_LOGICAL_SECTOR_SIZE) || MCUBOOT_LOGICAL_SECTOR_SIZE == 0 */
25412547

25422548
#else /* MCUBOOT_DIRECT_XIP || MCUBOOT_RAM_LOAD */
25432549

0 commit comments

Comments
 (0)