suit/storage/ram: Introduce RAM storage backend for SUIT
This commit is contained in:
parent
7742750abd
commit
9ce2ba1c55
89
sys/include/suit/storage/ram.h
Normal file
89
sys/include/suit/storage/ram.h
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* 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_ram ram storage backend
|
||||||
|
* @ingroup sys_suit_storage
|
||||||
|
* @brief RAM blob SUIT payload storage backends
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @brief RAM-based storage backend for SUIT OTA updates
|
||||||
|
* @author Koen Zandberg <koen@bergzand.net>
|
||||||
|
*
|
||||||
|
* This module implements a RAM-backed storage interface for SUIT. The main
|
||||||
|
* purpose is mock testing the SUIT implementation, however the interface could
|
||||||
|
* also be used for to target backup ram storage by changing @ref
|
||||||
|
* CONFIG_SUIT_STORAGE_RAM_SIZE to store it in backup ram.
|
||||||
|
*
|
||||||
|
* The module uses a .ram.### structure where the number indicates the index of
|
||||||
|
* the memory region being targeted.
|
||||||
|
*
|
||||||
|
* @warning The install function is implemented as a noop. There is no
|
||||||
|
* distinction between valid content and not yet invalidated content.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SUIT_STORAGE_RAM_H
|
||||||
|
#define SUIT_STORAGE_RAM_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "suit.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Size of each memory region
|
||||||
|
*/
|
||||||
|
#ifndef CONFIG_SUIT_STORAGE_RAM_SIZE
|
||||||
|
#define CONFIG_SUIT_STORAGE_RAM_SIZE (64U)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Number of allocated regions
|
||||||
|
*/
|
||||||
|
#ifndef CONFIG_SUIT_STORAGE_RAM_REGIONS
|
||||||
|
#define CONFIG_SUIT_STORAGE_RAM_REGIONS (2U)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Extra attributes for allocating the RAM struct
|
||||||
|
*/
|
||||||
|
#ifndef CONFIG_SUIT_STORAGE_RAM_ATTR
|
||||||
|
#define CONFIG_SUIT_STORAGE_RAM_ATTR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Single in-memory storage region
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
size_t occupied; /**< Region space filled */
|
||||||
|
uint8_t mem[CONFIG_SUIT_STORAGE_RAM_SIZE]; /**< RAM area */
|
||||||
|
} suit_storage_ram_region_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief memory storage state
|
||||||
|
*/
|
||||||
|
typedef struct CONFIG_SUIT_STORAGE_RAM_ATTR {
|
||||||
|
suit_storage_t storage; /**< parent struct */
|
||||||
|
/**
|
||||||
|
* @brief ram storage regions
|
||||||
|
*/
|
||||||
|
suit_storage_ram_region_t regions[CONFIG_SUIT_STORAGE_RAM_REGIONS];
|
||||||
|
size_t active_region; /**< Active region to write to */
|
||||||
|
uint32_t sequence_no; /**< Ephemeral sequence number */
|
||||||
|
} suit_storage_ram_t;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* SUIT_STORAGE_RAM_H */
|
||||||
|
/** @} */
|
||||||
231
sys/suit/storage/ram.c
Normal file
231
sys/suit/storage/ram.c
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
/*
|
||||||
|
* 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 ram storage module implementation
|
||||||
|
*
|
||||||
|
* @author Koen Zandberg <koen@bergzand.net>
|
||||||
|
*
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
#include <string.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#include "fmt.h"
|
||||||
|
#include "kernel_defines.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
#include "suit.h"
|
||||||
|
#include "suit/storage.h"
|
||||||
|
#include "suit/storage/ram.h"
|
||||||
|
|
||||||
|
static inline suit_storage_ram_t *_get_ram(suit_storage_t *storage)
|
||||||
|
{
|
||||||
|
return container_of(storage, suit_storage_ram_t, storage);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline const suit_storage_ram_t *_get_ram_const(
|
||||||
|
const suit_storage_t *storage)
|
||||||
|
{
|
||||||
|
return container_of(storage, suit_storage_ram_t, storage);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline suit_storage_ram_region_t *_get_active_region(
|
||||||
|
suit_storage_ram_t *ram)
|
||||||
|
{
|
||||||
|
return &ram->regions[ram->active_region];
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool _get_region_by_string(const char *location, uint32_t *val)
|
||||||
|
{
|
||||||
|
/* Matching on .ram.### */
|
||||||
|
static const char prefix[] = ".ram.";
|
||||||
|
static const size_t prefix_len = sizeof(prefix) - 1;
|
||||||
|
|
||||||
|
/* Check for prefix */
|
||||||
|
if (strncmp(prefix, location, prefix_len) == 0 &&
|
||||||
|
location[prefix_len] != '\n') {
|
||||||
|
/* Advance to the number */
|
||||||
|
location += prefix_len;
|
||||||
|
/* Check if the rest of the string is a number */
|
||||||
|
if (fmt_is_number(location)) {
|
||||||
|
/* grab the number */
|
||||||
|
*val = scn_u32_dec(location, 5);
|
||||||
|
/* Number must be smaller than the number of regions */
|
||||||
|
if (*val < CONFIG_SUIT_STORAGE_RAM_REGIONS) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _ram_init(suit_storage_t *storage)
|
||||||
|
{
|
||||||
|
|
||||||
|
suit_storage_ram_t *ram = _get_ram(storage);
|
||||||
|
|
||||||
|
/* Clear the ram regions */
|
||||||
|
memset(ram->regions, 0,
|
||||||
|
sizeof(suit_storage_ram_region_t) * CONFIG_SUIT_STORAGE_RAM_REGIONS);
|
||||||
|
return SUIT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _ram_start(suit_storage_t *storage, const suit_manifest_t *manifest,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
(void)manifest;
|
||||||
|
suit_storage_ram_t *ram = _get_ram(storage);
|
||||||
|
suit_storage_ram_region_t *region = _get_active_region(ram);
|
||||||
|
|
||||||
|
if (len > CONFIG_SUIT_STORAGE_RAM_SIZE) {
|
||||||
|
return SUIT_ERR_STORAGE_EXCEEDED;
|
||||||
|
}
|
||||||
|
|
||||||
|
region->occupied = 0;
|
||||||
|
return SUIT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _ram_write(suit_storage_t *storage, const suit_manifest_t *manifest,
|
||||||
|
const uint8_t *buf, size_t offset, size_t len)
|
||||||
|
{
|
||||||
|
(void)manifest;
|
||||||
|
suit_storage_ram_t *ram = _get_ram(storage);
|
||||||
|
suit_storage_ram_region_t *region = _get_active_region(ram);
|
||||||
|
|
||||||
|
if (offset + len > CONFIG_SUIT_STORAGE_RAM_SIZE) {
|
||||||
|
return SUIT_ERR_STORAGE_EXCEEDED;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(®ion->mem[offset], buf, len);
|
||||||
|
region->occupied += len;
|
||||||
|
return SUIT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _ram_finish(suit_storage_t *storage, const suit_manifest_t *manifest)
|
||||||
|
{
|
||||||
|
(void)storage;
|
||||||
|
(void)manifest;
|
||||||
|
return SUIT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _ram_install(suit_storage_t *storage,
|
||||||
|
const suit_manifest_t *manifest)
|
||||||
|
{
|
||||||
|
(void)manifest;
|
||||||
|
(void)storage;
|
||||||
|
return SUIT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _ram_erase(suit_storage_t *storage)
|
||||||
|
{
|
||||||
|
suit_storage_ram_t *ram = _get_ram(storage);
|
||||||
|
suit_storage_ram_region_t *region = _get_active_region(ram);
|
||||||
|
|
||||||
|
memset(region->mem, 0, CONFIG_SUIT_STORAGE_RAM_SIZE);
|
||||||
|
return SUIT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _ram_read(suit_storage_t *storage, uint8_t *buf, size_t offset,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
suit_storage_ram_t *ram = _get_ram(storage);
|
||||||
|
suit_storage_ram_region_t *region = _get_active_region(ram);
|
||||||
|
|
||||||
|
if (offset + len > CONFIG_SUIT_STORAGE_RAM_SIZE) {
|
||||||
|
return SUIT_ERR_STORAGE_EXCEEDED;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buf, ®ion->mem[offset], len);
|
||||||
|
|
||||||
|
return SUIT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _ram_read_ptr(suit_storage_t *storage,
|
||||||
|
const uint8_t **buf, size_t *len)
|
||||||
|
{
|
||||||
|
suit_storage_ram_t *ram = _get_ram(storage);
|
||||||
|
suit_storage_ram_region_t *region = _get_active_region(ram);
|
||||||
|
|
||||||
|
*buf = region->mem;
|
||||||
|
*len = region->occupied;
|
||||||
|
return SUIT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool _ram_has_location(const suit_storage_t *storage,
|
||||||
|
const char *location)
|
||||||
|
{
|
||||||
|
(void)storage;
|
||||||
|
uint32_t val;
|
||||||
|
|
||||||
|
return _get_region_by_string(location, &val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _ram_set_active_location(suit_storage_t *storage,
|
||||||
|
const char *location)
|
||||||
|
{
|
||||||
|
suit_storage_ram_t *ram = _get_ram(storage);
|
||||||
|
uint32_t region = 0;
|
||||||
|
|
||||||
|
if (!_get_region_by_string(location, ®ion)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ram->active_region = region;
|
||||||
|
return SUIT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _ram_get_seq_no(const suit_storage_t *storage, uint32_t *seq_no)
|
||||||
|
{
|
||||||
|
const suit_storage_ram_t *ram = _get_ram_const(storage);
|
||||||
|
|
||||||
|
*seq_no = ram->sequence_no;
|
||||||
|
LOG_INFO("Retrieved sequence number: %" PRIu32 "\n", *seq_no);
|
||||||
|
return SUIT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _ram_set_seq_no(suit_storage_t *storage, uint32_t seq_no)
|
||||||
|
{
|
||||||
|
suit_storage_ram_t *ram = _get_ram(storage);
|
||||||
|
|
||||||
|
if (ram->sequence_no < seq_no) {
|
||||||
|
LOG_INFO("Stored sequence number: %" PRIu32 "\n", seq_no);
|
||||||
|
ram->sequence_no = seq_no;
|
||||||
|
return SUIT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SUIT_ERR_SEQUENCE_NUMBER;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const suit_storage_driver_t suit_storage_ram_driver = {
|
||||||
|
.init = _ram_init,
|
||||||
|
.start = _ram_start,
|
||||||
|
.write = _ram_write,
|
||||||
|
.finish = _ram_finish,
|
||||||
|
.read = _ram_read,
|
||||||
|
.read_ptr = _ram_read_ptr,
|
||||||
|
.install = _ram_install,
|
||||||
|
.erase = _ram_erase,
|
||||||
|
.has_location = _ram_has_location,
|
||||||
|
.set_active_location = _ram_set_active_location,
|
||||||
|
.get_seq_no = _ram_get_seq_no,
|
||||||
|
.set_seq_no = _ram_set_seq_no,
|
||||||
|
.separator = '.',
|
||||||
|
};
|
||||||
|
|
||||||
|
suit_storage_ram_t suit_storage_ram = {
|
||||||
|
.storage = {
|
||||||
|
.driver = &suit_storage_ram_driver,
|
||||||
|
},
|
||||||
|
};
|
||||||
Loading…
x
Reference in New Issue
Block a user