Merge pull request #12017 from VeijoPesonen/remove_nvstore

NVStore: already deprecated implementation removed
pull/12040/head
Martin Kojtal 2019-12-05 09:10:30 +01:00 committed by GitHub
commit 412a9317de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 11 additions and 2458 deletions

View File

@ -32,8 +32,7 @@
"events",
"kv-global-api",
"sd",
"qspif",
"nvstore"
"qspif"
],
"target_overrides": {
"*": {

View File

@ -17,7 +17,7 @@ limitations under the License.
This script is the host script for trng test sequence, it send the
step signaling sequence and receive and transmit data to the device after
reset if necesarry (default loading and storing mechanism while reseting the device
is NVstore, in case NVstore isn't enabled we'll use current infrastructure,
is KVStore, in case KVStore isn't enabled we'll use current infrastructure,
for more details see main.cpp file)
"""
@ -142,4 +142,4 @@ class TRNGResetTest(BaseHostTest):
self.send_kv(MSG_KEY_EXIT, MSG_VALUE_DUMMY)
# The sequence is correct -- test passed.
yield
yield

View File

@ -267,7 +267,6 @@ The [storage APIs](storage.html) include file system APIs, for file system opera
<td><a href="littlefilesystem.html">LittleFileSystem</a></td>
<td><a href="chainingblockdevice.html">ChainingBlockDevice</a></td>
<td><a href="../apis/dataflashblockdevice.html">DataFlashBlockDevice</a></td>
<td><a href="nvstore.html">NVStore</a></td>
</tr>
<tr>
<td><a href="static-global-api.html">Static Global API</a></td>
@ -3115,4 +3114,4 @@ An application can extend capabilities of `SimpleMessageParser` by adding new re
- [MessageParser](messageparser.html) API reference.
- [MessageBuilder](messagebuilder.html) API reference.
- [NFC architecture](../reference/nfc-technology.html).
- [NFC architecture](../reference/nfc-technology.html).

View File

@ -31,7 +31,6 @@ set(unittest-sources
../features/storage/kvstore/conf/kv_config.cpp
../features/storage/kvstore/filesystemstore/FileSystemStore.cpp
../features/storage/system_storage/SystemStorage.cpp
../features/storage/nvstore/source/nvstore.cpp
../features/storage/blockdevice/ChainingBlockDevice.cpp
../features/storage/blockdevice/ReadOnlyBlockDevice.cpp
../features/storage/blockdevice/SlicingBlockDevice.cpp

View File

@ -1,6 +1,6 @@
{
"name": "tfm-s",
"macros": ["MBED_FAULT_HANDLER_DISABLED", "BYPASS_NVSTORE_CHECK=1"],
"macros": ["MBED_FAULT_HANDLER_DISABLED"],
"config": {
"max_ns_thread_count": {
"help": "maximum allowed number of non-secure threads",

View File

@ -20,8 +20,6 @@ Below there is a list of some examples to explain the motivation and the need fo
examples:
- TDBStore needs to know if there are flash characteristics for the block device and if there aren<65>t it should use
FlashSimBlockDevice to simulate a flash BlockDevice.
- TDBStore should not co-exists with NVStore, but this is true only if TDBStore is running on internal memory. Therefore if TDBStore running on
internal memory and NVStore is also there an error should be raised.
- When creating a file system you would prefer working with FAT on top of SD while LITTLEFS on top of any flash block device.
Those preference in favor of better performance.

View File

@ -1,23 +1,23 @@
## DeviceKey
DeviceKey is a mechanism that implements key derivation from a root of trust key. The DeviceKey mechanism generates symmetric keys that security features need. You can use these keys for encryption, authentication and more. The DeviceKey API allows key derivation without exposing the actual root of trust, to reduce the possibility of accidental exposure of the root of trust outside the device.
DeviceKey is a mechanism that implements key derivation from a Root of Trust(RoT) key. The DeviceKey mechanism generates symmetric keys that security features need. You can use these keys for encryption, authentication and more. The DeviceKey API allows key derivation without exposing the actual RoT, to reduce the possibility of accidental exposure of the RoT outside the device.
We have implemented DeviceKey according to NIST SP 800-108, section "KDF in Counter Mode", with AES-CMAC as the pseudorandom function.
### Root of Trust
The root of trust key, which DeviceKey uses to derive additional keys, is generated using the hardware random generator if it exists, or using a key injected to the device in the production process.
The RoT key, which DeviceKey uses to derive additional keys, is generated using the hardware random generator if it exists, or using a key injected to the device in the production process.
The characteristics required by this root of trust are:
The characteristics required by this RoT are:
- It must be unique per device.
- It must be difficult to guess.
- It must be at least 128 bits.
- It must be kept secret.
The DeviceKey feature keeps the root of trust key in internal storage, using the NVStore component. Internal storage provides protection from external physical attacks to the device.
The DeviceKey feature keeps the RoT key in internal storage, using the KVStore component. Internal storage provides protection from external physical attacks to the device.
The root of trust is generated at the first use of DeviceKey if the true random number generator is available in the device. If no true random number generator is available, you must pass the injected root of trust key to the DeviceKey before you call the key derivation API.
The RoT is generated at the first use of DeviceKey if the True Random Number Generator(TRNG) is available in the device. If no TRNG is available, you must pass the injected RoT key to the DeviceKey before you call the key derivation API.
### Key derivation API
@ -25,7 +25,7 @@ The root of trust is generated at the first use of DeviceKey if the true random
#### Root of Trust Injection API
`device_inject_root_of_trust`: You must call this API once in the lifecycle of the device, before any call to key derivation, if the device does not support True Random Number Generator (`DEVICE_TRNG` is not defined).
`device_inject_root_of_trust`: You must call this API once in the lifecycle of the device, before any call to key derivation, if the device does not support TRNG (`DEVICE_TRNG` is not defined).
#### Using DeviceKey

View File

@ -25,10 +25,6 @@
#include "mbed_assert.h"
#include "mbed_wait_api.h"
#include "MbedCRC.h"
//Bypass the check of NVStore co existance if compiled for TARGET_TFM
#if !(BYPASS_NVSTORE_CHECK)
#include "features/storage/system_storage/SystemStorage.h"
#endif
using namespace mbed;
@ -1004,18 +1000,6 @@ int TDBStore::init()
goto end;
}
//Bypass the check of NVStore co existance if compiled for TARGET_TFM
#if !(BYPASS_NVSTORE_CHECK)
//Check if we are on internal memory && try to set the internal memory for TDBStore use.
if (strcmp(_bd->get_type(), "FLASHIAP") == 0 &&
avoid_conflict_nvstore_tdbstore(TDBSTORE) == MBED_ERROR_ALREADY_INITIALIZED) {
MBED_ERROR(MBED_ERROR_ALREADY_INITIALIZED, "TDBStore in internal memory can not be initialize when NVStore is in use");
}
#endif
_max_keys = initial_max_keys;
ram_table = new ram_table_entry_t[_max_keys];

View File

@ -1,60 +0,0 @@
# NVStore
NVStore is a lightweight module that stores data by keys in the internal flash for security purposes.
## Description
NVStore provides the ability to store a minimal set of system critical items in the internal flash.
For each item key, the NVStore module provides the ability to set the item data or get it.
Newly added values are added to the end of the existing data, superseding the previous value that was there for the same key.
The NVStore module ensures that power failures don't harm existing data during any operation.
The full interface can be found under `nvstore.h`.
### Flash structure
NVStore uses two Flash areas, active and nonactive. Each area must consist of at least one erasable unit (sector).
Data is written to the active area until it becomes full. When it does, garbage collection is invoked.
This compacts items from the active area to the nonactive one and switches activity between areas.
Each item is kept in an entry containing a header and data, where the header holds the item key, size and CRC.
### APIs
- init: Initialize NVStore (also lazily called by get, set, set_once and remove APIs).
- deinit: Deinitialize NVStore.
- get: Get the value of an item, given key.
- set: Set the value of an item, given key and value.
- set_once: Like set, but allows only a one time setting of this item (and disables deleting of this item).
- alloc_key: Allocates a free key (from the keys that are not predefined) to an owner (an owning feature).
- free_all_keys_by_owner: Free all allocated keys, given an owner.
- remove: Remove an item, given key.
- get_item_size: Get the item value size (in bytes).
- set_max_keys: Set maximal value of unique keys. Overriding the default of NVSTORE_MAX_KEYS. This affects RAM consumption,
as NVStore consumes 4 bytes per unique key. Reinitializes the module.
## Usage
### Enabling NVStore and configuring it for your board
NVStore is enabled by default for all devices with the internal flash driver (have "FLASH" in the device_has attribute).
One can disable it by setting its "enabled" attribute to false.
Unless specifically configured by the user, NVStore selects the last two flash sectors as its areas, with the minimum size of 4KBs,
meaning that if the sectors are smaller, few continuous ones will be used for each area.
The user can override this by setting the addresses and sizes of both areas in` mbed_lib.json` on a per board basis.
In this case, all following four attributes need to be set:
- area_1_address
- area_1_size
- area_2_address
- area_2_size
In addition, the `num_keys` value should be modified to change the default number of different keys.
### Using NVStore
NVStore is a singleton class, meaning that the system can have only a single instance of it.
To instantiate NVStore, one needs to call its get_instance member function as following:
``` c++
NVStore &nvstore = NVStore::get_instance();
```
After the NVStore instantiation, one can call the init API, but it is not necessary because all
NVStore APIs (get, set and so on) perform a "lazy initialization".
### Testing NVStore
Run the NVStore functionality test with the `mbed` command as following:
```mbed test -n features-nvstore-tests-nvstore-functionality```

View File

@ -1,699 +0,0 @@
/*
* Copyright (c) 2018 ARM Limited. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "nvstore.h"
#ifdef MBED_CONF_RTOS_PRESENT
#include "Thread.h"
#endif
#include "mbed_wait_api.h"
#include "greentea-client/test_env.h"
#include "unity/unity.h"
#include "utest/utest.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <algorithm>
#if !NVSTORE_ENABLED
#error [NOT_SUPPORTED] NVSTORE needs to be enabled for this test
#else
using namespace utest::v1;
static const uint16_t max_test_keys = 20;
static const uint16_t max_possible_keys_threshold = 64;
static const size_t basic_func_max_data_size = 128;
static const int thr_test_num_buffs = 5;
static const int thr_test_num_secs = 5;
static const int thr_test_max_data_size = 32;
static const int thr_test_num_threads = 3;
#if defined(__CORTEX_M23) || defined(__CORTEX_M33)
static const int thr_test_stack_size = 1280;
#else
static const int thr_test_stack_size = 1024;
#endif
typedef struct {
uint8_t *buffs[max_test_keys][thr_test_num_buffs];
uint16_t sizes[max_test_keys][thr_test_num_buffs];
uint16_t max_keys;
bool stop_threads;
} thread_test_data_t;
static thread_test_data_t *thr_test_data;
static const int race_test_num_threads = 4;
static const int race_test_key = 1;
static const int race_test_data_size = 128;
static const int race_test_stack_size = 768;
static bool nvstore_overlaps_code = false;
static void gen_random(uint8_t *s, int len)
{
for (int i = 0; i < len; ++i) {
s[i] = rand() % 256;
}
}
static void nvstore_basic_functionality_test()
{
uint16_t actual_len_bytes = 0;
NVStore &nvstore = NVStore::get_instance();
uint16_t key;
uint16_t max_possible_keys;
int result;
printf("NVStore areas:\n");
for (uint8_t area = 0; area < NVSTORE_NUM_AREAS; area++) {
uint32_t area_address;
size_t area_size;
nvstore.get_area_params(area, area_address, area_size);
printf("Area %d: address 0x%08lx, size %d (0x%x)\n", area, area_address, area_size, area_size);
if (area_address < FLASHIAP_APP_ROM_END_ADDR) {
nvstore_overlaps_code = true;
}
TEST_SKIP_UNLESS_MESSAGE(!nvstore_overlaps_code, "Test skipped. NVStore region overlaps code.");
}
uint8_t *nvstore_testing_buf_set = new (std::nothrow) uint8_t[basic_func_max_data_size];
uint8_t *nvstore_testing_buf_get = new (std::nothrow) uint8_t[basic_func_max_data_size];
if (!nvstore_testing_buf_set || !nvstore_testing_buf_get) {
printf("Not enough heap space to run test. Test skipped\n");
goto clean;
}
gen_random(nvstore_testing_buf_set, basic_func_max_data_size);
max_possible_keys = nvstore.get_max_possible_keys();
TEST_SKIP_UNLESS_MESSAGE(max_test_keys < max_possible_keys,
"Not enough possible keys for test. Test skipped.");
TEST_SKIP_UNLESS_MESSAGE(max_possible_keys >= max_possible_keys_threshold,
"Max possible keys below threshold. Test skipped.");
result = nvstore.reset();
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
nvstore.set_max_keys(max_test_keys);
TEST_ASSERT_EQUAL(max_test_keys, nvstore.get_max_keys());
printf("Max keys %d (out of %d possible ones)\n", nvstore.get_max_keys(), max_possible_keys);
result = nvstore.set(5, 18, nvstore_testing_buf_set);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
result = nvstore.get(5, 22, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
TEST_ASSERT_EQUAL(18, actual_len_bytes);
TEST_ASSERT_EQUAL_UINT8_ARRAY(nvstore_testing_buf_set, nvstore_testing_buf_get, 15);
result = nvstore.remove(5);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
result = nvstore.get(5, 20, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_NOT_FOUND, result);
result = nvstore.set(11, 0, NULL);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
result = nvstore.set(9, 20, NULL);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
result = nvstore.set(7, 0, nvstore_testing_buf_set);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
result = nvstore.set(10, 64, nvstore_testing_buf_set);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
result = nvstore.set(13, 3, &(nvstore_testing_buf_set[1]));
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
result = nvstore.set(15, 15, &(nvstore_testing_buf_set[2]));
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
result = nvstore.set(64, 15, &(nvstore_testing_buf_set[2]));
TEST_ASSERT_EQUAL(NVSTORE_BAD_VALUE, result);
result = nvstore.set(9, 20, &(nvstore_testing_buf_set[3]));
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
result = nvstore.set_once(19, 12, &(nvstore_testing_buf_set[2]));
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
result = nvstore.set(19, 10, &(nvstore_testing_buf_set[3]));
TEST_ASSERT_EQUAL(NVSTORE_ALREADY_EXISTS, result);
result = nvstore.allocate_key(key, 3);
TEST_ASSERT_EQUAL(NVSTORE_NUM_PREDEFINED_KEYS, key);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
result = nvstore.set(NVSTORE_NUM_PREDEFINED_KEYS, 17, &(nvstore_testing_buf_set[3]));
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
result = nvstore.allocate_key(key, 3);
TEST_ASSERT_EQUAL(NVSTORE_NUM_PREDEFINED_KEYS + 1, key);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
result = nvstore.set(NVSTORE_NUM_PREDEFINED_KEYS + 1, 17, &(nvstore_testing_buf_set[3]));
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
// Make sure set items are also gotten OK after reset
result = nvstore.deinit();
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
result = nvstore.init();
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
result = nvstore.get(14, 20, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_NOT_FOUND, result);
result = nvstore.get(7, 0, NULL, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
TEST_ASSERT_EQUAL(0, actual_len_bytes);
result = nvstore.get(7, 15, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
TEST_ASSERT_EQUAL(0, actual_len_bytes);
result = nvstore.get(7, 0, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
TEST_ASSERT_EQUAL(0, actual_len_bytes);
result = nvstore.get(9, 0, NULL, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_BUFF_TOO_SMALL, result);
result = nvstore.get(9, 150, NULL, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_BUFF_TOO_SMALL, result);
result = nvstore.get(10, 64, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
TEST_ASSERT_EQUAL(64, actual_len_bytes);
TEST_ASSERT_EQUAL_UINT8_ARRAY(nvstore_testing_buf_set, nvstore_testing_buf_get, 64);
result = nvstore.get(NVSTORE_NUM_PREDEFINED_KEYS, 64, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
TEST_ASSERT_EQUAL(17, actual_len_bytes);
TEST_ASSERT_EQUAL_UINT8_ARRAY(&nvstore_testing_buf_set[3], nvstore_testing_buf_get, 17);
result = nvstore.get(NVSTORE_NUM_PREDEFINED_KEYS + 1, 64, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
TEST_ASSERT_EQUAL(17, actual_len_bytes);
TEST_ASSERT_EQUAL_UINT8_ARRAY(&nvstore_testing_buf_set[3], nvstore_testing_buf_get, 17);
result = nvstore.free_all_keys_by_owner(3);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
result = nvstore.get(NVSTORE_NUM_PREDEFINED_KEYS, 64, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_NOT_FOUND, result);
result = nvstore.get(NVSTORE_NUM_PREDEFINED_KEYS + 1, 64, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_NOT_FOUND, result);
result = nvstore.get(10, 65, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
TEST_ASSERT_EQUAL(64, actual_len_bytes);
TEST_ASSERT_EQUAL_UINT8_ARRAY(nvstore_testing_buf_set, nvstore_testing_buf_get, 64);
result = nvstore.get(64, 20, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_BAD_VALUE, result);
result = nvstore.get(9, 20, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
TEST_ASSERT_EQUAL(20, actual_len_bytes);
TEST_ASSERT_EQUAL_UINT8_ARRAY(&(nvstore_testing_buf_set[3]), nvstore_testing_buf_get, 20);
result = nvstore.get(9, 21, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
TEST_ASSERT_EQUAL(20, actual_len_bytes);
TEST_ASSERT_EQUAL_UINT8_ARRAY(&(nvstore_testing_buf_set[3]), nvstore_testing_buf_get, 20);
result = nvstore.get(9, 19, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_BUFF_TOO_SMALL, result);
result = nvstore.get(13, 3, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
TEST_ASSERT_EQUAL(3, actual_len_bytes);
TEST_ASSERT_EQUAL_UINT8_ARRAY(&(nvstore_testing_buf_set[1]), nvstore_testing_buf_get, 3);
result = nvstore.get_item_size(13, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
TEST_ASSERT_EQUAL(3, actual_len_bytes);
result = nvstore.get(13, 4, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
TEST_ASSERT_EQUAL(3, actual_len_bytes);
TEST_ASSERT_EQUAL_UINT8_ARRAY(&(nvstore_testing_buf_set[1]), nvstore_testing_buf_get, 3);
result = nvstore.get(13, 2, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_BUFF_TOO_SMALL, result);
result = nvstore.init();
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
// check all the expected keys
actual_len_bytes = 0;
result = nvstore.get(10, 64, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
TEST_ASSERT_EQUAL(64, actual_len_bytes);
TEST_ASSERT_EQUAL_UINT8_ARRAY(nvstore_testing_buf_set, nvstore_testing_buf_get, 64);
actual_len_bytes = 0;
result = nvstore.get(11, 64, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
TEST_ASSERT_EQUAL(0, actual_len_bytes);
actual_len_bytes = 0;
result = nvstore.get(13, 3, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
TEST_ASSERT_EQUAL(3, actual_len_bytes);
TEST_ASSERT_EQUAL_UINT8_ARRAY(&(nvstore_testing_buf_set[1]), nvstore_testing_buf_get, 3);
actual_len_bytes = 0;
result = nvstore.get(9, 20, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
TEST_ASSERT_EQUAL(20, actual_len_bytes);
TEST_ASSERT_EQUAL_UINT8_ARRAY(&(nvstore_testing_buf_set[3]), nvstore_testing_buf_get, 20);
actual_len_bytes = 0;
result = nvstore.get(7, 0, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
TEST_ASSERT_EQUAL(0, actual_len_bytes);
actual_len_bytes = 0;
result = nvstore.get(15, 15, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
TEST_ASSERT_EQUAL(15, actual_len_bytes);
TEST_ASSERT_EQUAL_UINT8_ARRAY(&(nvstore_testing_buf_set[2]), nvstore_testing_buf_get, 15);
actual_len_bytes = 0;
result = nvstore.get(19, 12, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
TEST_ASSERT_EQUAL(12, actual_len_bytes);
TEST_ASSERT_EQUAL_UINT8_ARRAY(&(nvstore_testing_buf_set[2]), nvstore_testing_buf_get, 12);
// change the data for all keys
result = nvstore.set(10, 15, &(nvstore_testing_buf_set[4]));
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
result = nvstore.set(11, 27, &(nvstore_testing_buf_set[5]));
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
result = nvstore.set(13, 7, &(nvstore_testing_buf_set[6]));
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
result = nvstore.set(9, 0, &(nvstore_testing_buf_set[7]));
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
result = nvstore.set(7, 48, &(nvstore_testing_buf_set[8]));
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
result = nvstore.set(14, 89, &(nvstore_testing_buf_set[9]));
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
result = nvstore.set(15, 53, &(nvstore_testing_buf_set[10]));
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
actual_len_bytes = 0;
result = nvstore.get(10, 15, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
TEST_ASSERT_EQUAL(15, actual_len_bytes);
TEST_ASSERT_EQUAL_UINT8_ARRAY(&(nvstore_testing_buf_set[4]), nvstore_testing_buf_get, 15);
actual_len_bytes = 0;
result = nvstore.get(11, 27, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
TEST_ASSERT_EQUAL(27, actual_len_bytes);
TEST_ASSERT_EQUAL_UINT8_ARRAY(&(nvstore_testing_buf_set[5]), nvstore_testing_buf_get, 27);
actual_len_bytes = 0;
result = nvstore.get(13, 7, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
TEST_ASSERT_EQUAL(7, actual_len_bytes);
TEST_ASSERT_EQUAL_UINT8_ARRAY(&(nvstore_testing_buf_set[6]), nvstore_testing_buf_get, 7);
actual_len_bytes = 0;
result = nvstore.get(9, 0, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
TEST_ASSERT_EQUAL(0, actual_len_bytes);
actual_len_bytes = 0;
result = nvstore.get(7, 48, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
TEST_ASSERT_EQUAL(48, actual_len_bytes);
TEST_ASSERT_EQUAL_UINT8_ARRAY(&(nvstore_testing_buf_set[8]), nvstore_testing_buf_get, 48);
actual_len_bytes = 0;
result = nvstore.get(14, 89, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
TEST_ASSERT_EQUAL(89, actual_len_bytes);
TEST_ASSERT_EQUAL_UINT8_ARRAY(&(nvstore_testing_buf_set[9]), nvstore_testing_buf_get, 89);
actual_len_bytes = 0;
result = nvstore.get(15, 53, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
TEST_ASSERT_EQUAL(53, actual_len_bytes);
TEST_ASSERT_EQUAL_UINT8_ARRAY(&(nvstore_testing_buf_set[10]), nvstore_testing_buf_get, 53);
result = nvstore.deinit();
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
actual_len_bytes = 0;
result = nvstore.get(10, 64, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
TEST_ASSERT_EQUAL(15, actual_len_bytes);
TEST_ASSERT_EQUAL_UINT8_ARRAY(&(nvstore_testing_buf_set[4]), nvstore_testing_buf_get, 15);
actual_len_bytes = 0;
result = nvstore.get(11, 27, nvstore_testing_buf_get, actual_len_bytes); // no care about the buf and len values
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
TEST_ASSERT_EQUAL(27, actual_len_bytes);
TEST_ASSERT_EQUAL_UINT8_ARRAY(&(nvstore_testing_buf_set[5]), nvstore_testing_buf_get, 27);
actual_len_bytes = 0;
result = nvstore.get(13, 7, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
TEST_ASSERT_EQUAL(7, actual_len_bytes);
TEST_ASSERT_EQUAL_UINT8_ARRAY(&(nvstore_testing_buf_set[6]), nvstore_testing_buf_get, 7);
actual_len_bytes = 0;
result = nvstore.get(9, 0, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
TEST_ASSERT_EQUAL(0, actual_len_bytes);
actual_len_bytes = 0;
result = nvstore.get(7, 48, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
TEST_ASSERT_EQUAL(48, actual_len_bytes);
TEST_ASSERT_EQUAL_UINT8_ARRAY(&(nvstore_testing_buf_set[8]), nvstore_testing_buf_get, 48);
actual_len_bytes = 0;
result = nvstore.get(14, 89, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
TEST_ASSERT_EQUAL(89, actual_len_bytes);
TEST_ASSERT_EQUAL_UINT8_ARRAY(&(nvstore_testing_buf_set[9]), nvstore_testing_buf_get, 89);
actual_len_bytes = 0;
result = nvstore.get(15, 53, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
TEST_ASSERT_EQUAL(53, actual_len_bytes);
TEST_ASSERT_EQUAL_UINT8_ARRAY(&(nvstore_testing_buf_set[10]), nvstore_testing_buf_get, 53);
result = nvstore.get(NVSTORE_NUM_PREDEFINED_KEYS, 64, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_NOT_FOUND, result);
result = nvstore.get(NVSTORE_NUM_PREDEFINED_KEYS + 1, 64, nvstore_testing_buf_get, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_NOT_FOUND, result);
clean:
delete[] nvstore_testing_buf_set;
delete[] nvstore_testing_buf_get;
}
#ifdef MBED_CONF_RTOS_PRESENT
static void thread_test_check_key(uint16_t key)
{
uint8_t get_buff[thr_test_max_data_size];
int ret;
uint16_t actual_len_bytes;
NVStore &nvstore = NVStore::get_instance();
ret = nvstore.get(key, thr_test_max_data_size, get_buff, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, ret);
TEST_ASSERT_NOT_EQUAL(0, actual_len_bytes);
for (int i = 0; i < thr_test_num_buffs; i++) {
if (thr_test_data->sizes[key][i] != actual_len_bytes) {
continue;
}
if (!memcmp(thr_test_data->buffs[key][i], get_buff, actual_len_bytes)) {
return;
}
}
// Got here - always assert
TEST_ASSERT(0);
}
static void thread_test_worker()
{
int ret;
int buf_num, is_set;
uint16_t key;
NVStore &nvstore = NVStore::get_instance();
while (!thr_test_data->stop_threads) {
key = rand() % thr_test_data->max_keys;
is_set = rand() % 10;
if (is_set) {
buf_num = rand() % thr_test_num_buffs;
ret = nvstore.set(key, thr_test_data->sizes[key][buf_num], thr_test_data->buffs[key][buf_num]);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, ret);
} else {
thread_test_check_key(key);
}
wait_ms(1);
}
}
static void nvstore_multi_thread_test()
{
int i, result;
uint16_t size;
uint16_t key;
int ret;
char *dummy;
uint16_t max_possible_keys, actual_len_bytes = 0;
char test[] = "Test", read_buf[10] = {};
NVStore &nvstore = NVStore::get_instance();
TEST_SKIP_UNLESS_MESSAGE(!nvstore_overlaps_code, "Test skipped. NVStore region overlaps code.");
thr_test_data = 0;
rtos::Thread **threads = new (std::nothrow) rtos::Thread*[thr_test_num_threads];
if (!threads) {
goto mem_fail;
}
memset(threads, 0, thr_test_num_threads * sizeof(rtos::Thread *));
ret = nvstore.reset();
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, ret);
thr_test_data = new (std::nothrow) thread_test_data_t;
if (!thr_test_data) {
goto mem_fail;
}
memset(thr_test_data, 0, sizeof(thread_test_data_t));
thr_test_data->max_keys = max_test_keys / 2;
max_possible_keys = nvstore.get_max_possible_keys();
TEST_SKIP_UNLESS_MESSAGE(thr_test_data->max_keys < max_possible_keys,
"Not enough possible keys for test. Test skipped.");
TEST_SKIP_UNLESS_MESSAGE(max_possible_keys >= max_possible_keys_threshold,
"Max possible keys below threshold. Test skipped.");
nvstore.set_max_keys(max_test_keys + 1);
result = nvstore.set(max_test_keys, strlen(test), test);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
thr_test_data->stop_threads = false;
for (key = 0; key < thr_test_data->max_keys; key++) {
for (i = 0; i < thr_test_num_buffs; i++) {
size = 1 + rand() % thr_test_max_data_size;
thr_test_data->sizes[key][i] = size;
thr_test_data->buffs[key][i] = new (std::nothrow) uint8_t[size + 1];
if (!thr_test_data->buffs[key][i]) {
goto mem_fail;
}
gen_random(thr_test_data->buffs[key][i], size);
}
ret = nvstore.set(key, thr_test_data->sizes[key][0], thr_test_data->buffs[key][0]);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, ret);
}
for (i = 0; i < thr_test_num_threads; i++) {
threads[i] = new (std::nothrow) rtos::Thread((osPriority_t)((int)osPriorityBelowNormal - thr_test_num_threads + i),
thr_test_stack_size);
dummy = new (std::nothrow) char[thr_test_stack_size];
delete[] dummy;
if (!threads[i] || !dummy) {
goto mem_fail;
}
threads[i]->start(mbed::callback(thread_test_worker));
}
wait_ms(thr_test_num_secs * 1000);
thr_test_data->stop_threads = true;
wait_ms(1000);
ret = nvstore.deinit();
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, ret);
ret = nvstore.init();
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, ret);
for (key = 0; key < thr_test_data->max_keys; key++) {
thread_test_check_key(key);
}
result = nvstore.get(max_test_keys, sizeof(read_buf), read_buf, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, result);
TEST_ASSERT_EQUAL(strlen(test), actual_len_bytes);
TEST_ASSERT_EQUAL_UINT8_ARRAY(test, read_buf, strlen(test));
goto clean;
mem_fail:
printf("Not enough heap space to run test. Test skipped\n");
clean:
if (thr_test_data) {
thr_test_data->stop_threads = true;
wait_ms(1000);
for (key = 0; key < thr_test_data->max_keys; key++) {
for (i = 0; i < thr_test_num_buffs; i++) {
delete[] thr_test_data->buffs[key][i];
}
}
delete thr_test_data;
}
if (threads) {
for (i = 0; i < thr_test_num_threads; i++) {
delete threads[i];
}
delete[] threads;
}
nvstore.reset();
}
static void race_test_worker(void *buf)
{
int ret;
NVStore &nvstore = NVStore::get_instance();
ret = nvstore.set(race_test_key, race_test_data_size, buf);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, ret);
}
static void nvstore_race_test()
{
int i;
uint16_t initial_buf_size;
int ret;
int num_sets;
rtos::Thread *threads[race_test_num_threads];
uint8_t *get_buff = 0, *buffs[race_test_num_threads];
uint16_t actual_len_bytes;
uint16_t max_possible_keys;
char *dummy;
TEST_SKIP_UNLESS_MESSAGE(!nvstore_overlaps_code, "Test skipped. NVStore region overlaps code.");
NVStore &nvstore = NVStore::get_instance();
max_possible_keys = nvstore.get_max_possible_keys();
TEST_SKIP_UNLESS_MESSAGE(max_possible_keys >= max_possible_keys_threshold,
"Max possible keys below threshold. Test skipped.");
ret = nvstore.reset();
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, ret);
memset(buffs, 0, sizeof(buffs));
memset(threads, 0, sizeof(threads));
initial_buf_size = std::min((nvstore.size() - race_test_data_size) / 2, (size_t) race_test_data_size);
uint8_t *initial_buf = new (std::nothrow) uint8_t[initial_buf_size];
if (!initial_buf) {
goto mem_fail;
}
num_sets = (nvstore.size() - race_test_data_size) / initial_buf_size;
for (i = 0; i < num_sets; i++) {
ret = nvstore.set(0, initial_buf_size, initial_buf);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, ret);
}
delete[] initial_buf;
get_buff = new (std::nothrow) uint8_t[race_test_data_size];
if (!get_buff) {
goto mem_fail;
}
for (i = 0; i < race_test_num_threads; i++) {
buffs[i] = new (std::nothrow) uint8_t[race_test_data_size];
if (!buffs[i]) {
goto mem_fail;
}
gen_random(buffs[i], race_test_data_size);
}
for (i = 0; i < race_test_num_threads; i++) {
threads[i] = new (std::nothrow) rtos::Thread((osPriority_t)((int)osPriorityBelowNormal - race_test_num_threads + i),
race_test_stack_size);
if (!threads[i]) {
goto mem_fail;
}
dummy = new (std::nothrow) char[race_test_stack_size];
if (!dummy) {
goto mem_fail;
}
delete[] dummy;
threads[i]->start(mbed::callback(race_test_worker, (void *) buffs[i]));
threads[i]->join();
}
ret = nvstore.get(race_test_key, race_test_data_size, get_buff, actual_len_bytes);
TEST_ASSERT_EQUAL(NVSTORE_SUCCESS, ret);
TEST_ASSERT_EQUAL(race_test_data_size, actual_len_bytes);
for (i = 0; i < race_test_num_threads; i++) {
if (!memcmp(buffs[i], get_buff, actual_len_bytes)) {
break;
}
}
TEST_ASSERT_NOT_EQUAL(race_test_num_threads, i);
goto clean;
mem_fail:
printf("Not enough heap space to run test. Test skipped\n");
clean:
for (i = 0; i < race_test_num_threads; i++) {
delete threads[i];
delete[] buffs[i];
}
delete[] get_buff;
}
#endif
utest::v1::status_t greentea_failure_handler(const Case *const source, const failure_t reason)
{
greentea_case_failure_abort_handler(source, reason);
return STATUS_CONTINUE;
}
Case cases[] = {
Case("NVStore: Basic functionality", nvstore_basic_functionality_test, greentea_failure_handler),
#if defined(MBED_CONF_RTOS_PRESENT)
Case("NVStore: Race test", nvstore_race_test, greentea_failure_handler),
Case("NVStore: Multiple thread test", nvstore_multi_thread_test, greentea_failure_handler),
#endif
};
utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(120, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
int main()
{
return !Harness::run(specification);
}
#endif // !NVSTORE_ENABLED

View File

@ -1,60 +0,0 @@
{
"name": "nvstore",
"config": {
"enabled": {
"macro_name": "NVSTORE_ENABLED",
"value": true,
"help": "Enabled"
},
"max_keys": {
"macro_name": "NVSTORE_MAX_KEYS",
"value": 16,
"help": "Maximal number of allowed NVStore keys"
},
"area_1_address": {
"macro_name": "NVSTORE_AREA_1_ADDRESS",
"help": "Area 1 address"
},
"area_1_size": {
"macro_name": "NVSTORE_AREA_1_SIZE",
"help": "Area 1 size"
},
"area_2_address": {
"macro_name": "NVSTORE_AREA_2_ADDRESS",
"help": "Area 2 address"
},
"area_2_size": {
"macro_name": "NVSTORE_AREA_2_SIZE",
"help": "Area 2 size"
}
},
"target_overrides": {
"NUCLEO_F410RB": {
"enabled" : false
},
"FUTURE_SEQUANA": {
"area_1_address": "0x100F8000",
"area_1_size": 16384,
"area_2_address": "0x100FC000",
"area_2_size": 16384
},
"FUTURE_SEQUANA_M0": {
"area_1_address": "0x10078000",
"area_1_size": 16384,
"area_2_address": "0x1007C000",
"area_2_size": 16384
},
"CY8CKIT_062_WIFI_BT": {
"area_1_address": "0x100F8000",
"area_1_size": 16384,
"area_2_address": "0x100FC000",
"area_2_size": 16384
},
"CY8CPROTO_064_SB": {
"area_1_address": "0x10048000",
"area_1_size": 16384,
"area_2_address": "0x1004C000",
"area_2_size": 16384
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,457 +0,0 @@
/*
* Copyright (c) 2018 ARM Limited. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBED_NVSTORE_H
#define MBED_NVSTORE_H
// These addresses need to be configured according to board (in mbed_lib.json)
#if !DEVICE_FLASH
#undef NVSTORE_ENABLED
#define NVSTORE_ENABLED 0
#endif
#if (NVSTORE_ENABLED) || defined(DOXYGEN_ONLY)
#include <stdint.h>
#include <stdio.h>
#include "platform/NonCopyable.h"
#include "PlatformMutex.h"
#include "FlashIAP.h"
typedef enum {
NVSTORE_SUCCESS = 0,
NVSTORE_READ_ERROR = -1,
NVSTORE_WRITE_ERROR = -2,
NVSTORE_NOT_FOUND = -3,
NVSTORE_DATA_CORRUPT = -4,
NVSTORE_BAD_VALUE = -5,
NVSTORE_BUFF_TOO_SMALL = -6,
NVSTORE_FLASH_AREA_TOO_SMALL = -7,
NVSTORE_OS_ERROR = -8,
NVSTORE_ALREADY_EXISTS = -9,
NVSTORE_NO_FREE_KEY = -10,
} nvstore_status_e;
typedef enum {
NVSTORE_FIRST_PREDEFINED_KEY = 0,
// All predefined keys used for internal features should be defined here
NVSTORE_DEVICEKEY_KEY = 4,
NVSTORE_LAST_PREDEFINED_KEY = 15,
NVSTORE_NUM_PREDEFINED_KEYS
} nvstore_predefined_keys_e;
typedef enum {
NVSTORE_UNSPECIFIED_OWNER = 0,
// All owners (by features) should be specified here.
NVSTORE_MAX_OWNERS = 16
} nvstore_owner_e;
#ifndef NVSTORE_MAX_KEYS
#define NVSTORE_MAX_KEYS ((uint16_t)NVSTORE_NUM_PREDEFINED_KEYS)
#endif
// defines 2 areas - active and nonactive, not configurable
#define NVSTORE_NUM_AREAS 2
/** NVStore class
*
* Class for storing data by keys in the internal flash
*/
class NVStore : private mbed::NonCopyable<NVStore> {
public:
/**
* @brief As a singleton, return the single instance of the class.
* Reason for this class being a singleton is the following:
* - Ease the use for users of this class not having to coordinate instantiations.
* - Lazy instantiation of internal data (which we can't achieve with simple static classes).
*
* @returns Singleton instance reference.
*/
static NVStore &get_instance()
{
// Use this implementation of singleton (Meyer's) rather than the one that allocates
// the instance on the heap because it ensures destruction at program end (preventing warnings
// from memory checking tools).
static NVStore instance;
return instance;
}
virtual ~NVStore();
/**
* @brief Returns number of keys.
*
* @returns Number of keys.
*/
uint16_t get_max_keys() const;
/**
* @brief Set number of keys.
*
* @returns None.
*/
void set_max_keys(uint16_t num_keys);
/**
* @brief Return maximal possible number of keys (in this flash configuration).
*
* @returns Max possible number of keys.
*/
uint16_t get_max_possible_keys();
/**
* @brief Returns one item of data programmed on Flash, given key.
*
* @param[in] key Key of stored item.
* @param[in] buf_size Length of input buffer in bytes.
* @param[in] buf Buffer to store data on.
*
* @param[out] actual_size Actual size of returned data.
*
* @returns NVSTORE_SUCCESS Value was found on Flash.
* NVSTORE_NOT_FOUND Value was not found on Flash.
* NVSTORE_READ_ERROR Physical error reading data.
* NVSTORE_DATA_CORRUPT Data on Flash is corrupt.
* NVSTORE_BAD_VALUE Bad value in any of the parameters.
* NVSTORE_BUFF_TOO_SMALL Not enough memory in user buffer.
*/
int get(uint16_t key, uint16_t buf_size, void *buf, uint16_t &actual_size);
/**
* @brief Returns size of the data programmed on Flash, given key.
*
* @param[in] key Key of stored item.
* @param[out] actual_size Actual size of item
*
* @returns NVSTORE_SUCCESS Value was found on Flash.
* NVSTORE_NOT_FOUND Value was not found on Flash.
* NVSTORE_READ_ERROR Physical error reading data.
* NVSTORE_DATA_CORRUPT Data on Flash is corrupt.
* NVSTORE_BAD_VALUE Bad value in any of the parameters.
*/
int get_item_size(uint16_t key, uint16_t &actual_size);
/**
* @brief Programs one item of data on Flash, given key.
*
* @param[in] key Key of stored item.
* @param[in] buf_size Item size in bytes.
* @param[in] buf Buffer containing data.
*
* @returns NVSTORE_SUCCESS Value was successfully written on Flash.
* NVSTORE_WRITE_ERROR Physical error writing data.
* NVSTORE_BAD_VALUE Bad value in any of the parameters.
* NVSTORE_FLASH_AREA_TOO_SMALL
* Not enough space in Flash area.
* NVSTORE_ALREADY_EXISTS Item set with write once API already exists.
*
*/
int set(uint16_t key, uint16_t buf_size, const void *buf);
/**
* @brief Allocate a free key (to be used later in a set operation).
*
* @param[out] key Returned key of stored item.
* @param[in] owner Owner of allocated key.
*
* @returns NVSTORE_SUCCESS Key was successfully allocated.
* NVSTORE_NO_FREE_KEY Couldn't allocate a key for this call.
*
*/
int allocate_key(uint16_t &key, uint8_t owner = NVSTORE_UNSPECIFIED_OWNER);
/**
* @brief Free all allocated keys that belong to a specific owner.
*
* @param[in] owner Owner.
*
* @returns NVSTORE_SUCCESS Value was successfully written on Flash.
* NVSTORE_WRITE_ERROR Physical error writing data.
* NVSTORE_BAD_VALUE Bad value in any of the parameters.
*
*/
int free_all_keys_by_owner(uint8_t owner);
/**
* @brief Programs one item of data on Flash, given key, allowing no consequent sets to this key.
*
* @param[in] key Key of stored item.
* @param[in] buf_size Item size in bytes.
* @param[in] buf Buffer containing data.
*
* @returns NVSTORE_SUCCESS Value was successfully written on Flash.
* NVSTORE_WRITE_ERROR Physical error writing data.
* NVSTORE_BAD_VALUE Bad value in any of the parameters.
* NVSTORE_FLASH_AREA_TOO_SMALL
* Not enough space in Flash area.
* NVSTORE_ALREADY_EXISTS Item set with write once API already exists.
*
*/
int set_once(uint16_t key, uint16_t buf_size, const void *buf);
/**
* @brief Remove an item from flash.
*
* @param[in] key Key of stored item.
*
* @returns NVSTORE_SUCCESS Value was successfully written on Flash.
* NVSTORE_WRITE_ERROR Physical error writing data.
* NVSTORE_BAD_VALUE Bad value in any of the parameters.
* NVSTORE_FLASH_AREA_TOO_SMALL
* Not enough space in Flash area.
*
*/
int remove(uint16_t key);
/**
* @brief Initializes NVStore component.
*
* @returns NVSTORE_SUCCESS Initialization completed successfully.
* NVSTORE_READ_ERROR Physical error reading data.
* NVSTORE_WRITE_ERROR Physical error writing data (on recovery).
* NVSTORE_FLASH_AREA_TOO_SMALL
* Not enough space in Flash area.
*/
int init();
/**
* @brief Deinitializes NVStore component.
* Warning: This function is not thread safe and should not be called
* concurrently with other NVStore functions.
*
* @returns NVSTORE_SUCCESS Deinitialization completed successfully.
*/
int deinit();
/**
* @brief Reset Flash NVStore areas.
* Warning: This function is not thread safe and should not be called
* concurrently with other NVStore functions.
*
* @returns NVSTORE_SUCCESS Reset completed successfully.
* NVSTORE_READ_ERROR Physical error reading data.
* NVSTORE_WRITE_ERROR Physical error writing data.
*/
int reset();
/**
* @brief Return NVStore size (area size).
*
* @returns NVStore size.
*/
size_t size();
/**
* @brief Return address and size of an NVStore area.
*
* @param[in] area Area.
* @param[out] address Area address.
* @param[out] size Area size (bytes).
*
* @returns NVSTORE_SUCCESS Success.
* NVSTORE_BAD_VALUE Bad area parameter.
*/
int get_area_params(uint8_t area, uint32_t &address, size_t &size);
private:
typedef struct {
uint32_t address;
size_t size;
} nvstore_area_data_t;
int _init_done;
uint32_t _init_attempts;
uint8_t _active_area;
uint16_t _max_keys;
uint16_t _active_area_version;
uint32_t _free_space_offset;
size_t _size;
PlatformMutex *_mutex;
uint32_t *_offset_by_key;
nvstore_area_data_t _flash_area_params[NVSTORE_NUM_AREAS];
static nvstore_area_data_t initial_area_params[NVSTORE_NUM_AREAS];
mbed::FlashIAP *_flash;
uint32_t _min_prog_size;
uint8_t *_page_buf;
// Private constructor, as class is a singleton
MBED_DEPRECATED_SINCE("mbed-os-5.15", "NVStore is deprecated in favor of KVStore")
NVStore();
/**
* @brief Read a block from an area.
*
* @param[in] area Area.
* @param[in] offset Offset in area.
* @param[in] size Number of bytes to read.
* @param[in] buf Output buffer.
*
* @returns 0 for success, nonzero for failure.
*/
int flash_read_area(uint8_t area, uint32_t offset, uint32_t size, void *buf);
/**
* @brief Write a block to an area.
*
* @param[in] area Area.
* @param[in] offset Offset in area.
* @param[in] size Number of bytes to write.
* @param[in] buf Input buffer.
*
* @returns 0 for success, non-zero for failure.
*/
int flash_write_area(uint8_t area, uint32_t offset, uint32_t size, const void *buf);
/**
* @brief Erase an area.
*
* @param[in] area Area.
*
* @returns 0 for success, nonzero for failure.
*/
int flash_erase_area(uint8_t area);
/**
* @brief Calculate addresses and sizes of areas (in case no user configuration is given),
* or validate user configuration (if given).
*/
void calc_validate_area_params();
/**
* @brief Calculate empty (unprogrammed) continuous space at the end of the area.
*
* @param[in] area Area.
* @param[out] offset Offset of empty space.
*
* @returns 0 for success, nonzero for failure.
*/
int calc_empty_space(uint8_t area, uint32_t &offset);
/**
* @brief Read an NVStore record from a given location.
*
* @param[in] area Area.
* @param[in] offset Offset of record in area.
* @param[in] buf_size Buffer size (bytes).
* @param[in] buf Output Buffer.
* @param[out] actual_size Actual data size (bytes).
* @param[in] validate_only Just validate (without reading to buffer).
* @param[out] valid Is the record valid.
* @param[out] key Record key.
* @param[out] flags Record flags.
* @param[out] owner Owner.
* @param[out] next_offset Offset of next record.
*
* @returns 0 for success, nonzero for failure.
*/
int read_record(uint8_t area, uint32_t offset, uint16_t buf_size, void *buf,
uint16_t &actual_size, int validate_only, int &valid,
uint16_t &key, uint16_t &flags, uint8_t &owner, uint32_t &next_offset);
/**
* @brief Write an NVStore record from a given location.
*
* @param[in] area Area.
* @param[in] offset Offset of record in area.
* @param[in] key Record key.
* @param[in] flags Record flags.
* @param[in] owner Owner.
* @param[in] data_size Data size (bytes).
* @param[in] data_buf Data buffer.
* @param[out] next_offset Offset of next record.
*
* @returns 0 for success, nonzero for failure.
*/
int write_record(uint8_t area, uint32_t offset, uint16_t key, uint16_t flags, uint8_t owner,
uint32_t data_size, const void *data_buf, uint32_t &next_offset);
/**
* @brief Write a master record of a given area.
*
* @param[in] area Area.
* @param[in] version Area version.
* @param[out] next_offset Offset of next record.
*
* @returns 0 for success, nonzero for failure.
*/
int write_master_record(uint8_t area, uint16_t version, uint32_t &next_offset);
/**
* @brief Copy a record from one area to the other one.
*
* @param[in] from_area Area to copy record from.
* @param[in] from_offset Offset in source area.
* @param[in] to_offset Offset in destination area.
* @param[out] next_offset Offset of next record.
*
* @returns 0 for success, nonzero for failure.
*/
int copy_record(uint8_t from_area, uint32_t from_offset, uint32_t to_offset,
uint32_t &next_offset);
/**
* @brief Garbage collection (compact all records from active area to nonactive ones).
* All parameters belong to a record that needs to be written before the process.
*
* @param[in] key Record key.
* @param[in] flags Record flags.
* @param[in] owner Owner.
* @param[in] buf_size Data size (bytes).
* @param[in] buf Data buffer.
* @param[in] num_keys number of keys.
*
* @returns 0 for success, nonzero for failure.
*/
int garbage_collection(uint16_t key, uint16_t flags, uint8_t owner, uint16_t buf_size, const void *buf, uint16_t num_keys);
/**
* @brief Actual logics of get API (covers also get size API).
*
* @param[in] key key.
* @param[in] buf_size Buffer size (bytes).
* @param[in] buf Output Buffer.
* @param[out] actual_size Actual data size (bytes).
* @param[in] validate_only Just validate (without reading to buffer).
*
* @returns 0 for success, nonzero for failure.
*/
int do_get(uint16_t key, uint16_t buf_size, void *buf, uint16_t &actual_size,
int validate_only);
/**
* @brief Actual logics of set API (covers also set_once and remove APIs).
*
* @param[in] key key.
* @param[in] buf_size Buffer size (bytes).
* @param[in] buf Input Buffer.
* @param[in] flags Record flags.
*
* @returns 0 for success, nonzero for failure.
*/
int do_set(uint16_t key, uint16_t buf_size, const void *buf, uint16_t flags);
};
/** @}*/
#endif // NVSTORE_ENABLED
#endif

View File

@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "SystemStorage.h"
#include "features/storage/blockdevice/BlockDevice.h"
#include "features/storage/filesystem/FileSystem.h"
#include "features/storage/filesystem/fat/FATFileSystem.h"
@ -47,31 +46,6 @@
using namespace mbed;
MBED_WEAK int avoid_conflict_nvstore_tdbstore(owner_type_e in_mem_owner)
{
int status = MBED_SUCCESS;
static PlatformMutex _mutex;
static owner_type_e internal_memory_owner = NONE;
_mutex.lock();
if (internal_memory_owner != NONE &&
internal_memory_owner != in_mem_owner) {
status = MBED_ERROR_ALREADY_INITIALIZED;
} else {
internal_memory_owner = in_mem_owner;
}
_mutex.unlock();
return status;
}
// Align a value to a specified size.
// Parameters :
// val - [IN] Value.

View File

@ -1,36 +0,0 @@
/*
* Copyright (c) 2018 ARM Limited. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBED_SYSTEM_STORAGE_H
#define MBED_SYSTEM_STORAGE_H
#include "mbed_error.h"
typedef enum {
NONE = 0,
NVSTORE,
TDBSTORE
} owner_type_e;
/**
* @brief Try to get an ownership for the internal flash memory storage type.
* KVSTORE or NVSTORE is the current option and once the ownership is taken by one
* second one can not be initialize.
* @param[in] in_mem_owner Enum parameter to specify NVSTORE or KVSTORE as the storage owner
* @returns MBED_SUCCESS if succeeded or MBED_ERROR_ALREADY_INITIALIZED if fails.
*/
int avoid_conflict_nvstore_tdbstore(owner_type_e in_mem_owner);
#endif

View File

@ -166,22 +166,6 @@
"test" : false,
"auto-update" : true
},
{
"name": "mbed-os-example-nvstore",
"github":"https://github.com/ARMmbed/mbed-os-example-nvstore",
"sub-repo-example": false,
"subs": [],
"features" : [],
"targets" : ["K66F", "FVP_MPS2_M3"],
"toolchains" : [],
"exporters": [],
"compile" : true,
"export": true,
"test" : true,
"baud_rate": 9600,
"compare_log": ["mbed-os-example-nvstore/tests/nvstore.log"],
"auto-update" : true
},
{
"name": "mbed-os-example-devicekey",
"github":"https://github.com/ARMmbed/mbed-os-example-devicekey",