From 00adbd69f6ed3fa927a373bfbb1bfde0bdc78f9c Mon Sep 17 00:00:00 2001
From: Francisco Acosta <fco.ja.ac@gmail.com>
Date: Tue, 9 Oct 2018 15:28:25 +0200
Subject: [PATCH] sys: add riotboot_hdr submodule

riotboot_hdr enables to partition the internal flash memory
into "slots", each one with a header providing information
about the partition. The concept for now is limited to
firmware partitions, which are recognised by the riotboot
bootloader. In the future the concept might be extended to
represent other content.

Co-authored-by: Kaspar Schleiser <kaspar@schleiser.de>
---
 Makefile.dep                   |  5 ++
 makefiles/pseudomodules.inc.mk |  1 +
 sys/Makefile                   |  1 -
 sys/include/riotboot/hdr.h     | 89 ++++++++++++++++++++++++++++++++++
 sys/riotboot/Makefile          |  3 ++
 sys/riotboot/hdr.c             | 68 ++++++++++++++++++++++++++
 6 files changed, 166 insertions(+), 1 deletion(-)
 create mode 100644 sys/include/riotboot/hdr.h
 create mode 100644 sys/riotboot/Makefile
 create mode 100644 sys/riotboot/hdr.c

diff --git a/Makefile.dep b/Makefile.dep
index 9b01c11117..639ec08596 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 f27ea28fb4..c737ba2981 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 bab6d94783..27b9b5396a 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 0000000000..f4300657c7
--- /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 0000000000..cd1af2456e
--- /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 0000000000..53493051a1
--- /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));
+}
-- 
GitLab