From 2df0abfd7006ea2595b1849d6a362a250ecce491 Mon Sep 17 00:00:00 2001
From: Francisco Acosta <fco.ja.ac@gmail.com>
Date: Tue, 9 Oct 2018 15:35:18 +0200
Subject: [PATCH] sys/riotboot: add riotboot_slot module

This module adds some helper function to manage slots
created with a riotboot_hdr header.

Co-authored-by: Kaspar Schleiser <kaspar@schleiser.de>
---
 Makefile.dep                |   4 ++
 sys/include/riotboot/slot.h | 109 ++++++++++++++++++++++++++++++++++++
 sys/riotboot/Makefile       |   4 ++
 sys/riotboot/slot.c         |  86 ++++++++++++++++++++++++++++
 4 files changed, 203 insertions(+)
 create mode 100644 sys/include/riotboot/slot.h
 create mode 100644 sys/riotboot/slot.c

diff --git a/Makefile.dep b/Makefile.dep
index 4a811c91a3..d01275961d 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 0000000000..24d65e32da
--- /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 cd1af2456e..344672d2e2 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 0000000000..09cac62a78
--- /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];
+}
-- 
GitLab