From ed6460b81581a9fb3cf142cfcf8f8db1d8aaedbf Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Tue, 9 Apr 2024 10:49:14 +0200 Subject: [PATCH] mynewt: Add single_loader support There is existing functionality for Zephyr where mcuboot works with single slot (no swap) and image can be updated via boot_serial. To have same functionality in mynewet single_loader.c file is copied from zephyr tree and 2 pkg.yml files are modified to utilize new file when BOOTUTIL_SINGLE_APPLICATION_SLOT is defined Signed-off-by: Jerzy Kasenberg --- boot/bootutil/pkg.yml | 3 + boot/mynewt/pkg.yml | 3 + boot/mynewt/src/single_loader.c | 136 ++++++++++++++++++++++++++++++++ 3 files changed, 142 insertions(+) create mode 100644 boot/mynewt/src/single_loader.c diff --git a/boot/bootutil/pkg.yml b/boot/bootutil/pkg.yml index 531d6a26..c4d044b8 100644 --- a/boot/bootutil/pkg.yml +++ b/boot/bootutil/pkg.yml @@ -41,6 +41,9 @@ pkg.deps: - "@apache-mynewt-core/sys/defs" - "@mcuboot/boot/mynewt/flash_map_backend" +pkg.ign_files.BOOTUTIL_SINGLE_APPLICATION_SLOT: + - "loader.c" + pkg.deps.BOOTUTIL_USE_MBED_TLS: - "@apache-mynewt-core/crypto/mbedtls" diff --git a/boot/mynewt/pkg.yml b/boot/mynewt/pkg.yml index fe12d096..7e91c66b 100644 --- a/boot/mynewt/pkg.yml +++ b/boot/mynewt/pkg.yml @@ -35,6 +35,9 @@ pkg.deps: - "@apache-mynewt-core/kernel/os" - "@apache-mynewt-core/sys/log/stub" +pkg.ign_files.!BOOTUTIL_SINGLE_APPLICATION_SLOT: + - "single_loader.c" + pkg.deps.BOOTUTIL_NO_LOGGING: - "@apache-mynewt-core/sys/console/stub" diff --git a/boot/mynewt/src/single_loader.c b/boot/mynewt/src/single_loader.c new file mode 100644 index 00000000..564d7489 --- /dev/null +++ b/boot/mynewt/src/single_loader.c @@ -0,0 +1,136 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2020 Nordic Semiconductor ASA + * Copyright (c) 2020 Arm Limited + */ + +#include +#include "bootutil/image.h" +#include "../../../bootutil/src/bootutil_priv.h" +#include "bootutil/bootutil_log.h" +#include "bootutil/bootutil_public.h" +#include "bootutil/fault_injection_hardening.h" + +#include "mcuboot_config/mcuboot_config.h" + +BOOT_LOG_MODULE_DECLARE(mcuboot); + +/* Variables passed outside of unit via poiters. */ +static const struct flash_area *_fa_p; +static struct image_header _hdr = { 0 }; + +#if defined(MCUBOOT_VALIDATE_PRIMARY_SLOT) || defined(MCUBOOT_VALIDATE_PRIMARY_SLOT_ONCE) +/** + * Validate hash of a primary boot image. + * + * @param[in] fa_p flash area pointer + * @param[in] hdr boot image header pointer + * + * @return FIH_SUCCESS on success, error code otherwise + */ +fih_ret +boot_image_validate(const struct flash_area *fa_p, + struct image_header *hdr) +{ + static uint8_t tmpbuf[BOOT_TMPBUF_SZ]; + FIH_DECLARE(fih_rc, FIH_FAILURE); + + /* NOTE: The first argument to boot_image_validate, for enc_state pointer, + * is allowed to be NULL only because the single image loader compiles + * with BOOT_IMAGE_NUMBER == 1, which excludes the code that uses + * the pointer from compilation. + */ + /* Validate hash */ + if (IS_ENCRYPTED(hdr)) + { + /* Clear the encrypted flag we didn't supply a key + * This flag could be set if there was a decryption in place + * was performed. We will try to validate the image, and if still + * encrypted the validation will fail, and go in panic mode + */ + hdr->ih_flags &= ~(ENCRYPTIONFLAGS); + } + FIH_CALL(bootutil_img_validate, fih_rc, NULL, 0, hdr, fa_p, tmpbuf, + BOOT_TMPBUF_SZ, NULL, 0, NULL); + + FIH_RET(fih_rc); +} +#endif /* MCUBOOT_VALIDATE_PRIMARY_SLOT || MCUBOOT_VALIDATE_PRIMARY_SLOT_ONCE*/ + +#if defined(MCUBOOT_VALIDATE_PRIMARY_SLOT_ONCE) +inline static fih_ret +boot_image_validate_once(const struct flash_area *fa_p, + struct image_header *hdr) +{ + static struct boot_swap_state state; + int rc; + FIH_DECLARE(fih_rc, FIH_FAILURE); + + memset(&state, 0, sizeof(struct boot_swap_state)); + rc = boot_read_swap_state(fa_p, &state); + if (rc != 0) + FIH_RET(FIH_FAILURE); + if (state.magic != BOOT_MAGIC_GOOD + || state.image_ok != BOOT_FLAG_SET) { + /* At least validate the image once */ + FIH_CALL(boot_image_validate, fih_rc, fa_p, hdr); + if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { + FIH_RET(FIH_FAILURE); + } + if (state.magic != BOOT_MAGIC_GOOD) { + rc = boot_write_magic(fa_p); + if (rc != 0) + FIH_RET(FIH_FAILURE); + } + rc = boot_write_image_ok(fa_p); + if (rc != 0) + FIH_RET(FIH_FAILURE); + } + FIH_RET(FIH_SUCCESS); +} +#endif + +/** + * Gather information on image and prepare for booting. + * + * @parami[out] rsp Parameters for booting image, on success + * + * @return FIH_SUCCESS on success; nonzero on failure. + */ +fih_ret +boot_go(struct boot_rsp *rsp) +{ + int rc = -1; + FIH_DECLARE(fih_rc, FIH_FAILURE); + + rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(0), &_fa_p); + assert(rc == 0); + + rc = boot_image_load_header(_fa_p, &_hdr); + if (rc != 0) + goto out; + +#ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT + FIH_CALL(boot_image_validate, fih_rc, _fa_p, &_hdr); + if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { + goto out; + } +#elif defined(MCUBOOT_VALIDATE_PRIMARY_SLOT_ONCE) + FIH_CALL(boot_image_validate_once, fih_rc, _fa_p, &_hdr); + if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { + goto out; + } +#else + fih_rc = FIH_SUCCESS; +#endif /* MCUBOOT_VALIDATE_PRIMARY_SLOT */ + + rsp->br_flash_dev_id = flash_area_get_device_id(_fa_p); + rsp->br_image_off = flash_area_get_off(_fa_p); + rsp->br_hdr = &_hdr; + +out: + flash_area_close(_fa_p); + + FIH_RET(fih_rc); +}