Skip to content

Commit a94e57e

Browse files
edersondisouzateburd
authored andcommitted
boot/zephyr: Support for loading images from arbitrary flash slots
Instead of normal MCUboot flow, that checks flash slots to find update images, this patch enables an MCUboot application to chose from which available slots to load an image. This allows an application, for instance, to check hardware configuration at runtime (by checking hardware straps, state of GPIOs, etc) and decide from where to load an image to boot. MCUboot will basically loop through provided image sources (flash slots) and boot the first one that succed signature/validation. To provide the image sources, the application need to provide strong implementation for functions flash_map_id_get_next() and flash_map_id_get_current(). The default, weak, implementations just keep current behaviour for single loader, i.e. just load from FLASH_AREA_IMAGE_PRIMARY(0). Note that in this case, MCUboot won't try to record if image succeeded boot, it will only boot the image provided. Signed-off-by: Ederson de Souza <[email protected]> Signed-off-by: Tom Burdick <[email protected]>
1 parent e43e670 commit a94e57e

File tree

4 files changed

+130
-24
lines changed

4 files changed

+130
-24
lines changed

boot/zephyr/Kconfig

+12
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,18 @@ config BOOT_IMAGE_EXECUTABLE_RAM_SIZE
383383
default $(dt_chosen_reg_size_int,$(DT_CHOSEN_Z_SRAM),0)
384384
endif
385385

386+
config FLASH_RUNTIME_SOURCES
387+
bool "Images are read from flash partitions defined at runtime"
388+
select SINGLE_APPLICATION_SLOT
389+
help
390+
Instead of using information on the flash slots to decide which images
391+
to load/update, the application provides the information from which
392+
flash slot to load in runtime. This is useful when the application
393+
reads the state for hardware straps or other sources to decide which
394+
image to load. The application must provide `flash_map_id_get_next`
395+
and `flash_map_id_get_next` functions to tell mcuboot where to find
396+
the images.
397+
386398
config BOOT_ENCRYPTION_SUPPORT
387399
bool
388400
help

boot/zephyr/flash_map_extended.c

+10-1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,15 @@ int flash_device_base(uint8_t fd_id, uintptr_t *ret)
5858
*/
5959
int flash_area_id_from_multi_image_slot(int image_index, int slot)
6060
{
61+
#if defined(CONFIG_FLASH_RUNTIME_SOURCES)
62+
uint8_t id;
63+
64+
if (flash_map_id_get_current(&id)) {
65+
return id;
66+
}
67+
return -1;
68+
#endif
69+
6170
switch (slot) {
6271
case 0: return FLASH_AREA_IMAGE_PRIMARY(image_index);
6372
#if !defined(CONFIG_SINGLE_APPLICATION_SLOT)
@@ -141,7 +150,7 @@ int flash_area_sector_from_off(off_t off, struct flash_sector *sector)
141150

142151
uint8_t flash_area_get_device_id(const struct flash_area *fa)
143152
{
144-
#if defined(CONFIG_ARM)
153+
#if defined(CONFIG_ARM) || defined(CONFIG_FLASH_RUNTIME_SOURCES)
145154
return fa->fa_id;
146155
#else
147156
(void)fa;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright (c) 2024 Intel Corporation
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#ifndef __FLASH_RUNTIME_SOURCES_H__
8+
#define __FLASH_RUNTIME_SOURCES_H__
9+
10+
#include <inttypes.h>
11+
12+
#ifdef __cplusplus
13+
extern "C" {
14+
#endif
15+
16+
/*
17+
* Get next flash map id.
18+
*
19+
* Implement this function to get the next flash map id. The function should
20+
* return true if the flash map id was successfully updated. If the reset
21+
* parameter is true, the function should reset the flash map id to the first
22+
* one.
23+
*
24+
* @param id Pointer to the flash map id.
25+
* @param reset If true, the function will reset the flash map id to the first
26+
* one.
27+
* @retval true If the flash map id was successfully updated.
28+
*/
29+
bool flash_map_id_get_next(uint8_t *id, bool reset);
30+
31+
/*
32+
* Get current flash map id.
33+
*
34+
* Implement this function to get the current flash map id. The function should
35+
* return true if the flash map id was successfully read.
36+
*
37+
* @param id Pointer to the flash map id.
38+
* @retval true If the flash map id was successfully read.
39+
*/
40+
bool flash_map_id_get_current(uint8_t *id);
41+
42+
#ifdef __cplusplus
43+
}
44+
#endif
45+
46+
#endif /* __FLASH_RUNTIME_SOURCES_H__ */

boot/zephyr/single_loader.c

+62-23
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,30 @@ BOOT_LOG_MODULE_DECLARE(mcuboot);
2020
static const struct flash_area *_fa_p;
2121
static struct image_header _hdr = { 0 };
2222

23+
__weak bool
24+
flash_map_id_get_next(uint8_t *id, bool reset)
25+
{
26+
if (!reset || !id) {
27+
return false;
28+
}
29+
30+
*id = FLASH_AREA_IMAGE_PRIMARY(0);
31+
32+
return true;
33+
}
34+
35+
__weak bool
36+
flash_map_id_get_current(uint8_t *id)
37+
{
38+
if (!id) {
39+
return false;
40+
}
41+
42+
*id = FLASH_AREA_IMAGE_PRIMARY(0);
43+
44+
return true;
45+
}
46+
2347
#if defined(MCUBOOT_VALIDATE_PRIMARY_SLOT) || defined(MCUBOOT_VALIDATE_PRIMARY_SLOT_ONCE)
2448
/**
2549
* Validate hash of a primary boot image.
@@ -102,50 +126,65 @@ fih_ret
102126
boot_go(struct boot_rsp *rsp)
103127
{
104128
int rc = -1;
129+
uint8_t flash_id;
130+
bool reset = true;
105131
FIH_DECLARE(fih_rc, FIH_FAILURE);
106132

107-
rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(0), &_fa_p);
108-
assert(rc == 0);
133+
while (flash_map_id_get_next(&flash_id, reset)) {
134+
reset = false;
135+
rc = flash_area_open(flash_id, &_fa_p);
136+
if (rc != 0) {
137+
continue;
138+
}
109139

110-
rc = boot_image_load_header(_fa_p, &_hdr);
111-
if (rc != 0)
112-
goto out;
140+
rc = boot_image_load_header(_fa_p, &_hdr);
141+
if (rc != 0) {
142+
flash_area_close(_fa_p);
143+
continue;
144+
}
113145

114146
#ifdef MCUBOOT_RAM_LOAD
115147
static struct boot_loader_state state;
116148
state.imgs[0][0].hdr = _hdr;
117149

118150
rc = boot_load_image_to_sram(&state);
119-
if (rc != 0)
120-
goto out;
151+
if (rc != 0) {
152+
flash_area_close(_fa_p);
153+
continue;
154+
}
121155
#endif
122156

123157
#ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT
124-
FIH_CALL(boot_image_validate, fih_rc, _fa_p, &_hdr);
125-
if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
158+
FIH_CALL(boot_image_validate, fih_rc, _fa_p, &_hdr);
159+
if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
160+
flash_area_close(_fa_p);
126161
#ifdef MCUBOOT_RAM_LOAD
127-
boot_remove_image_from_sram(&state);
162+
boot_remove_image_from_sram(&state);
128163
#endif
129-
goto out;
130-
}
164+
continue;
165+
}
131166
#elif defined(MCUBOOT_VALIDATE_PRIMARY_SLOT_ONCE)
132-
FIH_CALL(boot_image_validate_once, fih_rc, _fa_p, &_hdr);
133-
if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
167+
FIH_CALL(boot_image_validate_once, fih_rc, _fa_p, &_hdr);
168+
if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
169+
flash_area_close(_fa_p);
134170
#ifdef MCUBOOT_RAM_LOAD
135-
boot_remove_image_from_sram(&state);
171+
boot_remove_image_from_sram(&state);
136172
#endif
137-
goto out;
138-
}
173+
continue;
174+
}
139175
#else
140-
fih_rc = FIH_SUCCESS;
176+
fih_rc = FIH_SUCCESS;
141177
#endif /* MCUBOOT_VALIDATE_PRIMARY_SLOT */
142178

143-
rsp->br_flash_dev_id = flash_area_get_device_id(_fa_p);
144-
rsp->br_image_off = flash_area_get_off(_fa_p);
145-
rsp->br_hdr = &_hdr;
179+
rsp->br_flash_dev_id = flash_area_get_device_id(_fa_p);
180+
rsp->br_image_off = flash_area_get_off(_fa_p);
181+
rsp->br_hdr = &_hdr;
182+
183+
flash_area_close(_fa_p);
184+
185+
break;
186+
}
146187

147-
out:
148-
flash_area_close(_fa_p);
149188

150189
FIH_RET(fih_rc);
151190
}

0 commit comments

Comments
 (0)