Skip to content

Commit e2c97da

Browse files
committed
boot: bootutil: Fix serial recovery issues
Fixes serial recovery issues in various MCUboot operating modes by moving functions that are needed out from loader to a common file and adapting them to work in these different modes Signed-off-by: Jamie McCrae <jamie.mccrae@nordicsemi.no>
1 parent 2fcfba1 commit e2c97da

File tree

5 files changed

+315
-228
lines changed

5 files changed

+315
-228
lines changed

boot/bootutil/include/bootutil/bootutil.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,9 @@ fih_ret boot_go_for_image_id(struct boot_rsp *rsp, uint32_t image_id);
8989
void boot_state_clear(struct boot_loader_state *state);
9090
fih_ret context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp);
9191
struct boot_loader_state *boot_get_loader_state(void);
92+
struct image_max_size *boot_get_image_max_sizes(void);
9293
const struct image_max_size *boot_get_max_app_size(void);
94+
void boot_fetch_slot_state_sizes(void);
9395
uint32_t boot_get_state_secondary_offset(struct boot_loader_state *state,
9496
const struct flash_area *fap);
9597

boot/bootutil/src/bootutil_misc.c

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,23 @@
4343
#include "bootutil/enc_key.h"
4444
#endif
4545

46+
#if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) || defined(MCUBOOT_SWAP_USING_SCRATCH)
47+
#include "swap_priv.h"
48+
#endif
49+
4650
BOOT_LOG_MODULE_DECLARE(mcuboot);
4751

4852
/* Currently only used by imgmgr */
4953
int boot_current_slot;
5054

55+
#if (!defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)) || \
56+
defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO)
57+
/* Used for holding static buffers in multiple functions to work around issues
58+
* in older versions of gcc (e.g. 4.8.4)
59+
*/
60+
static struct boot_sector_buffer sector_buffers;
61+
#endif
62+
5163
/**
5264
* @brief Determine if the data at two memory addresses is equal
5365
*
@@ -696,3 +708,206 @@ boot_erase_region(const struct flash_area *fa, uint32_t off, uint32_t size, bool
696708
end:
697709
return rc;
698710
}
711+
712+
#if (!defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)) || \
713+
defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO)
714+
int
715+
boot_initialize_area(struct boot_loader_state *state, int flash_area)
716+
{
717+
uint32_t num_sectors = BOOT_MAX_IMG_SECTORS;
718+
boot_sector_t *out_sectors;
719+
uint32_t *out_num_sectors;
720+
int rc;
721+
722+
num_sectors = BOOT_MAX_IMG_SECTORS;
723+
724+
if (flash_area == FLASH_AREA_IMAGE_PRIMARY(BOOT_CURR_IMG(state))) {
725+
out_sectors = BOOT_IMG(state, BOOT_PRIMARY_SLOT).sectors;
726+
out_num_sectors = &BOOT_IMG(state, BOOT_PRIMARY_SLOT).num_sectors;
727+
#if BOOT_NUM_SLOTS > 1
728+
} else if (flash_area == FLASH_AREA_IMAGE_SECONDARY(BOOT_CURR_IMG(state))) {
729+
out_sectors = BOOT_IMG(state, BOOT_SECONDARY_SLOT).sectors;
730+
out_num_sectors = &BOOT_IMG(state, BOOT_SECONDARY_SLOT).num_sectors;
731+
#if MCUBOOT_SWAP_USING_SCRATCH
732+
} else if (flash_area == FLASH_AREA_IMAGE_SCRATCH) {
733+
out_sectors = state->scratch.sectors;
734+
out_num_sectors = &state->scratch.num_sectors;
735+
#endif
736+
#endif
737+
} else {
738+
return BOOT_EFLASH;
739+
}
740+
741+
#ifdef MCUBOOT_USE_FLASH_AREA_GET_SECTORS
742+
rc = flash_area_get_sectors(flash_area, &num_sectors, out_sectors);
743+
#else
744+
_Static_assert(sizeof(int) <= sizeof(uint32_t), "Fix needed");
745+
rc = flash_area_to_sectors(flash_area, (int *)&num_sectors, out_sectors);
746+
#endif /* defined(MCUBOOT_USE_FLASH_AREA_GET_SECTORS) */
747+
if (rc != 0) {
748+
return rc;
749+
}
750+
*out_num_sectors = num_sectors;
751+
return 0;
752+
}
753+
754+
static uint32_t
755+
boot_write_sz(struct boot_loader_state *state)
756+
{
757+
uint32_t elem_sz;
758+
#if MCUBOOT_SWAP_USING_SCRATCH
759+
uint32_t align;
760+
#endif
761+
762+
/* Figure out what size to write update status update as. The size depends
763+
* on what the minimum write size is for scratch area, active image slot.
764+
* We need to use the bigger of those 2 values.
765+
*/
766+
elem_sz = flash_area_align(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT));
767+
#if MCUBOOT_SWAP_USING_SCRATCH
768+
align = flash_area_align(BOOT_SCRATCH_AREA(state));
769+
if (align > elem_sz) {
770+
elem_sz = align;
771+
}
772+
#endif
773+
774+
return elem_sz;
775+
}
776+
777+
int
778+
boot_read_sectors(struct boot_loader_state *state, struct boot_sector_buffer *sectors)
779+
{
780+
uint8_t image_index;
781+
int rc;
782+
783+
if (sectors == NULL) {
784+
sectors = &sector_buffers;
785+
}
786+
787+
image_index = BOOT_CURR_IMG(state);
788+
789+
BOOT_IMG(state, BOOT_PRIMARY_SLOT).sectors =
790+
sectors->primary[image_index];
791+
#if BOOT_NUM_SLOTS > 1
792+
BOOT_IMG(state, BOOT_SECONDARY_SLOT).sectors =
793+
sectors->secondary[image_index];
794+
#if MCUBOOT_SWAP_USING_SCRATCH
795+
state->scratch.sectors = sectors->scratch;
796+
#endif
797+
#endif
798+
799+
rc = boot_initialize_area(state, FLASH_AREA_IMAGE_PRIMARY(image_index));
800+
if (rc != 0) {
801+
return BOOT_EFLASH;
802+
}
803+
804+
#if BOOT_NUM_SLOTS > 1
805+
rc = boot_initialize_area(state, FLASH_AREA_IMAGE_SECONDARY(image_index));
806+
if (rc != 0) {
807+
/* We need to differentiate from the primary image issue */
808+
return BOOT_EFLASH_SEC;
809+
}
810+
811+
#if MCUBOOT_SWAP_USING_SCRATCH
812+
rc = boot_initialize_area(state, FLASH_AREA_IMAGE_SCRATCH);
813+
if (rc != 0) {
814+
return BOOT_EFLASH;
815+
}
816+
#endif
817+
#endif
818+
819+
BOOT_WRITE_SZ(state) = boot_write_sz(state);
820+
821+
return 0;
822+
}
823+
#endif
824+
825+
#if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO)
826+
static int
827+
boot_read_sectors_recovery(struct boot_loader_state *state)
828+
{
829+
uint8_t image_index;
830+
int rc;
831+
832+
image_index = BOOT_CURR_IMG(state);
833+
834+
rc = boot_initialize_area(state, FLASH_AREA_IMAGE_PRIMARY(image_index));
835+
if (rc != 0) {
836+
return BOOT_EFLASH;
837+
}
838+
839+
rc = boot_initialize_area(state, FLASH_AREA_IMAGE_SECONDARY(image_index));
840+
if (rc != 0) {
841+
/* We need to differentiate from the primary image issue */
842+
return BOOT_EFLASH_SEC;
843+
}
844+
845+
return 0;
846+
}
847+
848+
/**
849+
* Reads image data to find out the maximum application sizes. Only needs to
850+
* be called in serial recovery mode, as the state information is unpopulated
851+
* at that time
852+
*/
853+
void boot_fetch_slot_state_sizes(void)
854+
{
855+
int rc = -1;
856+
int image_index;
857+
858+
rc = boot_open_all_flash_areas(boot_get_loader_state());
859+
if (rc != 0) {
860+
BOOT_LOG_DBG("boot_fetch_slot_state_sizes: error %d while opening flash areas", rc);
861+
goto finish;
862+
}
863+
864+
IMAGES_ITER(BOOT_CURR_IMG(boot_get_loader_state())) {
865+
int max_size = 0;
866+
867+
image_index = BOOT_CURR_IMG(boot_get_loader_state());
868+
869+
BOOT_IMG(boot_get_loader_state(), BOOT_PRIMARY_SLOT).sectors =
870+
sector_buffers.primary[image_index];
871+
#if BOOT_NUM_SLOTS > 1
872+
BOOT_IMG(boot_get_loader_state(), BOOT_SECONDARY_SLOT).sectors =
873+
sector_buffers.secondary[image_index];
874+
#if MCUBOOT_SWAP_USING_SCRATCH
875+
boot_get_loader_state()->scratch.sectors = sector_buffers.scratch;
876+
#endif
877+
#endif
878+
879+
/* Determine the sector layout of the image slots and scratch area. */
880+
rc = boot_read_sectors_recovery(boot_get_loader_state());
881+
882+
if (rc == 0) {
883+
max_size = app_max_size(boot_get_loader_state());
884+
885+
if (max_size > 0) {
886+
boot_get_image_max_sizes()[image_index].calculated = true;
887+
boot_get_image_max_sizes()[image_index].max_size = max_size;
888+
}
889+
}
890+
}
891+
892+
finish:
893+
boot_close_all_flash_areas(boot_get_loader_state());
894+
memset(boot_get_loader_state(), 0, sizeof(struct boot_loader_state));
895+
}
896+
#endif
897+
898+
/**
899+
* Clears the boot state, so that previous operations have no effect on new
900+
* ones.
901+
*
902+
* @param state The state that should be cleared. If the value
903+
* is NULL, the default bootloader state will be
904+
* cleared.
905+
*/
906+
void boot_state_clear(struct boot_loader_state *state)
907+
{
908+
if (state != NULL) {
909+
memset(state, 0, sizeof(struct boot_loader_state));
910+
} else {
911+
memset(boot_get_loader_state(), 0, sizeof(struct boot_loader_state));
912+
}
913+
}

boot/bootutil/src/bootutil_priv.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,12 @@ struct flash_area;
9292
#define BOOT_STATUS_OP_SWAP 2
9393
#endif
9494

95+
#if (BOOT_IMAGE_NUMBER > 1)
96+
#define IMAGES_ITER(x) for ((x) = 0; (x) < BOOT_IMAGE_NUMBER; ++(x))
97+
#else
98+
#define IMAGES_ITER(x)
99+
#endif
100+
95101
/*
96102
* Maintain state of copy progress.
97103
*/

0 commit comments

Comments
 (0)