diff --git a/Makefile.dep b/Makefile.dep index 9b01c11117a1443d3d76a90abc273a295deaccd4..639ec08596f14b3c3a71e388104a615ee9b54d2b 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -791,6 +791,11 @@ ifneq (,$(filter uuid,$(USEMODULE))) USEMODULE += random endif +ifneq (,$(filter riotboot_hdr, $(USEMODULE))) + USEMODULE += checksum + USEMODULE += riotboot +endif + # Enable periph_gpio when periph_gpio_irq is enabled ifneq (,$(filter periph_gpio_irq,$(USEMODULE))) FEATURES_REQUIRED += periph_gpio diff --git a/makefiles/pseudomodules.inc.mk b/makefiles/pseudomodules.inc.mk index f27ea28fb4c1fe19b8125ff8b90f8adbfe9fc7f3..c737ba29813c2c6798f0c0fca29337738f8eb2f9 100644 --- a/makefiles/pseudomodules.inc.mk +++ b/makefiles/pseudomodules.inc.mk @@ -54,6 +54,7 @@ PSEUDOMODULES += pktqueue PSEUDOMODULES += printf_float PSEUDOMODULES += prng PSEUDOMODULES += prng_% +PSEUDOMODULES += riotboot_% PSEUDOMODULES += saul_adc PSEUDOMODULES += saul_default PSEUDOMODULES += saul_gpio diff --git a/sys/Makefile b/sys/Makefile index bab6d947837d8e43f9d67dfab3059edd5fcc882e..27b9b5396a761d586305df33406e949e3bb5bcdf 100644 --- a/sys/Makefile +++ b/sys/Makefile @@ -140,7 +140,6 @@ ifneq (,$(filter cord_ep,$(USEMODULE))) DIRS += net/application_layer/cord/ep endif - DIRS += $(dir $(wildcard $(addsuffix /Makefile, $(USEMODULE)))) include $(RIOTBASE)/Makefile.base diff --git a/sys/include/riotboot/hdr.h b/sys/include/riotboot/hdr.h new file mode 100644 index 0000000000000000000000000000000000000000..f4300657c7451f078bbfc1f7c31a0f1141c01363 --- /dev/null +++ b/sys/include/riotboot/hdr.h @@ -0,0 +1,89 @@ +/* + * 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_hdr RIOT header helpers and tools + * @ingroup sys + * @{ + * + * The header contains + * + * - "RIOT" as magic number + * - the application version + * - the address where the RIOT firmware is found + * - the checksum of the three previous fields + * + * @file + * @brief RIOT "partition" header and tools + * + * @author Kaspar Schleiser <kaspar@schleiser.de> + * @author Francisco Acosta <francisco.acosta@inria.fr> + * + * @} + */ + +#ifndef RIOTBOOT_HDR_H +#define RIOTBOOT_HDR_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> + +/** + * @brief Magic number for riotboot_hdr + * + */ +#define RIOTBOOT_MAGIC 0x544f4952 /* "RIOT" */ + +/** + * @brief Structure to store image header - All members are little endian + * @{ + */ +typedef struct { + uint32_t magic_number; /**< Header magic number (always "RIOT") */ + uint32_t version; /**< Integer representing the partition version */ + uint32_t start_addr; /**< Address after the allocated space for the header */ + uint32_t chksum; /**< Checksum of riotboot_hdr */ +} riotboot_hdr_t; +/** @} */ + +/** + * @brief Print formatted riotboot_hdr_t to STDIO + * + * @param[in] riotboot_hdr ptr to image header + * + */ +void riotboot_hdr_print(const riotboot_hdr_t *riotboot_hdr); + +/** + * @brief Validate image header + * + * @param[in] riotboot_hdr ptr to image header + * + * @returns 0 if OK + * @returns -1 if not OK + */ +int riotboot_hdr_validate(const riotboot_hdr_t *riotboot_hdr); + +/** + * @brief Calculate header checksum + * + * @param[in] riotboot_hdr ptr to image header + * + * @returns the checksum of the given riotboot_hdr + */ +uint32_t riotboot_hdr_checksum(const riotboot_hdr_t *riotboot_hdr); + +#ifdef __cplusplus +} +#endif + +#endif /* RIOTBOOT_HDR_H */ diff --git a/sys/riotboot/Makefile b/sys/riotboot/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..cd1af2456e0554b9f34f996712ad3fa356b0d770 --- /dev/null +++ b/sys/riotboot/Makefile @@ -0,0 +1,3 @@ +SUBMODULES := 1 + +include $(RIOTBASE)/Makefile.base diff --git a/sys/riotboot/hdr.c b/sys/riotboot/hdr.c new file mode 100644 index 0000000000000000000000000000000000000000..53493051a108a73e7f47085334743ca2f5c30336 --- /dev/null +++ b/sys/riotboot/hdr.c @@ -0,0 +1,68 @@ +/* + * 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_hdr + * @{ + * + * @file + * @brief RIOT header helpers and tools + * + * @author Kaspar Schleiser <kaspar@schleiser.de> + * @author Francisco Acosta <francisco.acosta@inria.fr> + * + * @} + */ + +#include <string.h> +#include <stddef.h> +#include <stdio.h> + +#ifdef RIOT_VERSION +#include "log.h" +#else +#define LOG_INFO(...) printf(__VA_ARGS__) +#endif + +#include "riotboot/hdr.h" +#include "checksum/fletcher32.h" +#include "byteorder.h" + +#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ +# error "This code is implementented in a way that it will only work for little-endian systems!" +#endif + +void riotboot_hdr_print(const riotboot_hdr_t *riotboot_hdr) +{ + printf("Image magic_number: 0x%08x\n", (unsigned)riotboot_hdr->magic_number); + printf("Image Version: 0x%08x\n", (unsigned)riotboot_hdr->version); + printf("Image start address: 0x%08x\n", (unsigned)riotboot_hdr->start_addr); + printf("Header chksum: 0x%08x\n", (unsigned)riotboot_hdr->chksum); + printf("\n"); +} + +int riotboot_hdr_validate(const riotboot_hdr_t *riotboot_hdr) +{ + if (riotboot_hdr->magic_number != RIOTBOOT_MAGIC) { + LOG_INFO("%s: riotboot_hdr magic number invalid\n", __func__); + return -1; + } + + int res = riotboot_hdr_checksum(riotboot_hdr) == riotboot_hdr->chksum ? 0 : -1; + if (res) { + LOG_INFO("%s: riotboot_hdr checksum invalid\n", __func__); + } + + return res; +} + +uint32_t riotboot_hdr_checksum(const riotboot_hdr_t *riotboot_hdr) +{ + return fletcher32((uint16_t *)riotboot_hdr, offsetof(riotboot_hdr_t, chksum) / sizeof(uint16_t)); +}