Skip to content

Commit 6bd57b6

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 10a3cff commit 6bd57b6

File tree

3 files changed

+193
-2
lines changed

3 files changed

+193
-2
lines changed

boot/bootutil/src/bootutil_misc.c

Lines changed: 163 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,137 @@ 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(const struct boot_loader_state *state, int faid, const struct flash_area *fa)
678+
{
679+
uint32_t num_sectors = BOOT_MAX_IMG_SECTORS;
680+
size_t slot_size;
681+
size_t slot_off;
682+
size_t sect_off = 0;
683+
int rc;
684+
int final_rc = 0;
685+
const struct flash_parameters *fparams;
686+
bool device_with_erase;
687+
uint32_t wbs;
688+
689+
assert(fa != NULL);
690+
assert(faid != 0);
691+
692+
slot_off = flash_area_get_off(fa);
693+
slot_size = flash_area_get_size(fa);
694+
695+
fparams = flash_get_parameters(flash_area_get_device(fa));
696+
wbs = fparams->write_block_size;
697+
698+
device_with_erase =
699+
(flash_params_get_erase_cap(fparams) & FLASH_ERASE_C_EXPLICIT) & FLASH_ERASE_C_EXPLICIT;
700+
/* Go till all verifications are complete or we face issue that does not allow
701+
* to proceede with further tests.
702+
*/
703+
BOOT_LOG_INF("boot_verify_logical_sectors: verify flash area %p", fa);
704+
BOOT_LOG_INF("boot_verify_logical_sectors: MCUBOOT_LOGICAL_SECTOR_SIZE == 0x%x",
705+
MCUBOOT_LOGICAL_SECTOR_SIZE);
706+
BOOT_LOG_INF("boot_verify_logical_sectors: slot offset == 0x%x", slot_off);
707+
if (slot_size != 0) {
708+
BOOT_LOG_INF("boot_verify_logical_sectors: slot size == 0x%x", slot_size);
709+
} else {
710+
BOOT_LOG_ERR("boot_verify_logical_sectors: 0 size slot");
711+
return BOOT_EFLASH;
712+
}
713+
BOOT_LOG_INF("boot_verify_logical_sectors: write block size %u", wbs);
714+
BOOT_LOG_INF("boot_verify_logical_sectors: device with%s erase",
715+
device_with_erase ? "" : "out");
716+
717+
if (slot_size % MCUBOOT_LOGICAL_SECTOR_SIZE) {
718+
BOOT_LOG_ERR("boot_verify_logical_sectors: area size not aligned");
719+
final_rc = BOOT_EFLASH;
720+
}
721+
722+
BOOT_LOG_INF("boot_verify_logical_sectors: max %d logical sectors",
723+
slot_size / MCUBOOT_LOGICAL_SECTOR_SIZE);
724+
725+
if (device_with_erase) {
726+
/* Devices with explicit erase require alignment to page */
727+
if (slot_off % MCUBOOT_LOGICAL_SECTOR_SIZE) {
728+
BOOT_LOG_ERR("boot_verify_logical_sectors: area offset not aligned");
729+
final_rc = BOOT_EFLASH;
730+
}
731+
732+
/* Check all hardware specific pages against erase pages of a device */
733+
for (size_t i = 0; i < num_sectors; i++) {
734+
struct flash_sector fas;
735+
736+
MCUBOOT_WATCHDOG_FEED();
737+
738+
BOOT_LOG_INF("boot_verify_logical_sectors: page 0x%x:0x%x ", slot_off, sect_off);
739+
rc = flash_area_get_sector(fa, sect_off, &fas);
740+
if (rc < 0) {
741+
BOOT_LOG_ERR("boot_verify_logical_sectors: query err %d", rc);
742+
final_rc = BOOT_EFLASH;
743+
continue;
744+
}
745+
746+
747+
if (flash_sector_get_off(&fas) % MCUBOOT_LOGICAL_SECTOR_SIZE) {
748+
BOOT_LOG_ERR("boot_verify_logical_sectors: misaligned offset");
749+
final_rc = BOOT_EFLASH;
750+
}
751+
752+
sect_off += flash_sector_get_size(&fas);
753+
}
754+
} else {
755+
/* Devices with no-explicit erase require alignment to write block size */
756+
757+
if (MCUBOOT_LOGICAL_SECTOR_SIZE % wbs) {
758+
BOOT_LOG_ERR("boot_verify_logical_sectors: sector size not aligned to write block");
759+
final_rc = BOOT_EFLASH;
760+
}
761+
762+
if (slot_off % wbs) {
763+
BOOT_LOG_ERR("boot_verify_logical_sectors: slot not aligned to write block");
764+
final_rc = BOOT_EFLASH;
765+
}
766+
}
767+
768+
BOOT_LOG_INF("boot_verify_logical_sectors: completed (%d)", final_rc);
769+
770+
return final_rc;
771+
}
772+
#endif /* MCUBOOT_LOGICAL_SECTOR_VALIDATION */
773+
774+
static int
775+
boot_initialize_area(struct boot_loader_state *state, int flash_area)
776+
{
777+
size_t area_size;
778+
uint32_t *out_num_sectors;
779+
780+
if (flash_area == FLASH_AREA_IMAGE_PRIMARY(BOOT_CURR_IMG(state))) {
781+
area_size = flash_area_get_size(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT));
782+
out_num_sectors = &BOOT_IMG(state, BOOT_PRIMARY_SLOT).num_sectors;
783+
} else if (flash_area == FLASH_AREA_IMAGE_SECONDARY(BOOT_CURR_IMG(state))) {
784+
area_size = flash_area_get_size(BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT));
785+
out_num_sectors = &BOOT_IMG(state, BOOT_SECONDARY_SLOT).num_sectors;
786+
#if MCUBOOT_SWAP_USING_SCRATCH
787+
} else if (flash_area == FLASH_AREA_IMAGE_SCRATCH) {
788+
area_size = flash_area_get_size(state->scratch.area);
789+
out_num_sectors = &state->scratch.num_sectors;
790+
#endif
791+
} else {
792+
return BOOT_EFLASH;
793+
}
794+
795+
*out_num_sectors = area_size / MCUBOOT_LOGICAL_SECTOR_SIZE;
796+
797+
return 0;
798+
}
799+
800+
#endif /* defined(MCUBOOT_LOGICAL_SECTOR_SIZE) && MCUBOOT_LOGICAL_SECTOR_SIZE != 0 */
801+
668802
static uint32_t
669803
boot_write_sz(struct boot_loader_state *state)
670804
{
@@ -694,12 +828,13 @@ boot_read_sectors(struct boot_loader_state *state, struct boot_sector_buffer *se
694828
uint8_t image_index;
695829
int rc;
696830

831+
image_index = BOOT_CURR_IMG(state);
832+
833+
#if !defined(MCUBOOT_LOGICAL_SECTOR_SIZE) || MCUBOOT_LOGICAL_SECTOR_SIZE == 0
697834
if (sectors == NULL) {
698835
sectors = &sector_buffers;
699836
}
700837

701-
image_index = BOOT_CURR_IMG(state);
702-
703838
BOOT_IMG(state, BOOT_PRIMARY_SLOT).sectors =
704839
sectors->primary[image_index];
705840
#if BOOT_NUM_SLOTS > 1
@@ -709,6 +844,9 @@ boot_read_sectors(struct boot_loader_state *state, struct boot_sector_buffer *se
709844
state->scratch.sectors = sectors->scratch;
710845
#endif
711846
#endif
847+
#else
848+
(void)sectors;
849+
#endif /* !defined(MCUBOOT_LOGICAL_SECTOR_SIZE) || MCUBOOT_LOGICAL_SECTOR_SIZE == 0 */
712850

713851
rc = boot_initialize_area(state, FLASH_AREA_IMAGE_PRIMARY(image_index));
714852
if (rc != 0) {
@@ -732,6 +870,29 @@ boot_read_sectors(struct boot_loader_state *state, struct boot_sector_buffer *se
732870

733871
BOOT_WRITE_SZ(state) = boot_write_sz(state);
734872

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

boot/bootutil/src/bootutil_priv.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,14 +245,18 @@ struct boot_loader_state {
245245
struct {
246246
struct image_header hdr;
247247
const struct flash_area *area;
248+
#if !defined(MCUBOOT_LOGICAL_SECTOR_SIZE) || MCUBOOT_LOGICAL_SECTOR_SIZE == 0
248249
boot_sector_t *sectors;
250+
#endif
249251
uint32_t num_sectors;
250252
} imgs[BOOT_IMAGE_NUMBER][BOOT_NUM_SLOTS];
251253

252254
#if MCUBOOT_SWAP_USING_SCRATCH
253255
struct {
254256
const struct flash_area *area;
257+
#if !defined(MCUBOOT_LOGICAL_SECTOR_SIZE) || MCUBOOT_LOGICAL_SECTOR_SIZE == 0
255258
boot_sector_t *sectors;
259+
#endif
256260
uint32_t num_sectors;
257261
} scratch;
258262
#endif
@@ -515,6 +519,7 @@ boot_img_slot_off(struct boot_loader_state *state, size_t slot)
515519
return flash_area_get_off(BOOT_IMG_AREA(state, slot));
516520
}
517521

522+
#if !defined(MCUBOOT_LOGICAL_SECTOR_SIZE) || MCUBOOT_LOGICAL_SECTOR_SIZE == 0
518523
#ifndef MCUBOOT_USE_FLASH_AREA_GET_SECTORS
519524

520525
static inline size_t
@@ -554,6 +559,25 @@ boot_img_sector_off(const struct boot_loader_state *state, size_t slot,
554559
}
555560

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

558582
#ifdef MCUBOOT_RAM_LOAD
559583
# 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)