diff --git a/Makefile.dep b/Makefile.dep index 4a811c91a31f18a12ad8e4b1a0ebde71a7b62156..d01275961d6914a2efc784570db2302b98a2aca8 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -808,6 +808,10 @@ ifneq (,$(filter periph_gpio_irq,$(USEMODULE))) FEATURES_REQUIRED += periph_gpio endif +ifneq (,$(filter riotboot_slot, $(USEMODULE))) + USEMODULE += riotboot_hdr +endif + # always select gpio (until explicit dependencies are sorted out) FEATURES_OPTIONAL += periph_gpio diff --git a/sys/include/riotboot/slot.h b/sys/include/riotboot/slot.h new file mode 100644 index 0000000000000000000000000000000000000000..24d65e32da174ce45b1232cf117bebe0c4745777 --- /dev/null +++ b/sys/include/riotboot/slot.h @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2018 Kaspar Schleiser <kaspar@schleiser.de> + * Inria + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @defgroup sys_riotboot_slot Helpers to manipulate partitions (slots) + * on internal flash + * @ingroup sys + * @{ + * + * @file + * @brief Slot management tools + * + * @author Kaspar Schleiser <kaspar@schleiser.de> + * @author Francisco Acosta <francisco.acosta@inria.fr> + * + * @} + */ + +#ifndef RIOTBOOT_SLOT_H +#define RIOTBOOT_SLOT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "riotboot/hdr.h" + +/** + * @brief Get currently running image slot + * + * @returns nr of currently active slot + */ +int riotboot_slot_current(void); + +/** + * @brief Get jump-to address of image slot + * + * @param[in] slot slot nr to work on + * + * @returns address of first byte of @p slot + */ +uint32_t riotboot_slot_get_image_startaddr(unsigned slot); + +/** + * @brief Boot into image in slot @p slot + * + * @param[in] slot slot nr to jump to + */ +void riotboot_slot_jump(unsigned slot); + +/** + * @brief Get header from a given flash slot + * + * @param[in] slot slot nr to work on + * + * @returns header of image slot nr @p slot + */ +const riotboot_hdr_t *riotboot_slot_get_hdr(unsigned slot); + +/** + * @brief Validate slot + * + * @param[in] slot slot nr to work on + * + * @returns 0 if ok. + */ +static inline int riotboot_slot_validate(unsigned slot) +{ + return riotboot_hdr_validate(riotboot_slot_get_hdr(slot)); +} + +/** + * @brief Print formatted slot header to STDIO + * + * @param[in] slot slot nr to work on + * + */ +static inline void riotboot_slot_print_hdr(unsigned slot) +{ + riotboot_hdr_print(riotboot_slot_get_hdr(slot)); +} + +/** + * @brief Dump the addresses of all configured slots + * + */ +void riotboot_slot_dump_addrs(void); + +/** + * @brief Number of configured firmware slots (incl. bootloader slot) + */ +extern const unsigned riotboot_slot_numof; + +/** + * @brief Storage for header pointers of the configured slots + */ +extern const riotboot_hdr_t * const riotboot_slots[]; + +#ifdef __cplusplus +} +#endif + +#endif /* RIOTBOOT_SLOT_H */ diff --git a/sys/riotboot/Makefile b/sys/riotboot/Makefile index cd1af2456e0554b9f34f996712ad3fa356b0d770..344672d2e216db7b2213058ff46de27039e661d0 100644 --- a/sys/riotboot/Makefile +++ b/sys/riotboot/Makefile @@ -1,3 +1,7 @@ SUBMODULES := 1 +ifneq (,$(filter riotboot_slot,$(USEMODULE))) + CFLAGS += -DSLOT0_OFFSET=$(SLOT0_OFFSET) +endif + include $(RIOTBASE)/Makefile.base diff --git a/sys/riotboot/slot.c b/sys/riotboot/slot.c new file mode 100644 index 0000000000000000000000000000000000000000..09cac62a789bf28990d9029874546539dc65bee8 --- /dev/null +++ b/sys/riotboot/slot.c @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2017 Kaspar Schleiser <kaspar@schleiser.de> + * Inria + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup sys_riotboot_slot + * @{ + * + * @file + * @brief Slot management functions + * + * @author Kaspar Schleiser <kaspar@schleiser.de> + * @author Francisco Acosta <francisco.acosta@inria.fr> + * + * @} + */ +#include <string.h> + +#include "cpu.h" +#include "riotboot/slot.h" +#include "riotboot/hdr.h" + +/* + * Store the start addresses of each slot. + * Take into account that CPU_FLASH_BASE represents the starting + * address of the bootloader, thus the header is located after the + * space reserved to the bootloader. + */ +const riotboot_hdr_t * const riotboot_slots[] = { + (riotboot_hdr_t*)(CPU_FLASH_BASE + SLOT0_OFFSET), /* First slot address -> firmware image */ +}; + +/* Calculate the number of slots */ +const unsigned riotboot_slot_numof = sizeof(riotboot_slots) / sizeof(riotboot_hdr_t*); + +static void _riotboot_slot_jump_to_image(const riotboot_hdr_t *hdr) +{ + cpu_jump_to_image(hdr->start_addr); +} + +int riotboot_slot_current(void) +{ + uint32_t base_addr = cpu_get_image_baseaddr(); + + for (unsigned i = 0; i < riotboot_slot_numof; i++) { + const riotboot_hdr_t *hdr = riotboot_slot_get_hdr(i); + if (base_addr == hdr->start_addr) { + return i; + } + } + + return -1; +} + +void riotboot_slot_jump(unsigned slot) +{ + _riotboot_slot_jump_to_image(riotboot_slot_get_hdr(slot)); +} + +uint32_t riotboot_slot_get_image_startaddr(unsigned slot) +{ + return riotboot_slot_get_hdr(slot)->start_addr; +} + +void riotboot_slot_dump_addrs(void) +{ + for (unsigned slot = 0; slot < riotboot_slot_numof; slot++) { + const riotboot_hdr_t *hdr = riotboot_slot_get_hdr(slot); + + printf("slot %u: metadata: %p image: 0x%08" PRIx32 "\n", slot, + hdr, + hdr->start_addr); + } +} + +const riotboot_hdr_t *riotboot_slot_get_hdr(unsigned slot) +{ + assert(slot < riotboot_slot_numof); + + return riotboot_slots[slot]; +}