Skip to content

Commit 3b5af50

Browse files
samples: Add a sample for runtime chosen image
A sample for runtime chose image on FRDM K64F. It provides implementation for boot_go and flash area id related hooks, showing how an external module implementing hooks can influence which images end up being booted on the platform. In this sample, one can influence from which slot image will be loaded by pressing a button on the board. For more details on how to build and test the samples, check the provided README.md. Signed-off-by: Ederson de Souza <[email protected]> Signed-off-by: Tom Burdick <[email protected]>
1 parent 5e8f30f commit 3b5af50

File tree

9 files changed

+220
-0
lines changed

9 files changed

+220
-0
lines changed
+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Runtime chosen image sample application
2+
3+
This sample demonstrates how to use a non flash storage to retrieve the image
4+
being booted. It was tested on a FRDM K64F. Both slots are used to store two
5+
different images. The image to be booted is selected based on a button press.
6+
7+
## Build
8+
9+
Build mcuboot. First, ensure ZEPHYR_SDK_INSTALL_DIR is defined. From the
10+
sample directory, run the following commands:
11+
12+
```
13+
source <path-to-zephyr>/zephyr-env.sh
14+
15+
west build -p -b frdm_k64f ../../../boot/zephyr/ -- \
16+
-DEXTRA_ZEPHYR_MODULES=$PWD/hooks -DEXTRA_CONF_FILE="$PWD/sample.conf"
17+
18+
west build -t flash
19+
```
20+
21+
Then, build the sample application to be loaded. We need to build it twice, one
22+
for each slot. From the sample
23+
app directory (mcuboot/samples/non-flash-source/zephyr/app), run:
24+
25+
```
26+
west build -p -b frdm_k64f .
27+
west flash
28+
```
29+
30+
Then change the overlay file to use the second slot. For instance, open
31+
`boards/frdm_k64f.overlay` and change the line:
32+
33+
```
34+
zephyr,code-partition = &slot0_partition;
35+
36+
```
37+
38+
to:
39+
40+
```
41+
zephyr,code-partition = &slot1_partition;
42+
```
43+
44+
And build and flash again:
45+
46+
```
47+
west build -b frdm_k64f .
48+
west flash
49+
```
50+
51+
## Run
52+
53+
Open a serial terminal to see the output and reset the board. It shall boot the
54+
image on slot0 by default. By keeping the SW2 button pressed during reset, the
55+
bootloader will boot the one on slot1.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
cmake_minimum_required(VERSION 3.20.0)
4+
5+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
6+
project(non_flash_backend_app)
7+
8+
if(NOT DEFINED FROM_WHO)
9+
set(FROM_WHO Zephyr)
10+
endif()
11+
12+
target_compile_definitions(app PRIVATE "-DMCUBOOT_HELLO_WORLD_FROM=\"${FROM_WHO}\"")
13+
14+
target_sources(app PRIVATE src/main.c)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/ {
2+
chosen {
3+
zephyr,code-partition = &slot0_partition;
4+
};
5+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
CONFIG_BOOTLOADER_MCUBOOT=y
2+
3+
CONFIG_MCUBOOT_SIGNATURE_KEY_FILE="./bootloader/mcuboot/root-rsa-2048.pem"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*
2+
* Copyright (c) 2024 Intel Corporation
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/kernel.h>
8+
#include <zephyr/sys/printk.h>
9+
10+
int main(void)
11+
{
12+
printk("Hello World from %s on %s, slot %s!\n",
13+
MCUBOOT_HELLO_WORLD_FROM, CONFIG_BOARD,
14+
DT_PROP(DT_CHOSEN(zephyr_code_partition), label));
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
zephyr_library()
2+
zephyr_library_sources(hooks.c)
3+
zephyr_library_link_libraries(MCUBOOT_BOOTUTIL)
+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
/*
2+
* Copyright (c) 2024 Intel Corporation
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/drivers/gpio.h>
8+
#include <zephyr/kernel.h>
9+
10+
#include "bootutil/bootutil.h"
11+
#include "bootutil/bootutil_public.h"
12+
#include "bootutil/fault_injection_hardening.h"
13+
14+
#define BOOT_TMPBUF_SZ 256
15+
16+
static struct image_header _hdr;
17+
static uint8_t tmpbuf[BOOT_TMPBUF_SZ];
18+
19+
static uint8_t known_ids[] = {
20+
FIXED_PARTITION_ID(slot0_partition),
21+
FIXED_PARTITION_ID(slot1_partition),
22+
};
23+
24+
static int current_id;
25+
26+
#define SW1_NODE DT_ALIAS(sw1)
27+
#if DT_NODE_HAS_STATUS(SW1_NODE, okay)
28+
static struct gpio_dt_spec sw1_spec = GPIO_DT_SPEC_GET(SW1_NODE, gpios);
29+
#endif
30+
31+
fih_ret boot_go_hook(struct boot_rsp *rsp)
32+
{
33+
int rc;
34+
#ifdef MCUBOOT_RAM_LOAD
35+
struct boot_loader_state *state;
36+
#endif
37+
FIH_DECLARE(fih_rc, FIH_FAILURE);
38+
const struct flash_area *_fa_p;
39+
40+
current_id = 0;
41+
42+
#if DT_NODE_HAS_STATUS(SW1_NODE, okay)
43+
if (gpio_pin_configure_dt(&sw1_spec, GPIO_INPUT) == 0) {
44+
if (gpio_pin_get_dt(&sw1_spec) == 1) {
45+
current_id = ARRAY_SIZE(known_ids) - 1;
46+
printk("%s pressed, forcing boot from partition %u\n",
47+
sw1_spec.port->name, known_ids[current_id]);
48+
} else {
49+
printk("%s not pressed, looping partitions to boot\n",
50+
sw1_spec.port->name);
51+
}
52+
}
53+
#else
54+
printk("SW1 not defined, looping partitions to boot\n");
55+
#endif
56+
57+
for ( ; current_id < ARRAY_SIZE(known_ids); current_id++) {
58+
printk("Trying to boot from fixed partition %u\n",
59+
known_ids[current_id]);
60+
61+
rc = flash_area_open(known_ids[current_id], &_fa_p);
62+
if (rc != 0) {
63+
continue;
64+
}
65+
66+
rc = boot_image_load_header(_fa_p, &_hdr);
67+
if (rc != 0) {
68+
flash_area_close(_fa_p);
69+
continue;
70+
}
71+
72+
#ifdef MCUBOOT_RAM_LOAD
73+
state = boot_get_loader_state();
74+
75+
rc = boot_load_image_from_flash_to_sram(state, &_hdr);
76+
if (rc != 0) {
77+
flash_area_close(_fa_p);
78+
continue;
79+
}
80+
#endif
81+
82+
FIH_CALL(bootutil_img_validate, fih_rc, NULL, 0, &_hdr, _fa_p, tmpbuf,
83+
BOOT_TMPBUF_SZ, NULL, 0, NULL);
84+
if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
85+
flash_area_close(_fa_p);
86+
#ifdef MCUBOOT_RAM_LOAD
87+
boot_remove_image_from_sram(state);
88+
#endif
89+
continue;
90+
}
91+
92+
rsp->br_flash_dev_id = flash_area_get_device_id(_fa_p);
93+
rsp->br_image_off = flash_area_get_off(_fa_p);
94+
rsp->br_hdr = &_hdr;
95+
96+
flash_area_close(_fa_p);
97+
break;
98+
}
99+
100+
FIH_RET(fih_rc);
101+
}
102+
103+
int flash_area_id_from_multi_image_slot_hook(int image_index, int slot,
104+
int *area_id)
105+
{
106+
*area_id = known_ids[current_id];
107+
108+
return 0;
109+
}
110+
111+
int flash_area_get_device_id_hook(const struct flash_area *fa, uint8_t *dev_id)
112+
{
113+
return BOOT_HOOK_REGULAR;
114+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
name: testmod
2+
build:
3+
cmake: .
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CONFIG_FLASH_RUNTIME_SOURCES=y
2+
CONFIG_SINGLE_APPLICATION_SLOT=y
3+
CONFIG_BOOT_SIGNATURE_TYPE_RSA=y
4+
CONFIG_TEST_RANDOM_GENERATOR=y
5+
CONFIG_ENTROPY_GENERATOR=y
6+
7+
CONFIG_BOOT_GO_HOOKS=y
8+
CONFIG_BOOT_FLASH_AREA_HOOKS=y

0 commit comments

Comments
 (0)