SDHI_driver patch (mbedOS 5.11.5)
Diff: mbed-os-program/mbed-os/features/storage/kvstore/conf/kv_config.cpp
- Revision:
- 2:7c75ab32d7c9
diff -r b07be64e592e -r 7c75ab32d7c9 mbed-os-program/mbed-os/features/storage/kvstore/conf/kv_config.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-os-program/mbed-os/features/storage/kvstore/conf/kv_config.cpp Fri Mar 29 19:47:34 2019 +0200 @@ -0,0 +1,1167 @@ +/* + * 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 "kv_config.h" +#include "KVStore.h" +#include "KVMap.h" +#include "BlockDevice.h" +#include "FileSystem.h" +#include "FileSystemStore.h" +#include "SlicingBlockDevice.h" +#include "FATFileSystem.h" +#include "LittleFileSystem.h" +#include "TDBStore.h" +#include "mbed_error.h" +#include "FlashIAP.h" +#include "FlashSimBlockDevice.h" +#include "mbed_trace.h" +#include "SecureStore.h" +#define TRACE_GROUP "KVCFG" + +#if COMPONENT_FLASHIAP +#include "FlashIAPBlockDevice.h" +#endif + +#if COMPONENT_QSPIF +#include "QSPIFBlockDevice.h" +#endif + +#if COMPONENT_SPIF +#include "SPIFBlockDevice.h" +#endif + +#if COMPONENT_DATAFLASH +#include "DataFlashBlockDevice.h" +#endif + +#if COMPONENT_SD +#include "SDBlockDevice.h" +#endif + +#if COMPONENT_RZ_SDHI +#include "RZ_SDHIBlockDevice.hpp" +#endif + +/** + * @brief This function initializes internal memory secure storage + * This includes a TDBStore instance with a FlashIAPBlockdevice + * as the supported storage. + * The following is a list of configuration parameter + * MBED_CONF_STORAGE_TDB_INTERNAL_SIZE - The size of the underlying FlashIAPBlockdevice + * MBED_CONF_STORAGE_TDB_INTERNAL_BASE_ADDRESS - The start address of the underlying FlashIAPBlockdevice + * @returns 0 on success or negative value on failure. + */ +int _storage_config_TDB_INTERNAL(); + +/** + * @brief This function initialize external memory secure storage + * This includes a SecureStore class with TDBStore over FlashIAPBlockdevice + * and an external TDBStore over a default blockdevice unless configured differently. + * The following is a list of configuration parameter: + * MBED_CONF_STORAGE_TDB_EXTERNAL_RBP_INTERNAL_SIZE - Size of the internal FlashIAPBlockDevice and by + * default is set to from start address to the end of the flash. + * If start address is 0 the start address will be set to end of + * flash - rbp_internal_size. + * MBED_CONF_STORAGE_TDB_EXTERNAL_INTERNAL_BASE_ADDRESS - The satrt address of the internal FlashIAPBlockDevice. + * MBED_CONF_STORAGE_TDB_EXTERNAL_EXTERNAL_SIZE - Size of the external blockdevice in bytes or NULL for + * max possible size. + * MBED_CONF_STORAGE_TDB_EXTERNAL_EXTERNAL_BASE_ADDRESS - The block device start address. + * MBED_CONF_STORAGE_TDB_EXTERNAL_EXTERNAL_BLOCK_DEVICE - Alowed vlaues are: default, SPIF, DATAFASH, QSPIF or SD + * @returns 0 on success or negative value on failure. + */ +int _storage_config_TDB_EXTERNAL(); + +/** + * @brief This function initialize a external memory secure storage + * This includes a SecureStore class with external TDBStore over a blockdevice or, + * if no blockdevice was set the default blockdevice will be used. + * The following is a list of configuration parameter: + * MBED_CONF_STORAGE_TDB_EXTERNAL_NO_RBP_EXTERNAL_SIZE - Size of the external blockdevice in bytes + * or NULL for max possible size. + * MBED_CONF_STORAGE_TDB_EXTERNAL_NO_RBP_EXTERNAL_BASE_ADDRESS - The block device start address + * MBED_CONF_STORAGE_TDB_EXTERNAL_NO_RBP_EXTERNAL_BLOCK_DEVICE - Alowed vlaues are: default, SPIF, DATAFASH, QSPIF or SD + * @returns 0 on success or negative value on failure. + */ +int _storage_config_TDB_EXTERNAL_NO_RBP(); + +/** + * @brief This function initialize a FILESYSTEM memory secure storage + * This includes a SecureStore class with TDBStore over FlashIAPBlockdevice + * in the internal memory and an external FileSysteStore. If blockdevice and filesystem not set, + * the system will use the default block device and default filesystem + * The following is a list of configuration parameter: + * MBED_CONF_STORAGE_FILESYSTEM_RBP_INTERNAL_SIZE - Size of the internal FlashIAPBlockDevice and by + * default is set to from start address to the end of the flash. + * If start address is 0 the start address will be set to end of + * flash - rbp_internal_size. + * MBED_CONF_STORAGE_FILESYSTEM_INTERNAL_BASE_ADDRESS - The satrt address of the internal FlashIAPBlockDevice. + * MBED_CONF_STORAGE_FILESYSTEM_FILESYSTEM - Allowed values are: default, FAT or LITTLE + * MBED_CONF_STORAGE_FILESYSTEM_BLOCKDEVICE - Allowed values are: default, SPIF, DATAFASH, QSPIF or SD + * MBED_CONF_STORAGE_FILESYSTEM_EXTERNAL_SIZE - External Blockdevice size in bytes or NULL for max possible size. + * MBED_CONF_STORAGE_FILESYSTEM_EXTERNAL_BASE_ADDRESS - The block device start address. + * MBED_CONF_STORAGE_FILESYSTEM_MOUNT_POINT - Where to mount the filesystem + * MBED_CONF_STORAGE_FILESYSTEM_FOLDER_PATH - The working folder paths + * + * @returns 0 on success or negative value on failure. + */ +int _storage_config_FILESYSTEM(); + +/** + * @brief This function initialize a FILESYSTEM_NO_RBP memory secure storage with no + * rollback protection. This includes a SecureStore class an external FileSysteStore over a default + * filesystem with default blockdevice unless differently configured. + * The following is a list of configuration parameter: + * MBED_CONF_STORAGE_FILESYSTEM_NO_RBP_FILESYSTEM - Allowed values are: default, FAT or LITTLE + * MBED_CONF_STORAGE_FILESYSTEM_NO_RBP_BLOCKDEVICE - Allowed values are: default, SPIF, DATAFASH, QSPIF or SD + * MBED_CONF_STORAGE_FILESYSTEM_NO_RBP_EXTERNAL_SIZE - Blockdevice size in bytes. or NULL for max possible size. + * MBED_CONF_STORAGE_FILESYSTEM_NO_RBP_EXTERNAL_BASE_ADDRESS - The block device start address. + * MBED_CONF_STORAGE_FILESYSTEM_NO_RBP_MOUNT_POINT - Where to mount the filesystem + * MBED_CONF_STORAGE_FILESYSTEM_NO_RBP_FOLDER_PATH - The working folder paths + * + * @returns 0 on success or negative value on failure. + */ +int _storage_config_FILESYSTEM_NO_RBP(); + +int _storage_config_tdb_external_common(); +int _storage_config_filesystem_common(); + +static const char *filesystemstore_folder_path = NULL; + +using namespace mbed; + + +static SingletonPtr<PlatformMutex> mutex; +static bool is_kv_config_initialize = false; +static kvstore_config_t kvstore_config; + +#define INTERNAL_BLOCKDEVICE_NAME FLASHIAP + +#define STR_EXPAND(tok) #tok +#define STR(tok) STR_EXPAND(tok) + +#define _GET_FILESYSTEM_concat(dev, ...) _get_filesystem_##dev(__VA_ARGS__) +#define GET_FILESYSTEM(dev, ...) _GET_FILESYSTEM_concat(dev, __VA_ARGS__) + +#define _GET_BLOCKDEVICE_concat(dev, ...) _get_blockdevice_##dev(__VA_ARGS__) +#define GET_BLOCKDEVICE(dev, ...) _GET_BLOCKDEVICE_concat(dev, __VA_ARGS__) + +static inline uint32_t align_up(uint64_t val, uint64_t size) +{ + return (((val - 1) / size) + 1) * size; +} + +static inline uint32_t align_down(uint64_t val, uint64_t size) +{ + return (((val) / size)) * size; +} + +int _calculate_blocksize_match_tdbstore(BlockDevice *bd) +{ + bd_size_t size = bd->size(); + bd_size_t erase_size = bd->get_erase_size(); + bd_size_t number_of_sector = size / erase_size; + + if (number_of_sector < 2) { + tr_warning("KV Config: There are less than two sectors - TDBStore will not work."); + return -1; + } + + + if (number_of_sector % 2 != 0) { + tr_warning("KV Config: Number of sectors is not an even number. Consider changing the BlockDevice size"); + } + + return MBED_SUCCESS; +} + +int _get_addresses(BlockDevice *bd, bd_addr_t start_address, bd_size_t size, bd_addr_t *out_start_addr, + bd_addr_t *out_end_addr) +{ + bd_addr_t aligned_end_address; + bd_addr_t end_address; + bd_addr_t aligned_start_address; + + aligned_start_address = align_down(start_address, bd->get_erase_size(start_address)); + if (aligned_start_address != start_address) { + tr_error("KV Config: Start address is not aligned. Better use %02llx", aligned_start_address); + return -1; + } + + if (size == 0) { + (*out_start_addr) = aligned_start_address; + (*out_end_addr) = bd->size(); + return 0; + } + + end_address = start_address + size; + aligned_end_address = align_up(end_address, bd->get_erase_size(end_address)); + if (aligned_end_address != end_address) { + tr_error("KV Config: End address is not aligned. Consider changing the size parameter."); + return -1; + } + + if (aligned_end_address > bd->size()) { + tr_error("KV Config: End address is out of boundaries"); + return -1; + } + + (*out_start_addr) = aligned_start_address; + (*out_end_addr) = aligned_end_address; + return 0; +} + +FileSystem *_get_filesystem_FAT(const char *mount) +{ + static FATFileSystem sdcard(mount); + return &sdcard; + +} + +FileSystem *_get_filesystem_LITTLE(const char *mount) +{ + static LittleFileSystem flash(mount); + return &flash; +} + +FileSystemStore *_get_file_system_store(FileSystem *fs) +{ + static FileSystemStore fss(fs); + return &fss; +} + +FileSystem *_get_filesystem_default(const char *mount) +{ +#if COMPONENT_QSPIF || COMPONENT_SPIF || COMPONENT_DATAFLASH + return _get_filesystem_LITTLE(mount); +#elif (COMPONENT_SD || COMPONENT_RZ_SDHI) + return _get_filesystem_FAT(mount); +#else + return NULL; +#endif +} + +//Calculates the start address of FLASHIAP block device for TDB_INTERNAL profile. +//If possible, the address will start 2 sectors after the end of code sector allowing +//some space for an application update. +int _get_flashiap_bd_default_addresses_tdb_internal(bd_addr_t *start_address, bd_size_t *size) +{ +#if COMPONENT_FLASHIAP + + FlashIAP flash; + + if (*start_address != 0 || *size != 0) { + return MBED_ERROR_INVALID_ARGUMENT; + } + + //If default values are set, we should get the maximum available size of internal bd. + if (flash.init() != 0) { + return MBED_ERROR_FAILED_OPERATION; + } + + *start_address = align_up(FLASHIAP_APP_ROM_END_ADDR, flash.get_sector_size(FLASHIAP_APP_ROM_END_ADDR)); + + // Give the application a couple of spare sectors to grow (if there are such) + bd_size_t spare_size_for_app = 0; + bd_addr_t curr_addr = *start_address; + bd_addr_t flash_end_address = flash.get_flash_start() + flash.get_flash_size(); + + int spare_sectors_for_app = 2; + int min_sectors_for_storage = 2; + for (int i = 0; i < spare_sectors_for_app + min_sectors_for_storage - 1; i++) { + bd_size_t sector_size = flash.get_sector_size(curr_addr); + curr_addr += sector_size; + if (curr_addr >= flash_end_address) { + spare_size_for_app = 0; + break; + } + + if (i < spare_sectors_for_app) { + spare_size_for_app += sector_size; + } + } + *start_address += spare_size_for_app; + + flash.deinit(); + +#endif + + return MBED_SUCCESS; +} + +//Calculates address and size for FLASHIAP block device in TDB_EXTERNAL and FILESYSTEM profiles. +//The size of the block device will be 2 sectors at the ends of the internal flash for +//the use of the rbp internal TDBStore. +int _get_flashiap_bd_default_addresses_rbp(bd_addr_t *start_address, bd_size_t *size) +{ +#if COMPONENT_FLASHIAP + + bd_addr_t flash_end_address; + bd_addr_t flash_start_address; + bd_addr_t aligned_start_address; + bd_addr_t flash_first_writable_sector_address; + FlashIAP flash; + + if (*start_address != 0 || *size != 0) { + return MBED_ERROR_INVALID_ARGUMENT; + } + + int ret = flash.init(); + if (ret != 0) { + return MBED_ERROR_INITIALIZATION_FAILED; + } + + flash_first_writable_sector_address = align_up(FLASHIAP_APP_ROM_END_ADDR, flash.get_sector_size(FLASHIAP_APP_ROM_END_ADDR)); + flash_start_address = flash.get_flash_start(); + flash_end_address = flash_start_address + flash.get_flash_size();; + *start_address = flash_end_address - 1; + aligned_start_address = align_down(*start_address, flash.get_sector_size(*start_address)); + *size = (flash_end_address - aligned_start_address) * 2; + *start_address = (flash_end_address - *size); + aligned_start_address = align_down(*start_address, flash.get_sector_size(*start_address)); + + flash.deinit(); + + if (aligned_start_address < flash_first_writable_sector_address) { + tr_error("KV Config: Internal block device start address overlapped ROM address "); + return MBED_ERROR_INITIALIZATION_FAILED; + } + +#endif + + return MBED_SUCCESS; + +} + +BlockDevice *_get_blockdevice_FLASHIAP(bd_addr_t start_address, bd_size_t size) +{ +#if COMPONENT_FLASHIAP + + bd_addr_t flash_end_address; + bd_addr_t flash_start_address; + bd_addr_t flash_first_writable_sector_address; + bd_addr_t aligned_start_address; + bd_addr_t aligned_end_address; + bd_addr_t end_address; + FlashIAP flash; + + int ret = flash.init(); + if (ret != 0) { + return NULL; + } + + //Get flash parameters before starting + flash_first_writable_sector_address = align_up(FLASHIAP_APP_ROM_END_ADDR, flash.get_sector_size(FLASHIAP_APP_ROM_END_ADDR)); + flash_start_address = flash.get_flash_start(); + flash_end_address = flash_start_address + flash.get_flash_size();; + + //Non default configuration + if (start_address != 0) { + + aligned_start_address = align_down(start_address, flash.get_sector_size(start_address)); + if (start_address != aligned_start_address) { + tr_error("KV Config: Internal block device start address is not aligned. Better use %02llx", aligned_start_address); + flash.deinit(); + return NULL; + } + + if (size == 0) { + //The block device will have all space form start address to the end of the flash + size = (flash_end_address - start_address); + + static FlashIAPBlockDevice bd(start_address, size); + flash.deinit(); + return &bd; + } + + if (size != 0) { + end_address = start_address + size; + if (end_address > flash_end_address) { + tr_error("KV Config: Internal block device end address is out of boundaries"); + flash.deinit(); + return NULL; + } + + aligned_end_address = align_up(end_address, flash.get_sector_size(end_address - 1)); + if (end_address != aligned_end_address) { + tr_error("KV Config: Internal block device start address is not aligned. Consider changing the size parameter"); + flash.deinit(); + return NULL; + } + + static FlashIAPBlockDevice bd(start_address, size); + flash.deinit(); + return &bd; + } + } + + //Non default configuration start_address = 0 + start_address = flash_end_address - size; + aligned_start_address = align_down(start_address, flash.get_sector_size(start_address)); + if (start_address != aligned_start_address) { + tr_error("KV Config: Internal block device start address is not aligned. Consider changing the size parameter"); + flash.deinit(); + return NULL; + } + + flash.deinit(); + + if (aligned_start_address < flash_first_writable_sector_address) { + tr_error("KV Config: Internal block device start address overlapped ROM address "); + return NULL; + } + static FlashIAPBlockDevice bd(aligned_start_address, size); + return &bd; + +#else + return NULL; +#endif +} + +BlockDevice *_get_blockdevice_SPIF(bd_addr_t start_address, bd_size_t size) +{ +#if COMPONENT_SPIF + + bd_addr_t aligned_end_address; + bd_addr_t aligned_start_address; + + static SPIFBlockDevice bd( + MBED_CONF_SPIF_DRIVER_SPI_MOSI, + MBED_CONF_SPIF_DRIVER_SPI_MISO, + MBED_CONF_SPIF_DRIVER_SPI_CLK, + MBED_CONF_SPIF_DRIVER_SPI_CS, + MBED_CONF_SPIF_DRIVER_SPI_FREQ + ); + + if (bd.init() != MBED_SUCCESS) { + tr_error("KV Config: SPIFBlockDevice init fail"); + return NULL; + } + + if (start_address == 0 && size == 0) { + return &bd; + } + + //If address and size were specified use SlicingBlockDevice to get the correct block device size and start address. + if (_get_addresses(&bd, start_address, size, &aligned_start_address, &aligned_end_address) != 0) { + tr_error("KV Config: Fail to get addresses for SlicingBlockDevice."); + return NULL; + } + + static SlicingBlockDevice sbd(&bd, aligned_start_address, aligned_end_address); + return &sbd; + +#else + return NULL; +#endif +} + +BlockDevice *_get_blockdevice_QSPIF(bd_addr_t start_address, bd_size_t size) +{ +#if COMPONENT_QSPIF + + bd_addr_t aligned_end_address; + bd_addr_t aligned_start_address; + + static QSPIFBlockDevice bd( + QSPI_FLASH1_IO0, + QSPI_FLASH1_IO1, + QSPI_FLASH1_IO2, + QSPI_FLASH1_IO3, + QSPI_FLASH1_SCK, + QSPI_FLASH1_CSN, + QSPIF_POLARITY_MODE_0, + MBED_CONF_QSPIF_QSPI_FREQ + ); + + if (bd.init() != MBED_SUCCESS) { + tr_error("KV Config: QSPIFBlockDevice init fail"); + return NULL; + } + + if (start_address == 0 && size == 0) { + return &bd; + } + + //If address and size were specified use SlicingBlockDevice to get the correct block device size and start address. + if (_get_addresses(&bd, start_address, size, &aligned_start_address, &aligned_end_address) != 0) { + tr_error("KV Config: Fail to get addresses for SlicingBlockDevice."); + return NULL; + } + + static SlicingBlockDevice sbd(&bd, aligned_start_address, aligned_end_address); + return &sbd; + +#else + return NULL; +#endif +} + +BlockDevice *_get_blockdevice_DATAFLASH(bd_addr_t start_address, bd_size_t size) +{ +#if COMPONENT_DATAFLASH + + bd_addr_t aligned_end_address; + bd_addr_t aligned_start_address; + + static DataFlashBlockDevice bd( + MBED_CONF_DATAFLASH_SPI_MOSI, + MBED_CONF_DATAFLASH_SPI_MISO, + MBED_CONF_DATAFLASH_SPI_CLK, + MBED_CONF_DATAFLASH_SPI_CS + ); + + if (bd.init() != MBED_SUCCESS) { + tr_error("KV Config: DataFlashBlockDevice init fail"); + return NULL; + } + + if (start_address == 0 && size == 0) { + return &bd; + } + + //If address and size were specified use SlicingBlockDevice to get the correct block device size and start address. + if (_get_addresses(&bd, start_address, size, &aligned_start_address, &aligned_end_address) != 0) { + tr_error("KV Config: Fail to get addresses for SlicingBlockDevice."); + return NULL; + } + + static SlicingBlockDevice sbd(&bd, aligned_start_address, aligned_end_address); + return &sbd; + + +#else + return NULL; +#endif +} + +BlockDevice *_get_blockdevice_SD(bd_addr_t start_address, bd_size_t size) +{ +#if COMPONENT_SD + + bd_addr_t aligned_end_address; + bd_addr_t aligned_start_address; + + static SDBlockDevice bd( + MBED_CONF_SD_SPI_MOSI, + MBED_CONF_SD_SPI_MISO, + MBED_CONF_SD_SPI_CLK, + MBED_CONF_SD_SPI_CS + ); + + if (bd.init() != MBED_SUCCESS) { + tr_error("KV Config: SDBlockDevice init fail"); + return NULL; + } + + if (strcmp(STR(MBED_CONF_STORAGE_STORAGE_TYPE), "TDB_EXTERNAL_NO_RBP") == 0 || + strcmp(STR(MBED_CONF_STORAGE_STORAGE_TYPE), "TDB_EXTERNAL") == 0) { + //In TDBStore profile, we have a constraint of 4GByte + if (start_address == 0 && size == 0 && bd.size() < (uint32_t)(-1)) { + return &bd; + } + + //If the size of external storage is bigger than 4G we need to slice it. + size = size != 0 ? size : align_down(bd.size(), bd.get_erase_size(bd.size() - 1)); + + if (_get_addresses(&bd, start_address, size, &aligned_start_address, &aligned_end_address) != 0) { + tr_error("KV Config: Fail to get addresses for SlicingBlockDevice."); + return NULL; + } + + if (aligned_end_address - aligned_start_address != (uint32_t)(aligned_end_address - aligned_start_address)) { + aligned_end_address = aligned_start_address + (uint32_t)(-1);//Support up to 4G only + } + } else { + //For all other KVStore profiles beside TDBStore we take the entire external memory space. + if (start_address == 0 && size == 0) { + return &bd; + } + + if (_get_addresses(&bd, start_address, size, &aligned_start_address, &aligned_end_address) != 0) { + tr_error("KV Config: Fail to get addresses for SlicingBlockDevice."); + return NULL; + } + } + + aligned_end_address = align_down(aligned_end_address, bd.get_erase_size(aligned_end_address)); + static SlicingBlockDevice sbd(&bd, aligned_start_address, aligned_end_address); + return &sbd; + +#else + return NULL; +#endif +} + +BlockDevice *_get_blockdevice_RZ_SDHI(bd_addr_t start_address, bd_size_t size) +{ +#if COMPONENT_RZ_SDHI + + bd_addr_t aligned_end_address; + bd_addr_t aligned_start_address; + + static SDHIBlockDevice bd(MBED_CONF_RZ_SDHI_CH); + + if (bd.init() != MBED_SUCCESS) { + tr_error("KV Config: SDBlockDevice init fail"); + return NULL; + } + + if (strcmp(STR(MBED_CONF_STORAGE_STORAGE_TYPE), "TDB_EXTERNAL_NO_RBP") == 0 || + strcmp(STR(MBED_CONF_STORAGE_STORAGE_TYPE), "TDB_EXTERNAL") == 0) { + //In TDBStore profile, we have a constraint of 4GByte + if (start_address == 0 && size == 0 && bd.size() < (uint32_t)(-1)) { + return &bd; + } + + //If the size of external storage is bigger than 4G we need to slice it. + size = size != 0 ? size : align_down(bd.size(), bd.get_erase_size(bd.size() - 1)); + + if (_get_addresses(&bd, start_address, size, &aligned_start_address, &aligned_end_address) != 0) { + tr_error("KV Config: Fail to get addresses for SlicingBlockDevice."); + return NULL; + } + + if (aligned_end_address - aligned_start_address != (uint32_t)(aligned_end_address - aligned_start_address)) { + aligned_end_address = aligned_start_address + (uint32_t)(-1);//Support up to 4G only + } + } else { + //For all other KVStore profiles beside TDBStore we take the entire external memory space. + if (start_address == 0 && size == 0) { + return &bd; + } + + if (_get_addresses(&bd, start_address, size, &aligned_start_address, &aligned_end_address) != 0) { + tr_error("KV Config: Fail to get addresses for SlicingBlockDevice."); + return NULL; + } + } + + aligned_end_address = align_down(aligned_end_address, bd.get_erase_size(aligned_end_address)); + static SlicingBlockDevice sbd(&bd, aligned_start_address, aligned_end_address); + return &sbd; + +#else + return NULL; +#endif +} + +BlockDevice *_get_blockdevice_default(bd_addr_t start_address, bd_size_t size) +{ +#if COMPONENT_QSPIF + return _get_blockdevice_QSPIF(start_address, size); +#elif COMPONENT_SPIF + return _get_blockdevice_SPIF(start_address, size); +#elif COMPONENT_DATAFLASH + return _get_blockdevice_DATAFLASH(start_address, size); +#elif COMPONENT_SD + return _get_blockdevice_SD(start_address, size); +#elif COMPONENT_RZ_SDHI + return _get_blockdevice_RZ_SDHI(start_address, size); +#else + tr_error("KV Config: No default component define in target.json for this target."); + return NULL; +#endif +} + +int _storage_config_TDB_INTERNAL() +{ +#if COMPONENT_FLASHIAP + bd_size_t internal_size = MBED_CONF_STORAGE_TDB_INTERNAL_INTERNAL_SIZE; + bd_addr_t internal_start_address = MBED_CONF_STORAGE_TDB_INTERNAL_INTERNAL_BASE_ADDRESS; + + if (internal_size == 0 && internal_start_address == 0) { + //Calculate the block device size and start address in case default values are used. + if (_get_flashiap_bd_default_addresses_tdb_internal(&internal_start_address, &internal_size) != MBED_SUCCESS) { + return MBED_ERROR_FAILED_OPERATION; + } + } + + //Get internal memory FLASHIAP block device. + kvstore_config.internal_bd = GET_BLOCKDEVICE(INTERNAL_BLOCKDEVICE_NAME, internal_start_address, internal_size); + if (kvstore_config.internal_bd == NULL) { + tr_error("KV Config: Fail to get internal BlockDevice."); + return MBED_ERROR_FAILED_OPERATION; + } + + + int ret = kvstore_config.internal_bd->init(); + if (ret != MBED_SUCCESS) { + tr_error("KV Config: Fail to init internal BlockDevice."); + return MBED_ERROR_FAILED_OPERATION; + } + + //Check that internal flash has 2 or more sectors + if (_calculate_blocksize_match_tdbstore(kvstore_config.internal_bd) != MBED_SUCCESS) { + tr_error("KV Config: Can not create TDBStore with less then 2 sector."); + return MBED_ERROR_INVALID_ARGUMENT; + } + + //Deinitialize internal block device and TDB will reinitialize and take control on it. + ret = kvstore_config.internal_bd->deinit(); + if (ret != MBED_SUCCESS) { + tr_error("KV Config: Fail to deinit internal BlockDevice."); + return MBED_ERROR_FAILED_OPERATION; + } + + //Create a TDBStore in the internal FLASHIAP block device. + static TDBStore tdb_internal(kvstore_config.internal_bd); + kvstore_config.internal_store = &tdb_internal; + + ret = kvstore_config.internal_store->init(); + if (ret != MBED_SUCCESS) { + tr_error("KV Config: Fail to init internal TDBStore."); + return ret; + } + kvstore_config.kvstore_main_instance = + kvstore_config.internal_store; + + //Masking flag - Actually used to remove any KVStore flag which is not supported + //in the chosen KVStore profile. + kvstore_config.flags_mask = ~(KVStore::REQUIRE_CONFIDENTIALITY_FLAG | + KVStore::REQUIRE_REPLAY_PROTECTION_FLAG); + + //Initialize kv_map and add the configuration struct to KVStore map. + KVMap &kv_map = KVMap::get_instance(); + ret = kv_map.init(); + if (MBED_SUCCESS != ret) { + tr_error("KV Config: Fail to init KVStore global API."); + return ret; + } + + ret = kv_map.attach(STR(MBED_CONF_STORAGE_DEFAULT_KV), &kvstore_config); + if (MBED_SUCCESS != ret) { + tr_error("KV Config: Fail to attach KVStore main instance to KVStore global API."); + return ret; + } + return MBED_SUCCESS; +#else + return MBED_ERROR_UNSUPPORTED; +#endif + +} + +int _storage_config_TDB_EXTERNAL() +{ +#if !SECURESTORE_ENABLED + return MBED_ERROR_UNSUPPORTED; +#endif + + bd_size_t internal_rbp_size = MBED_CONF_STORAGE_TDB_EXTERNAL_RBP_INTERNAL_SIZE; + bd_addr_t internal_start_address = MBED_CONF_STORAGE_TDB_EXTERNAL_INTERNAL_BASE_ADDRESS; + + //Get the default address and size for internal rbp TDBStore + if (internal_rbp_size == 0 && internal_start_address == 0) { + //Calculate the block device size and start address in case default values are used. + if (_get_flashiap_bd_default_addresses_rbp(&internal_start_address, &internal_rbp_size) != MBED_SUCCESS) { + return MBED_ERROR_FAILED_OPERATION; + } + } + + //Create internal FLASHIAP block device + kvstore_config.internal_bd = GET_BLOCKDEVICE(INTERNAL_BLOCKDEVICE_NAME, internal_start_address, internal_rbp_size); + if (kvstore_config.internal_bd == NULL) { + tr_error("KV Config: Fail to get internal BlockDevice."); + return MBED_ERROR_FAILED_OPERATION ; + } + + int ret = kvstore_config.internal_bd->init(); + if (ret != MBED_SUCCESS) { + tr_error("KV Config: Fail to init internal BlockDevice."); + return MBED_ERROR_FAILED_OPERATION ; + } + + //Check if TDBStore has at least 2 sector. + if (_calculate_blocksize_match_tdbstore(kvstore_config.internal_bd) != MBED_SUCCESS) { + tr_error("KV Config: Can not create TDBStore with less then 2 sector."); + return MBED_ERROR_INVALID_ARGUMENT; + } + + //Create internal TDBStore + static TDBStore tdb_internal(kvstore_config.internal_bd); + kvstore_config.internal_store = &tdb_internal; + + ret = kvstore_config.internal_store->init(); + if (ret != MBED_SUCCESS) { + tr_error("KV Config: Fail to init internal TDBStore."); + return ret; + } + + bd_size_t size = MBED_CONF_STORAGE_TDB_EXTERNAL_EXTERNAL_SIZE; + bd_addr_t address = MBED_CONF_STORAGE_TDB_EXTERNAL_EXTERNAL_BASE_ADDRESS; + + //Get external BlockDevice for TDBStore + BlockDevice *bd = GET_BLOCKDEVICE(MBED_CONF_STORAGE_TDB_EXTERNAL_BLOCKDEVICE, address, size); + if (bd == NULL) { + tr_error("KV Config: Fail to get external BlockDevice."); + return MBED_ERROR_FAILED_OPERATION ; + } + + //TDBStore needs a block device base on flash. so if this is SD block device or the default block device is SD + //add FlashSimBlockDevice on top of the SDBlockDevice +#if defined(COMPONENT_SD) || defined(COMPONENT_RZ_SDHI) + if (strcmp(STR(MBED_CONF_STORAGE_TDB_EXTERNAL_BLOCKDEVICE), "SD") == 0 +#if (defined(COMPONENT_SD) || defined(COMPONENT_RZ_SDHI))&& !defined(COMPONENT_SPIF) && !defined(COMPONENT_QSPIF) && !defined(COMPONENT_DATAFLASH) + || strcmp(STR(MBED_CONF_STORAGE_TDB_EXTERNAL_BLOCKDEVICE), "default") == 0) { +#else + ) { + +#endif + //TDBStore need FlashSimBlockDevice when working with SD block device + if (bd->init() != MBED_SUCCESS) { + tr_error("KV Config: Fail to init external BlockDevice."); + return MBED_ERROR_FAILED_OPERATION ; + } + + static FlashSimBlockDevice flash_bd(bd); + kvstore_config.external_bd = &flash_bd; + } else { + kvstore_config.external_bd = bd; + } +#else + kvstore_config.external_bd = bd; +#endif + + kvstore_config.flags_mask = ~(0); + + return _storage_config_tdb_external_common(); +} + +int _storage_config_TDB_EXTERNAL_NO_RBP() +{ +#if !SECURESTORE_ENABLED + return MBED_ERROR_UNSUPPORTED; +#endif + bd_size_t size = MBED_CONF_STORAGE_TDB_EXTERNAL_NO_RBP_EXTERNAL_SIZE; + bd_addr_t address = MBED_CONF_STORAGE_TDB_EXTERNAL_NO_RBP_EXTERNAL_BASE_ADDRESS; + + //Get external block device + BlockDevice *bd = GET_BLOCKDEVICE(MBED_CONF_STORAGE_TDB_EXTERNAL_NO_RBP_BLOCKDEVICE, address, size); + if (bd == NULL) { + tr_error("KV Config: Fail to get external BlockDevice."); + return MBED_ERROR_FAILED_OPERATION ; + } + + //TDBStore needs a block device base on flash. so if this is SD block device or the default block device is SD + //add FlashSimBlockDevice on top of the SDBlockDevice +#if defined(COMPONENT_SD) || defined(COMPONENT_RZ_SDHI) + if (strcmp(STR(MBED_CONF_STORAGE_TDB_EXTERNAL_NO_RBP_BLOCKDEVICE), "SD") == 0 +#if (defined(COMPONENT_SD) || defined(COMPONENT_RZ_SDHI)) && !defined(COMPONENT_SPIF) && !defined(COMPONENT_QSPIF) && !defined(COMPONENT_DATAFLASH) + || strcmp(STR(MBED_CONF_STORAGE_TDB_EXTERNAL_NO_RBP_BLOCKDEVICE), "default") == 0) { +#else + ) { + +#endif + //TDBStore need FlashSimBlockDevice when working with SD block device + if (bd->init() != MBED_SUCCESS) { + tr_error("KV Config: Fail to init external BlockDevice."); + return MBED_ERROR_FAILED_OPERATION ; + } + + static FlashSimBlockDevice flash_bd(bd); + kvstore_config.external_bd = &flash_bd; + } else { + kvstore_config.external_bd = bd; + } +#else + kvstore_config.external_bd = bd; +#endif + + //Masking flag - Actually used to remove any KVStore flag which is not supported + //in the chosen KVStore profile. + kvstore_config.flags_mask = ~(KVStore::REQUIRE_REPLAY_PROTECTION_FLAG); + + return _storage_config_tdb_external_common(); +} + +int _storage_config_tdb_external_common() +{ +#if SECURESTORE_ENABLED + //Initialize external block device + int ret = kvstore_config.external_bd->init(); + if (ret != MBED_SUCCESS) { + tr_error("KV Config: Fail to init external BlockDevice."); + return MBED_ERROR_FAILED_OPERATION ; + } + + //Check that there is at least 2 sector for the external TDBStore + if (_calculate_blocksize_match_tdbstore(kvstore_config.external_bd) != MBED_SUCCESS) { + tr_error("KV Config: Can not create TDBStore with less then 2 sector."); + return MBED_ERROR_INVALID_SIZE; + } + + //Create external TDBStore + static TDBStore tdb_external(kvstore_config.external_bd); + kvstore_config.external_store = &tdb_external; + + //Create SecureStore and initialize it + static SecureStore secst(kvstore_config.external_store, kvstore_config.internal_store); + + ret = secst.init(); + if (ret != MBED_SUCCESS) { + tr_error("KV Config: Fail to init SecureStore."); + return ret ; + } + + kvstore_config.kvstore_main_instance = &secst; + + //Init kv_map and add the configuration struct to KVStore map. + KVMap &kv_map = KVMap::get_instance(); + ret = kv_map.init(); + if (MBED_SUCCESS != ret) { + tr_error("KV Config: Fail to init KVStore global API"); + return ret; + } + + ret = kv_map.attach(STR(MBED_CONF_STORAGE_DEFAULT_KV), &kvstore_config); + if (MBED_SUCCESS != ret) { + tr_error("KV Config: Fail to attach KvStore main instance to KVStore global API"); + return ret; + } + + return MBED_SUCCESS; +#else + return MBED_ERROR_UNSUPPORTED; +#endif +} + +int _storage_config_FILESYSTEM() +{ +#if !SECURESTORE_ENABLED + return MBED_ERROR_UNSUPPORTED; +#endif + + filesystemstore_folder_path = STR(MBED_CONF_STORAGE_FILESYSTEM_FOLDER_PATH); + + bd_size_t internal_rbp_size = MBED_CONF_STORAGE_FILESYSTEM_RBP_INTERNAL_SIZE; + bd_addr_t internal_start_address = MBED_CONF_STORAGE_FILESYSTEM_INTERNAL_BASE_ADDRESS; + + //Get the default address and size for internal rbp TDBStore + if (internal_rbp_size == 0 && internal_start_address == 0) { + //Calculate the block device size and start address in case default values are used. + if (_get_flashiap_bd_default_addresses_rbp(&internal_start_address, &internal_rbp_size) != MBED_SUCCESS) { + return MBED_ERROR_FAILED_OPERATION; + } + } + + //Get internal FLASHIAP block device + kvstore_config.internal_bd = GET_BLOCKDEVICE(INTERNAL_BLOCKDEVICE_NAME, internal_start_address, internal_rbp_size); + if (kvstore_config.internal_bd == NULL) { + tr_error("KV Config: Fail to get internal BlockDevice "); + return MBED_ERROR_FAILED_OPERATION ; + } + + int ret = kvstore_config.internal_bd->init(); + if (ret != MBED_SUCCESS) { + tr_error("KV Config: Fail to init internal BlockDevice "); + return MBED_ERROR_FAILED_OPERATION ; + } + + //Check that internal flash has 2 or more sectors + if (_calculate_blocksize_match_tdbstore(kvstore_config.internal_bd) != MBED_SUCCESS) { + tr_error("KV Config: Can not create TDBStore with less then 2 sector."); + return MBED_ERROR_INVALID_ARGUMENT; + } + + //Deinitialize internal block device and TDB will reinitialize and take control on it. + ret = kvstore_config.internal_bd->deinit(); + if (ret != MBED_SUCCESS) { + tr_error("KV Config: Fail to deinit internal BlockDevice."); + return MBED_ERROR_FAILED_OPERATION; + } + + //Create internal TDBStore for rbp + static TDBStore tdb_internal(kvstore_config.internal_bd); + kvstore_config.internal_store = &tdb_internal; + + ret = kvstore_config.internal_store->init(); + if (ret != MBED_SUCCESS) { + tr_error("KV Config: Fail to init internal TDBStore"); + return ret; + } + + bd_size_t size = MBED_CONF_STORAGE_FILESYSTEM_EXTERNAL_SIZE; + bd_addr_t address = MBED_CONF_STORAGE_FILESYSTEM_EXTERNAL_BASE_ADDRESS; + const char *mount_point = STR(MBED_CONF_STORAGE_FILESYSTEM_MOUNT_POINT); + + //Get external block device for FileSystem. + kvstore_config.external_bd = GET_BLOCKDEVICE(MBED_CONF_STORAGE_FILESYSTEM_BLOCKDEVICE, address, size); + if (kvstore_config.external_bd == NULL) { + tr_error("KV Config: Fail to get external BlockDevice "); + return MBED_ERROR_FAILED_OPERATION ; + } + + ret = kvstore_config.external_bd->init(); + if (MBED_SUCCESS != ret) { + tr_error("KV Config: Fail to init external BlockDevice "); + return MBED_ERROR_FAILED_OPERATION ; + } + + //Get FileSystem. Can be FAT, LITTLE or default. in case of default, the type will be decided base on the default + //component block device configured in the system. The priority is: + //QSPI -> SPI -> DATAFLASH == LITTLE + //SD == FAT + kvstore_config.external_fs = GET_FILESYSTEM(MBED_CONF_STORAGE_FILESYSTEM_FILESYSTEM, mount_point); + if (kvstore_config.external_fs == NULL) { + tr_error("KV Config: Fail to get FileSystem"); + return MBED_ERROR_FAILED_OPERATION ; + } + + kvstore_config.flags_mask = ~(0); + + return _storage_config_filesystem_common(); +} + +int _storage_config_FILESYSTEM_NO_RBP() +{ +#if !SECURESTORE_ENABLED + return MBED_ERROR_UNSUPPORTED; +#endif + + filesystemstore_folder_path = STR(MBED_CONF_STORAGE_FILESYSTEM_NO_RBP_FOLDER_PATH); + + bd_size_t size = MBED_CONF_STORAGE_FILESYSTEM_NO_RBP_EXTERNAL_SIZE; + bd_addr_t address = MBED_CONF_STORAGE_FILESYSTEM_NO_RBP_EXTERNAL_BASE_ADDRESS; + const char *mount_point = STR(MBED_CONF_STORAGE_FILESYSTEM_NO_RBP_MOUNT_POINT); + + //Get external block device for FileSystem. + kvstore_config.external_bd = GET_BLOCKDEVICE(MBED_CONF_STORAGE_FILESYSTEM_NO_RBP_BLOCKDEVICE, address, size); + if (kvstore_config.external_bd == NULL) { + tr_error("KV Config: Fail to get external BlockDevice "); + return MBED_ERROR_FAILED_OPERATION ; + } + + int ret = kvstore_config.external_bd->init(); + if (MBED_SUCCESS != ret) { + tr_error("KV Config: Fail to init external BlockDevice "); + return MBED_ERROR_FAILED_OPERATION ; + } + + //Get FileSystem. Can be FAT, LITTLE or default. in case of default, the type will be decided base on the default + //component block device configured in the system. The priority is: + //QSPI -> SPI -> DATAFLASH == LITTLE + //SD == FAT + kvstore_config.external_fs = GET_FILESYSTEM(MBED_CONF_STORAGE_FILESYSTEM_NO_RBP_FILESYSTEM, mount_point); + if (kvstore_config.external_fs == NULL) { + tr_error("KV Config: Fail to get FileSystem"); + return MBED_ERROR_FAILED_OPERATION ; + } + + //Masking flag - Actually used to remove any KVStore flag which is not supported + //in the chosen KVStore profile. + kvstore_config.flags_mask = ~(KVStore::REQUIRE_REPLAY_PROTECTION_FLAG); + + return _storage_config_filesystem_common(); +} + +int _storage_config_filesystem_common() +{ +#if SECURESTORE_ENABLED + + //Mount file system. if it fails, try to reformat + int ret = kvstore_config.external_fs->mount(kvstore_config.external_bd); + if (ret != MBED_SUCCESS) { + ret = kvstore_config.external_fs->reformat(kvstore_config.external_bd); + if (ret != MBED_SUCCESS) { + tr_error("KV Config: Fail to mount FileSystem to %s", + STR(MBED_CONF_STORAGE_FILESYSTEM_NO_RBP_MOUNT_POINT)); + return MBED_ERROR_FAILED_OPERATION ; + } + } + + //Create FileSystemStore + kvstore_config.external_store = _get_file_system_store(kvstore_config.external_fs); + if (kvstore_config.external_store == NULL) { + tr_error("KV Config: Fail to get FileSystemStore"); + return MBED_ERROR_FAILED_OPERATION ; + } + + //Create SecureStore and set it as main KVStore + static SecureStore secst(kvstore_config.external_store, kvstore_config.internal_store); + + ret = secst.init(); + if (ret != MBED_SUCCESS) { + tr_error("KV Config: Fail to init SecureStore."); + return ret; ; + } + + kvstore_config.kvstore_main_instance = &secst; + + //Init kv_map and add the configuration struct to KVStore map. + KVMap &kv_map = KVMap::get_instance(); + ret = kv_map.init(); + if (MBED_SUCCESS != ret) { + tr_error("KV Config: Fail to init KVStore global API"); + return ret; + } + + ret = kv_map.attach(STR(MBED_CONF_STORAGE_DEFAULT_KV), &kvstore_config); + if (MBED_SUCCESS != ret) { + tr_error("KV Config: Fail to attach KvStore main instance to KVStore global API"); + return ret; + } + + return MBED_SUCCESS; +#else + return MBED_ERROR_UNSUPPORTED; +#endif +} + +int _storage_config_default() +{ +#if COMPONENT_QSPIF || COMPONENT_SPIF || COMPONENT_DATAFLASH + return _storage_config_TDB_EXTERNAL(); +#elif (COMPONENT_SD || COMPONENT_RZ_SDHI) + return _storage_config_FILESYSTEM(); +#elif COMPONENT_FLASHIAP + return _storage_config_TDB_INTERNAL(); +#else + return MBED_ERROR_UNSUPPORTED; +#endif +} + +const char *get_filesystemstore_folder_path() +{ + return filesystemstore_folder_path; +} + +MBED_WEAK int kv_init_storage_config() +{ + + int ret = MBED_SUCCESS; + + // We currently have no supported configuration without internal storage +#ifndef COMPONENT_FLASHIAP + return MBED_ERROR_UNSUPPORTED; +#endif + + mutex->lock(); + + if (is_kv_config_initialize) { + goto exit; + } + + memset(&kvstore_config, 0, sizeof(kvstore_config_t)); + + ret = _STORAGE_CONFIG(MBED_CONF_STORAGE_STORAGE_TYPE); + + if (ret == MBED_SUCCESS) { + is_kv_config_initialize = true; + } + +exit: + mutex->unlock(); + return ret; +}