From 99e1ebdafdad01f2d5553668c2322ade6ddfe451 Mon Sep 17 00:00:00 2001 From: Mathijs Meulendijks Date: Thu, 3 Oct 2024 09:52:19 +0200 Subject: [PATCH] dfu: Add custom device update Adds a custom device update option to the DFU subsystem Signed-off-by: Mathijs Meulendijks --- doc/nrf/libraries/dfu/dfu_target.rst | 9 +++ include/dfu/dfu_target.h | 4 +- include/dfu/dfu_target_custom.h | 92 ++++++++++++++++++++++++++ subsys/dfu/dfu_target/Kconfig | 6 ++ subsys/dfu/dfu_target/src/dfu_target.c | 14 ++++ 5 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 include/dfu/dfu_target_custom.h diff --git a/doc/nrf/libraries/dfu/dfu_target.rst b/doc/nrf/libraries/dfu/dfu_target.rst index 3500445e2fb1..7fd0064bc0b0 100644 --- a/doc/nrf/libraries/dfu/dfu_target.rst +++ b/doc/nrf/libraries/dfu/dfu_target.rst @@ -49,6 +49,7 @@ The DFU target library supports the following types of firmware upgrades: * Modem delta upgrades * Full modem firmware upgrades * SUIT-style upgrades +* Custom upgrades MCUboot-style upgrades ---------------------- @@ -167,6 +168,13 @@ When all image data transfers are completed, the application using the DFU targe The application must schedule the upgrade of all images at once using the :c:func:`dfu_target_schedule_update` function. During this operation, the manifests stored in the ``dfu_partition`` partition will be processed. +Custom upgrades +------------------- + +This firmware upgrade supports custom updates for external peripherals or other custom firmware. +To use this feature, the application must implement the custom upgrade logic by applying the functions defined in the :file:`include/dfu/dfu_target_custom.h` file. + + Configuration ************* @@ -193,6 +201,7 @@ You can disable support for specific DFU targets using the following options: * :kconfig:option:`CONFIG_DFU_TARGET_MCUBOOT` * :kconfig:option:`CONFIG_DFU_TARGET_MODEM_DELTA` * :kconfig:option:`CONFIG_DFU_TARGET_FULL_MODEM` +* :kconfig:option:`CONFIG_DFU_TARGET_CUSTOM` Maintaining writing progress after reboot ========================================= diff --git a/include/dfu/dfu_target.h b/include/dfu/dfu_target.h index 0dd77bd1a2a9..8b71b99e997d 100644 --- a/include/dfu/dfu_target.h +++ b/include/dfu/dfu_target.h @@ -38,6 +38,8 @@ enum dfu_target_image_type { DFU_TARGET_IMAGE_TYPE_SMP = 8, /** SUIT Envelope */ DFU_TARGET_IMAGE_TYPE_SUIT = 16, + /** Custom update implementation, e.g. for external MCU */ + DFU_TARGET_IMAGE_TYPE_CUSTOM = 32, /** Any application image type */ DFU_TARGET_IMAGE_TYPE_ANY_APPLICATION = DFU_TARGET_IMAGE_TYPE_MCUBOOT, /** Any modem image */ @@ -46,7 +48,7 @@ enum dfu_target_image_type { /** Any DFU image type */ DFU_TARGET_IMAGE_TYPE_ANY = (DFU_TARGET_IMAGE_TYPE_MCUBOOT | DFU_TARGET_IMAGE_TYPE_MODEM_DELTA | - DFU_TARGET_IMAGE_TYPE_FULL_MODEM), + DFU_TARGET_IMAGE_TYPE_FULL_MODEM | DFU_TARGET_IMAGE_TYPE_CUSTOM), }; enum dfu_target_evt_id { diff --git a/include/dfu/dfu_target_custom.h b/include/dfu/dfu_target_custom.h new file mode 100644 index 000000000000..fa1677322da8 --- /dev/null +++ b/include/dfu/dfu_target_custom.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/** + * @file dfu_target_custom.h + * @defgroup dfu_target_custom Custom DFU Target + * @{ + * @brief Custom DFU (Device Firmware Update) target implementation. + * + * This file contains the function declarations for a custom DFU target implementation. + * It provides function prototypess for identifying, initializing, writing, and finalizing a custom + * firmware update process. + */ + +#ifndef DFU_TARGET_CUSTOM_H__ +#define DFU_TARGET_CUSTOM_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +/** + * @brief Identifies if the provided buffer contains a custom firmware image. + * + * @param[in] buf Pointer to the buffer containing the potential firmware image. + * @retval true if the buffer contains a valid custom firmware image, false otherwise. + */ +bool dfu_target_custom_identify(const void *const buf); + +/** + * @brief Initializes the custom DFU target. + * + * @param[in] file_size Size of the firmware file to be written. + * @param[in] img_num Image number for multi-image DFU. + * @param[in] cb Callback function to be called during the DFU process. + * @retval 0 on success, negative errno code on failure. + */ +int dfu_target_custom_init(size_t file_size, int img_num, dfu_target_callback_t cb); + +/** + * @brief Gets the current write offset for the custom DFU target. + * + * @param[out] offset Pointer to store the current write offset. + * @retval 0 on success, negative errno code on failure. + */ +int dfu_target_custom_offset_get(size_t *offset); + +/** + * @brief Writes data to the custom DFU target. + * + * @param[in] buf Pointer to the buffer containing the data to be written. + * @param[in] len Length of the data to be written. + * @retval 0 on success, negative errno code on failure. + */ +int dfu_target_custom_write(const void *const buf, size_t len); + +/** + * @brief Releases resources and finalizes the custom DFU process if successful. + * + * @param[in] successful true if the DFU process was successful, false otherwise. + * @retval 0 on success, negative errno code on failure. + */ +int dfu_target_custom_done(bool successful); + +/** + * @brief Schedules an update for the custom DFU target. + * + * @param[in] img_num Image number for multi-image DFU. + * @retval 0 on success, negative errno code on failure. + */ +int dfu_target_custom_schedule_update(int img_num); + +/** + * @brief Release resources and erase the download area. + * + * Cancel any ongoing updates. + * + * @retval 0 on success, negative errno code on failure. + */ +int dfu_target_custom_reset(void); + +#ifdef __cplusplus +} +#endif + +#endif /* DFU_TARGET_SUIT_H__ */ +/**@} */ diff --git a/subsys/dfu/dfu_target/Kconfig b/subsys/dfu/dfu_target/Kconfig index cbdee019e5a5..505a37e59137 100644 --- a/subsys/dfu/dfu_target/Kconfig +++ b/subsys/dfu/dfu_target/Kconfig @@ -153,6 +153,12 @@ config DFU_TARGET_REBOOT_RESET_DELAY_MS endif # DFU_TARGET_SUIT +config DFU_TARGET_CUSTOM + bool "Custom application controlled update support" + default n + help + Enable support for custom updates using DFU target + module=DFU_TARGET module-dep=LOG module-str=Device Firmware Upgrade diff --git a/subsys/dfu/dfu_target/src/dfu_target.c b/subsys/dfu/dfu_target/src/dfu_target.c index 0260396d5699..bf02b4a99c5c 100644 --- a/subsys/dfu/dfu_target/src/dfu_target.c +++ b/subsys/dfu/dfu_target/src/dfu_target.c @@ -38,6 +38,10 @@ DEF_DFU_TARGET(smp); #include "dfu/dfu_target_suit.h" DEF_DFU_TARGET(suit); #endif +#ifdef CONFIG_DFU_TARGET_CUSTOM +#include "dfu/dfu_target_custom.h" +DEF_DFU_TARGET(custom); +#endif #define MIN_SIZE_IDENTIFY_BUF 32 @@ -65,6 +69,11 @@ enum dfu_target_image_type dfu_target_img_type(const void *const buf, size_t len if (dfu_target_full_modem_identify(buf)) { return DFU_TARGET_IMAGE_TYPE_FULL_MODEM; } +#endif +#ifdef CONFIG_DFU_TARGET_CUSTOM + if (dfu_target_custom_identify(buf)) { + return DFU_TARGET_IMAGE_TYPE_CUSTOM; + } #endif LOG_ERR("No supported image type found"); return DFU_TARGET_IMAGE_TYPE_NONE; @@ -113,6 +122,11 @@ int dfu_target_init(int img_type, int img_num, size_t file_size, dfu_target_call new_target = &dfu_target_suit; } #endif +#ifdef CONFIG_DFU_TARGET_CUSTOM + if (img_type == DFU_TARGET_IMAGE_TYPE_CUSTOM) { + new_target = &dfu_target_custom; + } +#endif if (new_target == NULL) { LOG_ERR("Unknown image type");