From 0ffcf4f44ed4fce8bf78b10c29c5a6f05b0e12e4 Mon Sep 17 00:00:00 2001 From: Ederson de Souza Date: Wed, 7 Aug 2024 08:34:26 -0700 Subject: [PATCH] samples: Add a sample for runtime chosen image A sample for runtime chose image on FRDM K64F. It provides implementation for Zephyr flash_area_open_custom(), so the right flash map implementation is used, and MCUboot flash_map_id_get_next() and flash_map_id_get_current() to prioritize sources. It should show what is expected from an application to be able to use non-flash sources for images. 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 --- boot/zephyr/CMakeLists.txt | 6 ++ boot/zephyr/flash_map_extended.c | 4 ++ samples/runtime-source/zephyr/README.md | 56 +++++++++++++++++ .../runtime-source/zephyr/app/CMakeLists.txt | 14 +++++ .../zephyr/app/boards/frdm_k64f.overlay | 5 ++ samples/runtime-source/zephyr/app/prj.conf | 3 + samples/runtime-source/zephyr/app/src/main.c | 15 +++++ .../zephyr/flash_map_dispatcher.c | 60 +++++++++++++++++++ samples/runtime-source/zephyr/sample.conf | 4 ++ 9 files changed, 167 insertions(+) create mode 100644 samples/runtime-source/zephyr/README.md create mode 100644 samples/runtime-source/zephyr/app/CMakeLists.txt create mode 100644 samples/runtime-source/zephyr/app/boards/frdm_k64f.overlay create mode 100644 samples/runtime-source/zephyr/app/prj.conf create mode 100644 samples/runtime-source/zephyr/app/src/main.c create mode 100644 samples/runtime-source/zephyr/flash_map_dispatcher.c create mode 100644 samples/runtime-source/zephyr/sample.conf diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 54bdee19b..834c4731c 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -428,6 +428,12 @@ if(CONFIG_BOOT_MAX_IMG_SECTORS_AUTO) endif() endif() +if(BUILD_RUNTIME_SOURCE_SAMPLE) + zephyr_library_sources( + ${MCUBOOT_DIR}/samples/runtime-source/zephyr/flash_map_dispatcher.c + ) +endif() + if(SYSBUILD) if(CONFIG_SINGLE_APPLICATION_SLOT OR CONFIG_BOOT_FIRMWARE_LOADER OR CONFIG_BOOT_SWAP_USING_SCRATCH OR CONFIG_BOOT_SWAP_USING_MOVE OR CONFIG_BOOT_UPGRADE_ONLY OR CONFIG_BOOT_DIRECT_XIP OR CONFIG_BOOT_RAM_LOAD) # TODO: RAM LOAD support diff --git a/boot/zephyr/flash_map_extended.c b/boot/zephyr/flash_map_extended.c index c13d6adf0..ef11f34cd 100644 --- a/boot/zephyr/flash_map_extended.c +++ b/boot/zephyr/flash_map_extended.c @@ -14,6 +14,10 @@ #include #include +#if defined(CONFIG_FLASH_RUNTIME_SOURCES) +#include +#endif + #include "bootutil/bootutil_log.h" BOOT_LOG_MODULE_DECLARE(mcuboot); diff --git a/samples/runtime-source/zephyr/README.md b/samples/runtime-source/zephyr/README.md new file mode 100644 index 000000000..825858160 --- /dev/null +++ b/samples/runtime-source/zephyr/README.md @@ -0,0 +1,56 @@ +# Runtime chosen image sample application + +This sample demonstrates how to use a non flash storage to retrieve the image +being booted. It was tested on a FRDM K64F. Both slots are used to store two +different images. The image to be booted is selected based on a button press. + +## Build + +Build mcuboot. First, ensure ZEPHYR_SDK_INSTALL_DIR is defined. From the +mcuboot directory, run the following commands: + +``` + source /zephyr-env.sh + + west build -p -b frdm_k64f boot/zephyr/ -- -DBUILD_RUNTIME_SOURCE_SAMPLE=1 \ + -DEXTRA_CONF_FILE="../../samples/runtime-source/zephyr/sample.conf" + -DEXTRA_DTC_OVERLAY_FILE=../../samples/runtime-source/zephyr/boards/frdm_k64f.overlay + + west build -t flash +``` + +Then, build the sample application to be loaded. We need to build it twice, one +for each slot. From the sample +app directory (mcuboot/samples/non-flash-source/zephyr/app), run: + +``` + west build -p -b frdm_k64f . + west flash +``` + +Then change the overlay file to use the second slot. For instance, open +`boards/frdm_k64f.overlay` and change the line: + +``` + zephyr,code-partition = &slot0_partition; + +``` + +to: + +``` + zephyr,code-partition = &slot1_partition; +``` + +And build and flash again: + +``` + west build -b frdm_k64f . + west flash +``` + +## Run + +Open a serial terminal to see the output and reset the board. It shall boot the +image on slot0 by default. By keeping the SW2 button pressed during reset, the +bootloader will randomly select the image to be booted. diff --git a/samples/runtime-source/zephyr/app/CMakeLists.txt b/samples/runtime-source/zephyr/app/CMakeLists.txt new file mode 100644 index 000000000..bb60128f3 --- /dev/null +++ b/samples/runtime-source/zephyr/app/CMakeLists.txt @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(non_flash_backend_app) + +if (NOT DEFINED FROM_WHO) + set(FROM_WHO Zephyr) +endif() + +target_compile_definitions(app PRIVATE "-DMCUBOOT_HELLO_WORLD_FROM=\"${FROM_WHO}\"") + +target_sources(app PRIVATE src/main.c) diff --git a/samples/runtime-source/zephyr/app/boards/frdm_k64f.overlay b/samples/runtime-source/zephyr/app/boards/frdm_k64f.overlay new file mode 100644 index 000000000..8b642c6b6 --- /dev/null +++ b/samples/runtime-source/zephyr/app/boards/frdm_k64f.overlay @@ -0,0 +1,5 @@ +/ { + chosen { + zephyr,code-partition = &slot0_partition; + }; +}; diff --git a/samples/runtime-source/zephyr/app/prj.conf b/samples/runtime-source/zephyr/app/prj.conf new file mode 100644 index 000000000..bf0ea6a28 --- /dev/null +++ b/samples/runtime-source/zephyr/app/prj.conf @@ -0,0 +1,3 @@ +CONFIG_BOOTLOADER_MCUBOOT=y + +CONFIG_MCUBOOT_SIGNATURE_KEY_FILE="./bootloader/mcuboot/root-rsa-2048.pem" diff --git a/samples/runtime-source/zephyr/app/src/main.c b/samples/runtime-source/zephyr/app/src/main.c new file mode 100644 index 000000000..a3ebbdca3 --- /dev/null +++ b/samples/runtime-source/zephyr/app/src/main.c @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2017 Linaro, Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +int main(void) +{ + printk("Hello World from %s on %s, slot %s!\n", + MCUBOOT_HELLO_WORLD_FROM, CONFIG_BOARD, + DT_PROP(DT_CHOSEN(zephyr_code_partition), label)); +} diff --git a/samples/runtime-source/zephyr/flash_map_dispatcher.c b/samples/runtime-source/zephyr/flash_map_dispatcher.c new file mode 100644 index 000000000..63e1feb88 --- /dev/null +++ b/samples/runtime-source/zephyr/flash_map_dispatcher.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#define SW1_NODE DT_ALIAS(sw1) +#if DT_NODE_HAS_STATUS(SW1_NODE, okay) +static struct gpio_dt_spec sw1_spec = GPIO_DT_SPEC_GET(SW1_NODE, gpios); +#endif + +static int curr_idx = -1; + +static uint8_t known_ids[] = { + FIXED_PARTITION_ID(slot0_partition), + FIXED_PARTITION_ID(slot1_partition), +}; + +bool +flash_map_id_get_next(uint8_t *id, bool reset) +{ + if (reset) { + curr_idx = 0; +#if DT_NODE_HAS_STATUS(SW1_NODE, okay) + if (gpio_pin_configure_dt(&sw1_spec, GPIO_INPUT) == 0) { + if (gpio_pin_get_dt(&sw1_spec) == 1) { + curr_idx = sys_rand8_get() % ARRAY_SIZE(known_ids); + printk("Booting from curr_idx = %d\n", curr_idx); + } + } +#endif + } else { + curr_idx++; + } + + if (curr_idx >= ARRAY_SIZE(known_ids)) { + return false; + } + + *id = known_ids[curr_idx]; + + return true; +} + +bool +flash_map_id_get_current(uint8_t *id) +{ + if (curr_idx == -1 || curr_idx >= ARRAY_SIZE(known_ids)) { + return false; + } + + *id = known_ids[curr_idx]; + + return true; +} diff --git a/samples/runtime-source/zephyr/sample.conf b/samples/runtime-source/zephyr/sample.conf new file mode 100644 index 000000000..3a6b9819c --- /dev/null +++ b/samples/runtime-source/zephyr/sample.conf @@ -0,0 +1,4 @@ +CONFIG_FLASH_RUNTIME_SOURCES=y +CONFIG_BOOT_SIGNATURE_TYPE_RSA=y +CONFIG_TEST_RANDOM_GENERATOR=y +CONFIG_ENTROPY_GENERATOR=y