mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
suit/storage/flashwrite: Add riotboot flashwrite storage backend
This commit is contained in:
parent
9ce2ba1c55
commit
a29eaf557f
43
sys/include/suit/storage/flashwrite.h
Normal file
43
sys/include/suit/storage/flashwrite.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Koen Zandberg
|
||||
* 2020 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_suit_storage_flashwrite riotboot flashwrite storage backend
|
||||
* @ingroup sys_suit_storage
|
||||
* @brief SUIT riotboot firmware storage backend
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* @brief riotboot Flashwrite storage backend functions for SUIT manifests
|
||||
* @author Koen Zandberg <koen@bergzand.net>
|
||||
*/
|
||||
|
||||
#ifndef SUIT_STORAGE_FLASHWRITE_H
|
||||
#define SUIT_STORAGE_FLASHWRITE_H
|
||||
|
||||
#include "suit.h"
|
||||
#include "riotboot/flashwrite.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief riotboot flashwrite SUIT storage context
|
||||
*/
|
||||
typedef struct {
|
||||
suit_storage_t storage; /**< parent struct */
|
||||
riotboot_flashwrite_t writer; /**< Riotboot flashwriter */
|
||||
} suit_storage_flashwrite_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SUIT_STORAGE_FLASHWRITE_H */
|
||||
/** @} */
|
216
sys/suit/storage/flashwrite.c
Normal file
216
sys/suit/storage/flashwrite.c
Normal file
@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Koen Zandberg
|
||||
* 2020 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_suit_storage
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief SUIT flashwrite storage module implementation
|
||||
*
|
||||
* @author Koen Zandberg <koen@bergzand.net>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#include "kernel_defines.h"
|
||||
#include "log.h"
|
||||
|
||||
#include "suit.h"
|
||||
#include "suit/storage.h"
|
||||
#include "suit/storage/flashwrite.h"
|
||||
#include "riotboot/flashwrite.h"
|
||||
#include "riotboot/slot.h"
|
||||
|
||||
static inline suit_storage_flashwrite_t *_get_fw(suit_storage_t *storage)
|
||||
{
|
||||
return container_of(storage, suit_storage_flashwrite_t, storage);
|
||||
}
|
||||
|
||||
static int _flashwrite_init(suit_storage_t *storage)
|
||||
{
|
||||
(void)storage;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _flashwrite_start(suit_storage_t *storage,
|
||||
const suit_manifest_t *manifest,
|
||||
size_t len)
|
||||
{
|
||||
(void)manifest;
|
||||
(void)len;
|
||||
suit_storage_flashwrite_t *fw = _get_fw(storage);
|
||||
int target_slot = riotboot_slot_other();
|
||||
|
||||
return riotboot_flashwrite_init(&fw->writer, target_slot);
|
||||
}
|
||||
|
||||
static int _flashwrite_write(suit_storage_t *storage,
|
||||
const suit_manifest_t *manifest,
|
||||
const uint8_t *buf, size_t offset, size_t len)
|
||||
{
|
||||
(void)manifest;
|
||||
suit_storage_flashwrite_t *fw = _get_fw(storage);
|
||||
|
||||
if (offset == 0) {
|
||||
if (len < RIOTBOOT_FLASHWRITE_SKIPLEN) {
|
||||
LOG_WARNING("_suit_flashwrite(): offset==0, len<4. aborting\n");
|
||||
return -1;
|
||||
}
|
||||
offset = RIOTBOOT_FLASHWRITE_SKIPLEN;
|
||||
buf += RIOTBOOT_FLASHWRITE_SKIPLEN;
|
||||
len -= RIOTBOOT_FLASHWRITE_SKIPLEN;
|
||||
}
|
||||
|
||||
if (offset != fw->writer.offset) {
|
||||
LOG_ERROR("Unexpected offset: %u - expected: %u\n", (unsigned)offset,
|
||||
(unsigned)fw->writer.offset);
|
||||
return SUIT_ERR_STORAGE;
|
||||
}
|
||||
|
||||
return riotboot_flashwrite_putbytes(&fw->writer, buf, len, 1);
|
||||
}
|
||||
|
||||
static int _flashwrite_finish(suit_storage_t *storage,
|
||||
const suit_manifest_t *manifest)
|
||||
{
|
||||
(void)manifest;
|
||||
suit_storage_flashwrite_t *fw = _get_fw(storage);
|
||||
|
||||
return riotboot_flashwrite_flush(&fw->writer) <
|
||||
0 ? SUIT_ERR_STORAGE : SUIT_OK;
|
||||
}
|
||||
|
||||
static int _flashwrite_install(suit_storage_t *storage,
|
||||
const suit_manifest_t *manifest)
|
||||
{
|
||||
(void)manifest;
|
||||
suit_storage_flashwrite_t *fw = _get_fw(storage);
|
||||
|
||||
return riotboot_flashwrite_finish(&fw->writer);
|
||||
}
|
||||
|
||||
static int _flashwrite_read(suit_storage_t *storage, uint8_t *buf,
|
||||
size_t offset, size_t len)
|
||||
{
|
||||
(void)storage;
|
||||
|
||||
static const char _prefix[] = "RIOT";
|
||||
static const size_t _prefix_len = sizeof(_prefix) - 1;
|
||||
int target_slot = riotboot_slot_other();
|
||||
size_t slot_size = riotboot_slot_size(target_slot);
|
||||
|
||||
/* Insert the "RIOT" magic number */
|
||||
if (offset < (_prefix_len)) {
|
||||
size_t prefix_to_copy = _prefix_len - offset;
|
||||
memcpy(buf, _prefix + offset, prefix_to_copy);
|
||||
len -= prefix_to_copy;
|
||||
offset = _prefix_len;
|
||||
buf += prefix_to_copy;
|
||||
|
||||
}
|
||||
if (offset + len > slot_size) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t *slot = (uint8_t *)riotboot_slot_get_hdr(target_slot);
|
||||
|
||||
memcpy(buf, slot + offset, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool _flashwrite_has_location(const suit_storage_t *storage,
|
||||
const char *location)
|
||||
{
|
||||
(void)storage;
|
||||
|
||||
/* Firmware matches at zero length string */
|
||||
return (location[0] == '\0');
|
||||
}
|
||||
|
||||
static int _flashwrite_set_active_location(suit_storage_t *storage,
|
||||
const char *location)
|
||||
{
|
||||
(void)storage;
|
||||
(void)location;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool _flashwrite_match_offset(const suit_storage_t *storage,
|
||||
size_t offset)
|
||||
{
|
||||
(void)storage;
|
||||
|
||||
int target_slot = riotboot_slot_other();
|
||||
uintptr_t slot_start = (intptr_t)riotboot_slot_get_hdr(target_slot);
|
||||
|
||||
return (slot_start == (uintptr_t)offset);
|
||||
}
|
||||
|
||||
static int _flashwrite_get_seq_no(const suit_storage_t *storage,
|
||||
uint32_t *seq_no)
|
||||
{
|
||||
(void)storage;
|
||||
uint32_t max_seq_no = 0;
|
||||
bool valid = false;
|
||||
|
||||
for (unsigned i = 0; i < riotboot_slot_numof; i++) {
|
||||
const riotboot_hdr_t *riot_hdr = riotboot_slot_get_hdr(i);
|
||||
if (riotboot_slot_validate(i)) {
|
||||
/* skip slot if metadata broken */
|
||||
continue;
|
||||
}
|
||||
if (!valid || riot_hdr->version > max_seq_no) {
|
||||
max_seq_no = riot_hdr->version;
|
||||
valid = true;
|
||||
}
|
||||
}
|
||||
if (valid) {
|
||||
*seq_no = max_seq_no;
|
||||
return SUIT_OK;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int _flashwrite_set_seq_no(suit_storage_t *storage,
|
||||
uint32_t seq_no)
|
||||
{
|
||||
(void)storage;
|
||||
int target_slot = riotboot_slot_other();
|
||||
const riotboot_hdr_t *hdr = riotboot_slot_get_hdr(target_slot);
|
||||
|
||||
if (hdr->version == seq_no) {
|
||||
return SUIT_OK;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static const suit_storage_driver_t suit_storage_flashwrite_driver = {
|
||||
.init = _flashwrite_init,
|
||||
.start = _flashwrite_start,
|
||||
.write = _flashwrite_write,
|
||||
.finish = _flashwrite_finish,
|
||||
.read = _flashwrite_read,
|
||||
.install = _flashwrite_install,
|
||||
.has_location = _flashwrite_has_location,
|
||||
.set_active_location = _flashwrite_set_active_location,
|
||||
.match_offset = _flashwrite_match_offset,
|
||||
.get_seq_no = _flashwrite_get_seq_no,
|
||||
.set_seq_no = _flashwrite_set_seq_no,
|
||||
.separator = '\0',
|
||||
};
|
||||
|
||||
suit_storage_flashwrite_t suit_storage_flashwrite = {
|
||||
.storage = {
|
||||
.driver = &suit_storage_flashwrite_driver,
|
||||
},
|
||||
};
|
Loading…
Reference in New Issue
Block a user