Skip to content

Commit a4aabf3

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 78f87cf commit a4aabf3

File tree

3 files changed

+197
-2
lines changed

3 files changed

+197
-2
lines changed

boot/bootutil/src/bootutil_misc.c

Lines changed: 167 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,141 @@ 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+
size_t slot_size;
680+
size_t slot_off;
681+
size_t sect_off = 0;
682+
int rc;
683+
int final_rc = 0;
684+
const struct flash_parameters *fparams;
685+
bool device_with_erase;
686+
uint32_t wbs;
687+
688+
assert(fa != NULL);
689+
assert(faid != 0);
690+
691+
slot_off = flash_area_get_off(fa);
692+
slot_size = flash_area_get_size(fa);
693+
694+
fparams = flash_get_parameters(flash_area_get_device(fa));
695+
wbs = fparams->write_block_size;
696+
697+
device_with_erase =
698+
(flash_params_get_erase_cap(fparams) & FLASH_ERASE_C_EXPLICIT) == FLASH_ERASE_C_EXPLICIT;
699+
/* Go till all verifications are complete or we face issue that does not allow
700+
* to precede with further tests.
701+
*/
702+
BOOT_LOG_INF("boot_verify_logical_sectors: verify flash area %p", fa);
703+
BOOT_LOG_INF("boot_verify_logical_sectors: MCUBOOT_LOGICAL_SECTOR_SIZE == 0x%x",
704+
MCUBOOT_LOGICAL_SECTOR_SIZE);
705+
BOOT_LOG_INF("boot_verify_logical_sectors: slot offset == 0x%x", slot_off);
706+
if (slot_size != 0) {
707+
BOOT_LOG_INF("boot_verify_logical_sectors: slot size == 0x%x", slot_size);
708+
} else {
709+
BOOT_LOG_ERR("boot_verify_logical_sectors: 0 size slot");
710+
return BOOT_EFLASH;
711+
}
712+
BOOT_LOG_INF("boot_verify_logical_sectors: write block size %u", wbs);
713+
BOOT_LOG_INF("boot_verify_logical_sectors: device with%s erase",
714+
device_with_erase ? "" : "out");
715+
716+
/* We are expecting slot size to be multiple of logical sector size.
717+
* Note though that we do not check alignment of the slot to logical sector.
718+
* as it does not matter, only alignment of slot to a real erase page
719+
* matters.
720+
*/
721+
if (slot_size % MCUBOOT_LOGICAL_SECTOR_SIZE) {
722+
BOOT_LOG_ERR("boot_verify_logical_sectors: area size not aligned");
723+
final_rc = BOOT_EFLASH;
724+
}
725+
726+
BOOT_LOG_INF("boot_verify_logical_sectors: max %d logical sectors",
727+
slot_size / MCUBOOT_LOGICAL_SECTOR_SIZE);
728+
729+
if (device_with_erase) {
730+
size_t total_scanned = 0;
731+
732+
/* Check all logical sectors pages against erase pages of a device */
733+
while (total_scanned < slot_size) {
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+
/* Jumping by logical sector size should align us with real erase page
747+
* each time.
748+
*/
749+
if (sect_off == flash_sector_get_off(&fas)) {
750+
BOOT_LOG_ERR("boot_verify_logical_sectors: misaligned offset");
751+
final_rc = BOOT_EFLASH;
752+
}
753+
754+
/* Jumping by logical sector size */
755+
sect_off += MCUBOOT_LOGICAL_SECTOR_SIZE;
756+
total_scanned += MCUBOOT_LOGICAL_SECTOR_SIZE;
757+
}
758+
} else {
759+
/* Devices with no-explicit erase require alignment to write block size */
760+
761+
if (MCUBOOT_LOGICAL_SECTOR_SIZE % wbs) {
762+
BOOT_LOG_ERR("boot_verify_logical_sectors: sector size not aligned to write block");
763+
final_rc = BOOT_EFLASH;
764+
}
765+
766+
if (slot_off % wbs) {
767+
BOOT_LOG_ERR("boot_verify_logical_sectors: slot not aligned to write block");
768+
final_rc = BOOT_EFLASH;
769+
}
770+
}
771+
772+
BOOT_LOG_INF("boot_verify_logical_sectors: completed (%d)", final_rc);
773+
774+
return final_rc;
775+
}
776+
#endif /* MCUBOOT_LOGICAL_SECTOR_VALIDATION */
777+
778+
static int
779+
boot_initialize_area(struct boot_loader_state *state, int flash_area)
780+
{
781+
size_t area_size;
782+
uint32_t *out_num_sectors;
783+
784+
if (flash_area == FLASH_AREA_IMAGE_PRIMARY(BOOT_CURR_IMG(state))) {
785+
area_size = flash_area_get_size(BOOT_IMG_AREA(state, BOOT_SLOT_PRIMARY));
786+
out_num_sectors = &BOOT_IMG(state, BOOT_SLOT_PRIMARY).num_sectors;
787+
} else if (flash_area == FLASH_AREA_IMAGE_SECONDARY(BOOT_CURR_IMG(state))) {
788+
area_size = flash_area_get_size(BOOT_IMG_AREA(state, BOOT_SLOT_SECONDARY));
789+
out_num_sectors = &BOOT_IMG(state, BOOT_SLOT_SECONDARY).num_sectors;
790+
#if MCUBOOT_SWAP_USING_SCRATCH
791+
} else if (flash_area == FLASH_AREA_IMAGE_SCRATCH) {
792+
area_size = flash_area_get_size(state->scratch.area);
793+
out_num_sectors = &state->scratch.num_sectors;
794+
#endif
795+
} else {
796+
return BOOT_EFLASH;
797+
}
798+
799+
*out_num_sectors = area_size / MCUBOOT_LOGICAL_SECTOR_SIZE;
800+
801+
return 0;
802+
}
803+
804+
#endif /* defined(MCUBOOT_LOGICAL_SECTOR_SIZE) && MCUBOOT_LOGICAL_SECTOR_SIZE != 0 */
805+
668806
static uint32_t
669807
boot_write_sz(struct boot_loader_state *state)
670808
{
@@ -694,12 +832,13 @@ boot_read_sectors(struct boot_loader_state *state, struct boot_sector_buffer *se
694832
uint8_t image_index;
695833
int rc;
696834

835+
image_index = BOOT_CURR_IMG(state);
836+
837+
#if !defined(MCUBOOT_LOGICAL_SECTOR_SIZE) || MCUBOOT_LOGICAL_SECTOR_SIZE == 0
697838
if (sectors == NULL) {
698839
sectors = &sector_buffers;
699840
}
700841

701-
image_index = BOOT_CURR_IMG(state);
702-
703842
BOOT_IMG(state, BOOT_SLOT_PRIMARY).sectors =
704843
sectors->primary[image_index];
705844
#if BOOT_NUM_SLOTS > 1
@@ -709,6 +848,9 @@ boot_read_sectors(struct boot_loader_state *state, struct boot_sector_buffer *se
709848
state->scratch.sectors = sectors->scratch;
710849
#endif
711850
#endif
851+
#else
852+
(void)sectors;
853+
#endif /* !defined(MCUBOOT_LOGICAL_SECTOR_SIZE) || MCUBOOT_LOGICAL_SECTOR_SIZE == 0 */
712854

713855
rc = boot_initialize_area(state, FLASH_AREA_IMAGE_PRIMARY(image_index));
714856
if (rc != 0) {
@@ -732,6 +874,29 @@ boot_read_sectors(struct boot_loader_state *state, struct boot_sector_buffer *se
732874

733875
BOOT_WRITE_SZ(state) = boot_write_sz(state);
734876

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

boot/bootutil/src/bootutil_priv.h

Lines changed: 24 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,25 @@ 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+
return MCUBOOT_LOGICAL_SECTOR_SIZE;
563+
}
564+
565+
/*
566+
* Offset of the sector from the beginning of the image, NOT the flash
567+
* device.
568+
*/
569+
static inline uint32_t
570+
boot_img_sector_off(const struct boot_loader_state *state, size_t slot,
571+
size_t sector)
572+
{
573+
return MCUBOOT_LOGICAL_SECTOR_SIZE * sector;
574+
}
575+
#endif
552576

553577
#ifdef MCUBOOT_RAM_LOAD
554578
# 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)