Remove ROM overlaps checkup for kvstore FLASHIAP blockdevice if non default values are use

remove of rbp_number_of_entries from the kvstore configuration. Adding default option for storage_type
allowing the system to choose TDB_INTERNAl, TDB_EXTERNAL or FILESYSTEM base on the blockdevice component
set in the target board. Adding remarks to kv_config.cpp and break simplify the _get_blockdevice_FLASHIAP function
pull/9237/head
Yossi Levy 2018-12-26 12:08:34 +02:00
parent 51b8d6e59d
commit 388da7f841
5 changed files with 229 additions and 91 deletions

View File

@ -62,6 +62,8 @@ The following is a list of all storage parameters available and their descriptio
* `TDB_EXTERNAL_NO_RBP`. * `TDB_EXTERNAL_NO_RBP`.
* `FILESYSTEM`. * `FILESYSTEM`.
* `FILESYSTEM_NO_RBP`. * `FILESYSTEM_NO_RBP`.
* `default`
If default is set, the system will choose the type of storage base on the block device component set in target.json. For QSPIF, SPIF and DATAFLASH block devices TDB_EXTERNAL will be used. If SD is set a FILESYSTEM storage is set and if only FLASHIAP exists as the only block device component, a TDB_INTERNAL will be used.
* `default_kv` - This is a string representing the path for the default KVStore instantiation. Applications can pass an empty path (only the key name) or pass the generated name for this parameter (`MBED_CONF_STORAGE_DEFAULT_KV`) as the path to use this configuration. * `default_kv` - This is a string representing the path for the default KVStore instantiation. Applications can pass an empty path (only the key name) or pass the generated name for this parameter (`MBED_CONF_STORAGE_DEFAULT_KV`) as the path to use this configuration.
* `internal_size` - The size in bytes for the internal FlashIAP block device. This, together with the `internal_base_address`, adjusts exactly the size and location where the block device resides on memory. If not defined, the block device will try to get the maximum size available. * `internal_size` - The size in bytes for the internal FlashIAP block device. This, together with the `internal_base_address`, adjusts exactly the size and location where the block device resides on memory. If not defined, the block device will try to get the maximum size available.
* `internal_base_address` - The address where the internal FlashIAP blockDevice starts. This helps to prevent collisions with other needs, such as firmware updates. If not defined, the start address will be set to the first sector after the application code ends in `TDB_internal`. In any external configurations with rollback protection support, it will be set to end of flash - `rbp_internal_size`. * `internal_base_address` - The address where the internal FlashIAP blockDevice starts. This helps to prevent collisions with other needs, such as firmware updates. If not defined, the start address will be set to the first sector after the application code ends in `TDB_internal`. In any external configurations with rollback protection support, it will be set to end of flash - `rbp_internal_size`.
@ -83,7 +85,7 @@ Below is the main storage configuration `mbed_lib.json` file:
"name": "storage", "name": "storage",
"config": { "config": {
"storage_type": { "storage_type": {
"help": "Options are TDB_INTERNAL, TDB_EXTERNAL, TDB_EXTERNAL_NO_RBP, FILESYSTEM or FILESYSTEM_NO_RBP.", "help": "Options are TDB_INTERNAL, TDB_EXTERNAL, TDB_EXTERNAL_NO_RBP, FILESYSTEM, FILESYSTEM_NO_RBP or default. If default, the storage type will be chosen according to the component defined in targets.json",
"value": "NULL" "value": "NULL"
}, },
"default_kv": { "default_kv": {

View File

@ -2,13 +2,9 @@
"name": "storage_filesystem", "name": "storage_filesystem",
"config": { "config": {
"rbp_internal_size": { "rbp_internal_size": {
"help": "If default the size will be 4K*#entries/32", "help": "Default is the size of the 2 last sectors of internal flash",
"value": "0" "value": "0"
}, },
"rbp_number_of_entries": {
"help": "If not defined default is 64",
"value": "64"
},
"internal_base_address": { "internal_base_address": {
"help": "If default, base address is the first sector after the application code", "help": "If default, base address is the first sector after the application code",
"value": "0" "value": "0"

View File

@ -68,11 +68,12 @@ int _storage_config_TDB_INTERNAL();
* and an external TDBStore over a default blockdevice unless configured differently. * and an external TDBStore over a default blockdevice unless configured differently.
* The following is a list of configuration parameter: * The following is a list of configuration parameter:
* MBED_CONF_STORAGE_TDB_EXTERNAL_RBP_INTERNAL_SIZE - Size of the internal FlashIAPBlockDevice and by * MBED_CONF_STORAGE_TDB_EXTERNAL_RBP_INTERNAL_SIZE - Size of the internal FlashIAPBlockDevice and by
* default is set to 4K*#enteries/32. The start address will be set to end of flash - rbp_internal_size. * default is set to from start address to the end of the flash.
* MBED_CONF_STORAGE_TDB_EXTERNAL_RBP_NUMBER_OF_ENTRIES - If not defined default is 64 * 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_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 * MBED_CONF_STORAGE_TDB_EXTERNAL_EXTERNAL_SIZE - Size of the external blockdevice in bytes or NULL for
* max possible size. * max possible size.
* MBED_CONF_STORAGE_TDB_EXTERNAL_EXTERNAL_BASE_ADDRESS - The block device start address. * 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 * 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. * @returns 0 on success or negative value on failure.
@ -98,10 +99,10 @@ int _storage_config_TDB_EXTERNAL_NO_RBP();
* in the internal memory and an external FileSysteStore. If blockdevice and filesystem not set, * 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 system will use the default block device and default filesystem
* The following is a list of configuration parameter: * The following is a list of configuration parameter:
* MBED_CONF_STORAGE_FILESYSTEM_RBP_INTERNAL_SIZE - Size of the internal FlashIAPBlockDevice and by default is * MBED_CONF_STORAGE_FILESYSTEM_RBP_INTERNAL_SIZE - Size of the internal FlashIAPBlockDevice and by
* set to 4K*#enteries/32. The start address will be set to * default is set to from start address to the end of the flash.
* end of flash - rbp_internal_size. * If start address is 0 the start address will be set to end of
* MBED_CONF_STORAGE_FILESYSTEM_RBP_NUMBER_OF_ENTRIES - If not defined default is 64 * flash - rbp_internal_size.
* MBED_CONF_STORAGE_FILESYSTEM_INTERNAL_BASE_ADDRESS - The satrt address of the internal FlashIAPBlockDevice. * 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_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_BLOCKDEVICE - Allowed values are: default, SPIF, DATAFASH, QSPIF or SD
@ -160,6 +161,7 @@ static inline uint32_t align_down(uint64_t val, uint64_t size)
{ {
return (((val) / size)) * size; return (((val) / size)) * size;
} }
int _calculate_blocksize_match_tdbstore(BlockDevice *bd) int _calculate_blocksize_match_tdbstore(BlockDevice *bd)
{ {
bd_size_t size = bd->size(); bd_size_t size = bd->size();
@ -167,13 +169,13 @@ int _calculate_blocksize_match_tdbstore(BlockDevice *bd)
bd_size_t number_of_sector = size / erase_size; bd_size_t number_of_sector = size / erase_size;
if (number_of_sector < 2) { if (number_of_sector < 2) {
tr_warning("KV Config: there is less then 2 sector TDBStore will not work."); tr_warning("KV Config: There are less than two sectors - TDBStore will not work.");
return -1; return -1;
} }
if (number_of_sector % 2 != 0) { if (number_of_sector % 2 != 0) {
tr_warning("KV Config: Number of sector is not even number. Consider changing the BlockDevice size"); tr_warning("KV Config: Number of sectors is not an even number. Consider changing the BlockDevice size");
} }
return MBED_SUCCESS; return MBED_SUCCESS;
@ -245,11 +247,102 @@ FileSystem *_get_filesystem_default(BlockDevice *bd, const char *mount)
#endif #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) BlockDevice *_get_blockdevice_FLASHIAP(bd_addr_t start_address, bd_size_t size)
{ {
#if COMPONENT_FLASHIAP #if COMPONENT_FLASHIAP
bd_size_t bd_final_size;
bd_addr_t flash_end_address; bd_addr_t flash_end_address;
bd_addr_t flash_start_address; bd_addr_t flash_start_address;
bd_addr_t flash_first_writable_sector_address; bd_addr_t flash_first_writable_sector_address;
@ -268,13 +361,9 @@ BlockDevice *_get_blockdevice_FLASHIAP(bd_addr_t start_address, bd_size_t size)
flash_start_address = flash.get_flash_start(); flash_start_address = flash.get_flash_start();
flash_end_address = flash_start_address + flash.get_flash_size();; flash_end_address = flash_start_address + flash.get_flash_size();;
//Non default configuration
if (start_address != 0) { if (start_address != 0) {
if (start_address < flash_first_writable_sector_address) {
tr_error("KV Config: Internal block device start address overlapped ROM address ");
flash.deinit();
return NULL;
}
aligned_start_address = align_down(start_address, flash.get_sector_size(start_address)); aligned_start_address = align_down(start_address, flash.get_sector_size(start_address));
if (start_address != aligned_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); tr_error("KV Config: Internal block device start address is not aligned. Better use %02llx", aligned_start_address);
@ -283,16 +372,15 @@ BlockDevice *_get_blockdevice_FLASHIAP(bd_addr_t start_address, bd_size_t size)
} }
if (size == 0) { if (size == 0) {
//will use 2 sector only. //The block device will have all space form start address to the end of the flash
bd_final_size = (flash_end_address - start_address); size = (flash_end_address - start_address);
static FlashIAPBlockDevice bd(start_address, bd_final_size); static FlashIAPBlockDevice bd(start_address, size);
flash.deinit(); flash.deinit();
return &bd; return &bd;
} }
if (size != 0) { if (size != 0) {
end_address = start_address + size; end_address = start_address + size;
if (end_address > flash_end_address) { if (end_address > flash_end_address) {
tr_error("KV Config: Internal block device end address is out of boundaries"); tr_error("KV Config: Internal block device end address is out of boundaries");
@ -313,38 +401,22 @@ BlockDevice *_get_blockdevice_FLASHIAP(bd_addr_t start_address, bd_size_t size)
} }
} }
bool request_default = false; //Non default configuration start_address = 0
if (start_address == 0 && size == 0) {
request_default = true;
size = 1;
}
start_address = flash_end_address - size; start_address = flash_end_address - size;
aligned_start_address = align_down(start_address, flash.get_sector_size(start_address)); aligned_start_address = align_down(start_address, flash.get_sector_size(start_address));
//Skip this check if default parameters are set (0 for base address and 0 size). if (start_address != aligned_start_address) {
//We will calculate the address and size by ourselves
if (start_address != aligned_start_address && !request_default) {
tr_error("KV Config: Internal block device start address is not aligned. Consider changing the size parameter"); tr_error("KV Config: Internal block device start address is not aligned. Consider changing the size parameter");
flash.deinit(); flash.deinit();
return NULL; return NULL;
} }
if (request_default) {
//update start_address to double the size for TDBStore needs
bd_final_size = (flash_end_address - aligned_start_address) * 2;
start_address = (flash_end_address - bd_final_size);
aligned_start_address = align_down(start_address, flash.get_sector_size(start_address));
} else {
bd_final_size = (flash_end_address - aligned_start_address);
}
flash.deinit(); flash.deinit();
if (aligned_start_address < flash_first_writable_sector_address) { if (aligned_start_address < flash_first_writable_sector_address) {
tr_error("KV Config: Internal block device start address overlapped ROM address "); tr_error("KV Config: Internal block device start address overlapped ROM address ");
return NULL; return NULL;
} }
static FlashIAPBlockDevice bd(aligned_start_address, bd_final_size); static FlashIAPBlockDevice bd(aligned_start_address, size);
return &bd; return &bd;
#else #else
@ -376,6 +448,7 @@ BlockDevice *_get_blockdevice_SPIF(bd_addr_t start_address, bd_size_t size)
return &bd; 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) { if (_get_addresses(&bd, start_address, size, &aligned_start_address, &aligned_end_address) != 0) {
tr_error("KV Config: Fail to get addresses for SlicingBlockDevice."); tr_error("KV Config: Fail to get addresses for SlicingBlockDevice.");
return NULL; return NULL;
@ -416,6 +489,7 @@ BlockDevice *_get_blockdevice_QSPIF(bd_addr_t start_address, bd_size_t size)
return &bd; 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) { if (_get_addresses(&bd, start_address, size, &aligned_start_address, &aligned_end_address) != 0) {
tr_error("KV Config: Fail to get addresses for SlicingBlockDevice."); tr_error("KV Config: Fail to get addresses for SlicingBlockDevice.");
return NULL; return NULL;
@ -452,6 +526,7 @@ BlockDevice *_get_blockdevice_DATAFLASH(bd_addr_t start_address, bd_size_t size)
return &bd; 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) { if (_get_addresses(&bd, start_address, size, &aligned_start_address, &aligned_end_address) != 0) {
tr_error("KV Config: Fail to get addresses for SlicingBlockDevice."); tr_error("KV Config: Fail to get addresses for SlicingBlockDevice.");
return NULL; return NULL;
@ -485,35 +560,36 @@ BlockDevice *_get_blockdevice_SD(bd_addr_t start_address, bd_size_t size)
return NULL; return NULL;
} }
#if MBED_CONF_STORAGE_STORAGE_TYPE == TDB_EXTERNAL_NO_RBP || MBED_CONF_STORAGE_STORAGE_TYPE == TDB_EXTERNAL if (strcmp(STR(MBED_CONF_STORAGE_STORAGE_TYPE), "TDB_EXTERNAL_NO_RBP") == 0 ||
//In TDBStore we have a constraint of 4GByte strcmp(STR(MBED_CONF_STORAGE_STORAGE_TYPE), "TDB_EXTERNAL") == 0) {
if (start_address == 0 && size == 0 && bd.size() < (uint32_t)(-1)) { //In TDBStore profile, we have a constraint of 4GByte
return &bd; 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;
}
} }
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
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;
}
#endif
aligned_end_address = align_down(aligned_end_address, bd.get_erase_size(aligned_end_address)); 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); static SlicingBlockDevice sbd(&bd, aligned_start_address, aligned_end_address);
return &sbd; return &sbd;
@ -545,39 +621,41 @@ int _storage_config_TDB_INTERNAL()
bd_size_t internal_size = MBED_CONF_STORAGE_TDB_INTERNAL_INTERNAL_SIZE; 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; bd_addr_t internal_start_address = MBED_CONF_STORAGE_TDB_INTERNAL_INTERNAL_BASE_ADDRESS;
//If default values are set, we should get maximum available size of internal bd.
if (internal_size == 0 && internal_start_address == 0) { if (internal_size == 0 && internal_start_address == 0) {
FlashIAP flash; //Calculate the block device size and start address in case default values are used.
if (flash.init() != 0) { if (_get_flashiap_bd_default_addresses_tdb_internal(&internal_start_address, &internal_size) != MBED_SUCCESS) {
return MBED_ERROR_FAILED_OPERATION; return MBED_ERROR_FAILED_OPERATION;
} }
internal_start_address = align_up(FLASHIAP_APP_ROM_END_ADDR, flash.get_sector_size(FLASHIAP_APP_ROM_END_ADDR));
flash.deinit();
} }
//Get internal memory FLASHIAP block device.
kvstore_config.internal_bd = GET_BLOCKDEVICE(INTERNAL_BLOCKDEVICE_NAME, internal_start_address, internal_size); kvstore_config.internal_bd = GET_BLOCKDEVICE(INTERNAL_BLOCKDEVICE_NAME, internal_start_address, internal_size);
if (kvstore_config.internal_bd == NULL) { if (kvstore_config.internal_bd == NULL) {
tr_error("KV Config: Fail to get internal BlockDevice."); tr_error("KV Config: Fail to get internal BlockDevice.");
return MBED_ERROR_FAILED_OPERATION; return MBED_ERROR_FAILED_OPERATION;
} }
int ret = kvstore_config.internal_bd->init(); int ret = kvstore_config.internal_bd->init();
if (ret != MBED_SUCCESS) { if (ret != MBED_SUCCESS) {
tr_error("KV Config: Fail to init internal BlockDevice."); tr_error("KV Config: Fail to init internal BlockDevice.");
return MBED_ERROR_FAILED_OPERATION; 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) { if (_calculate_blocksize_match_tdbstore(kvstore_config.internal_bd) != MBED_SUCCESS) {
tr_error("KV Config: Can not create TDBStore with less then 2 sector."); tr_error("KV Config: Can not create TDBStore with less then 2 sector.");
return MBED_ERROR_INVALID_ARGUMENT; return MBED_ERROR_INVALID_ARGUMENT;
} }
//Deinitialize internal block device and TDB will reinitialize and take control on it.
ret = kvstore_config.internal_bd->deinit(); ret = kvstore_config.internal_bd->deinit();
if (ret != MBED_SUCCESS) { if (ret != MBED_SUCCESS) {
tr_error("KV Config: Fail to deinit internal BlockDevice."); tr_error("KV Config: Fail to deinit internal BlockDevice.");
return MBED_ERROR_FAILED_OPERATION; return MBED_ERROR_FAILED_OPERATION;
} }
//Create a TDBStore in the internal FLASHIAP block device.
static TDBStore tdb_internal(kvstore_config.internal_bd); static TDBStore tdb_internal(kvstore_config.internal_bd);
kvstore_config.internal_store = &tdb_internal; kvstore_config.internal_store = &tdb_internal;
@ -589,9 +667,12 @@ int _storage_config_TDB_INTERNAL()
kvstore_config.kvstore_main_instance = kvstore_config.kvstore_main_instance =
kvstore_config.internal_store; 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_config.flags_mask = ~(KVStore::REQUIRE_CONFIDENTIALITY_FLAG |
KVStore::REQUIRE_REPLAY_PROTECTION_FLAG); KVStore::REQUIRE_REPLAY_PROTECTION_FLAG);
//Initialize kv_map and add the configuration struct to KVStore map.
KVMap &kv_map = KVMap::get_instance(); KVMap &kv_map = KVMap::get_instance();
ret = kv_map.init(); ret = kv_map.init();
if (MBED_SUCCESS != ret) { if (MBED_SUCCESS != ret) {
@ -609,7 +690,6 @@ int _storage_config_TDB_INTERNAL()
return MBED_ERROR_UNSUPPORTED; return MBED_ERROR_UNSUPPORTED;
#endif #endif
} }
int _storage_config_TDB_EXTERNAL() int _storage_config_TDB_EXTERNAL()
@ -619,13 +699,17 @@ int _storage_config_TDB_EXTERNAL()
#endif #endif
bd_size_t internal_rbp_size = MBED_CONF_STORAGE_TDB_EXTERNAL_RBP_INTERNAL_SIZE; bd_size_t internal_rbp_size = MBED_CONF_STORAGE_TDB_EXTERNAL_RBP_INTERNAL_SIZE;
size_t rbp_num_of_enteries = MBED_CONF_STORAGE_TDB_EXTERNAL_RBP_NUMBER_OF_ENTRIES;
bd_addr_t internal_start_address = MBED_CONF_STORAGE_TDB_EXTERNAL_INTERNAL_BASE_ADDRESS; bd_addr_t internal_start_address = MBED_CONF_STORAGE_TDB_EXTERNAL_INTERNAL_BASE_ADDRESS;
if (internal_rbp_size == 0) { //Get the default address and size for internal rbp TDBStore
internal_rbp_size = 4 * 1024 * rbp_num_of_enteries / 32; 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); kvstore_config.internal_bd = GET_BLOCKDEVICE(INTERNAL_BLOCKDEVICE_NAME, internal_start_address, internal_rbp_size);
if (kvstore_config.internal_bd == NULL) { if (kvstore_config.internal_bd == NULL) {
tr_error("KV Config: Fail to get internal BlockDevice."); tr_error("KV Config: Fail to get internal BlockDevice.");
@ -638,11 +722,13 @@ int _storage_config_TDB_EXTERNAL()
return MBED_ERROR_FAILED_OPERATION ; return MBED_ERROR_FAILED_OPERATION ;
} }
//Check if TDBStore has at least 2 sector.
if (_calculate_blocksize_match_tdbstore(kvstore_config.internal_bd) != MBED_SUCCESS) { if (_calculate_blocksize_match_tdbstore(kvstore_config.internal_bd) != MBED_SUCCESS) {
tr_error("KV Config: Can not create TDBStore with less then 2 sector."); tr_error("KV Config: Can not create TDBStore with less then 2 sector.");
return MBED_ERROR_INVALID_ARGUMENT; return MBED_ERROR_INVALID_ARGUMENT;
} }
//Create internal TDBStore
static TDBStore tdb_internal(kvstore_config.internal_bd); static TDBStore tdb_internal(kvstore_config.internal_bd);
kvstore_config.internal_store = &tdb_internal; kvstore_config.internal_store = &tdb_internal;
@ -655,12 +741,15 @@ int _storage_config_TDB_EXTERNAL()
bd_size_t size = MBED_CONF_STORAGE_TDB_EXTERNAL_EXTERNAL_SIZE; bd_size_t size = MBED_CONF_STORAGE_TDB_EXTERNAL_EXTERNAL_SIZE;
bd_addr_t address = MBED_CONF_STORAGE_TDB_EXTERNAL_EXTERNAL_BASE_ADDRESS; 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); BlockDevice *bd = GET_BLOCKDEVICE(MBED_CONF_STORAGE_TDB_EXTERNAL_BLOCKDEVICE, address, size);
if (bd == NULL) { if (bd == NULL) {
tr_error("KV Config: Fail to get external BlockDevice."); tr_error("KV Config: Fail to get external BlockDevice.");
return MBED_ERROR_FAILED_OPERATION ; 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) #if defined(COMPONENT_SD)
if (strcmp(STR(MBED_CONF_STORAGE_TDB_EXTERNAL_BLOCKDEVICE), "SD") == 0 if (strcmp(STR(MBED_CONF_STORAGE_TDB_EXTERNAL_BLOCKDEVICE), "SD") == 0
#if defined(COMPONENT_SD) && !defined(COMPONENT_SPIF) && !defined(COMPONENT_QSPIF) && !defined(COMPONENT_DATAFLASH) #if defined(COMPONENT_SD) && !defined(COMPONENT_SPIF) && !defined(COMPONENT_QSPIF) && !defined(COMPONENT_DATAFLASH)
@ -697,12 +786,15 @@ int _storage_config_TDB_EXTERNAL_NO_RBP()
bd_size_t size = MBED_CONF_STORAGE_TDB_EXTERNAL_NO_RBP_EXTERNAL_SIZE; 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; 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); BlockDevice *bd = GET_BLOCKDEVICE(MBED_CONF_STORAGE_TDB_EXTERNAL_NO_RBP_BLOCKDEVICE, address, size);
if (bd == NULL) { if (bd == NULL) {
tr_error("KV Config: Fail to get external BlockDevice."); tr_error("KV Config: Fail to get external BlockDevice.");
return MBED_ERROR_FAILED_OPERATION ; 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) #if defined(COMPONENT_SD)
if (strcmp(STR(MBED_CONF_STORAGE_TDB_EXTERNAL_NO_RBP_BLOCKDEVICE), "SD") == 0 if (strcmp(STR(MBED_CONF_STORAGE_TDB_EXTERNAL_NO_RBP_BLOCKDEVICE), "SD") == 0
#if defined(COMPONENT_SD) && !defined(COMPONENT_SPIF) && !defined(COMPONENT_QSPIF) && !defined(COMPONENT_DATAFLASH) #if defined(COMPONENT_SD) && !defined(COMPONENT_SPIF) && !defined(COMPONENT_QSPIF) && !defined(COMPONENT_DATAFLASH)
@ -726,26 +818,30 @@ int _storage_config_TDB_EXTERNAL_NO_RBP()
kvstore_config.external_bd = bd; kvstore_config.external_bd = bd;
#endif #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); kvstore_config.flags_mask = ~(KVStore::REQUIRE_REPLAY_PROTECTION_FLAG);
return _storage_config_tdb_external_common(); return _storage_config_tdb_external_common();
} }
int _storage_config_tdb_external_common() int _storage_config_tdb_external_common()
{ {
#if SECURESTORE_ENABLED #if SECURESTORE_ENABLED
//Initialize external block device
int ret = kvstore_config.external_bd->init(); int ret = kvstore_config.external_bd->init();
if (ret != MBED_SUCCESS) { if (ret != MBED_SUCCESS) {
tr_error("KV Config: Fail to init external BlockDevice."); tr_error("KV Config: Fail to init external BlockDevice.");
return MBED_ERROR_FAILED_OPERATION ; 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) { if (_calculate_blocksize_match_tdbstore(kvstore_config.external_bd) != MBED_SUCCESS) {
tr_error("KV Config: Can not create TDBStore with less then 2 sector."); tr_error("KV Config: Can not create TDBStore with less then 2 sector.");
return MBED_ERROR_INVALID_SIZE; return MBED_ERROR_INVALID_SIZE;
} }
//Create external TDBStore
static TDBStore tdb_external(kvstore_config.external_bd); static TDBStore tdb_external(kvstore_config.external_bd);
kvstore_config.external_store = &tdb_external; kvstore_config.external_store = &tdb_external;
@ -755,6 +851,7 @@ int _storage_config_tdb_external_common()
return ret; return ret;
} }
//Create SecureStore and initialize it
static SecureStore secst(kvstore_config.external_store, kvstore_config.internal_store); static SecureStore secst(kvstore_config.external_store, kvstore_config.internal_store);
ret = secst.init(); ret = secst.init();
@ -765,6 +862,7 @@ int _storage_config_tdb_external_common()
kvstore_config.kvstore_main_instance = &secst; kvstore_config.kvstore_main_instance = &secst;
//Init kv_map and add the configuration struct to KVStore map.
KVMap &kv_map = KVMap::get_instance(); KVMap &kv_map = KVMap::get_instance();
ret = kv_map.init(); ret = kv_map.init();
if (MBED_SUCCESS != ret) { if (MBED_SUCCESS != ret) {
@ -790,13 +888,17 @@ int _storage_config_FILESYSTEM()
return MBED_ERROR_UNSUPPORTED; return MBED_ERROR_UNSUPPORTED;
#endif #endif
bd_size_t internal_rbp_size = MBED_CONF_STORAGE_FILESYSTEM_RBP_INTERNAL_SIZE; bd_size_t internal_rbp_size = MBED_CONF_STORAGE_FILESYSTEM_RBP_INTERNAL_SIZE;
size_t rbp_num_of_enteries = MBED_CONF_STORAGE_FILESYSTEM_RBP_NUMBER_OF_ENTRIES;
bd_addr_t internal_start_address = MBED_CONF_STORAGE_FILESYSTEM_INTERNAL_BASE_ADDRESS; bd_addr_t internal_start_address = MBED_CONF_STORAGE_FILESYSTEM_INTERNAL_BASE_ADDRESS;
if (internal_rbp_size == 0) { //Get the default address and size for internal rbp TDBStore
internal_rbp_size = 4 * 1024 * rbp_num_of_enteries / 32; 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); kvstore_config.internal_bd = GET_BLOCKDEVICE(INTERNAL_BLOCKDEVICE_NAME, internal_start_address, internal_rbp_size);
if (kvstore_config.internal_bd == NULL) { if (kvstore_config.internal_bd == NULL) {
tr_error("KV Config: Fail to get internal BlockDevice "); tr_error("KV Config: Fail to get internal BlockDevice ");
@ -809,6 +911,20 @@ int _storage_config_FILESYSTEM()
return MBED_ERROR_FAILED_OPERATION ; 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); static TDBStore tdb_internal(kvstore_config.internal_bd);
kvstore_config.internal_store = &tdb_internal; kvstore_config.internal_store = &tdb_internal;
@ -822,6 +938,7 @@ int _storage_config_FILESYSTEM()
bd_addr_t address = MBED_CONF_STORAGE_FILESYSTEM_EXTERNAL_BASE_ADDRESS; bd_addr_t address = MBED_CONF_STORAGE_FILESYSTEM_EXTERNAL_BASE_ADDRESS;
const char *mount_point = STR(MBED_CONF_STORAGE_FILESYSTEM_MOUNT_POINT); 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); kvstore_config.external_bd = GET_BLOCKDEVICE(MBED_CONF_STORAGE_FILESYSTEM_BLOCKDEVICE, address, size);
if (kvstore_config.external_bd == NULL) { if (kvstore_config.external_bd == NULL) {
tr_error("KV Config: Fail to get external BlockDevice "); tr_error("KV Config: Fail to get external BlockDevice ");
@ -834,6 +951,10 @@ int _storage_config_FILESYSTEM()
return MBED_ERROR_FAILED_OPERATION ; 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, kvstore_config.external_bd, kvstore_config.external_fs = GET_FILESYSTEM(MBED_CONF_STORAGE_FILESYSTEM_FILESYSTEM, kvstore_config.external_bd,
mount_point); mount_point);
if (kvstore_config.external_fs == NULL) { if (kvstore_config.external_fs == NULL) {
@ -852,6 +973,7 @@ int _storage_config_FILESYSTEM_NO_RBP()
bd_addr_t address = MBED_CONF_STORAGE_FILESYSTEM_NO_RBP_EXTERNAL_BASE_ADDRESS; 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); 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); kvstore_config.external_bd = GET_BLOCKDEVICE(MBED_CONF_STORAGE_FILESYSTEM_NO_RBP_BLOCKDEVICE, address, size);
if (kvstore_config.external_bd == NULL) { if (kvstore_config.external_bd == NULL) {
tr_error("KV Config: Fail to get external BlockDevice "); tr_error("KV Config: Fail to get external BlockDevice ");
@ -864,6 +986,10 @@ int _storage_config_FILESYSTEM_NO_RBP()
return MBED_ERROR_FAILED_OPERATION ; 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, kvstore_config.external_bd, kvstore_config.external_fs = GET_FILESYSTEM(MBED_CONF_STORAGE_FILESYSTEM_NO_RBP_FILESYSTEM, kvstore_config.external_bd,
mount_point); mount_point);
if (kvstore_config.external_fs == NULL) { if (kvstore_config.external_fs == NULL) {
@ -871,6 +997,8 @@ int _storage_config_FILESYSTEM_NO_RBP()
return MBED_ERROR_FAILED_OPERATION ; 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); kvstore_config.flags_mask = ~(KVStore::REQUIRE_REPLAY_PROTECTION_FLAG);
return _storage_config_filesystem_common(); return _storage_config_filesystem_common();
@ -879,6 +1007,8 @@ int _storage_config_FILESYSTEM_NO_RBP()
int _storage_config_filesystem_common() int _storage_config_filesystem_common()
{ {
#if SECURESTORE_ENABLED #if SECURESTORE_ENABLED
//Mount file system. if it fails, try to reformat
int ret = kvstore_config.external_fs->mount(kvstore_config.external_bd); int ret = kvstore_config.external_fs->mount(kvstore_config.external_bd);
if (ret != MBED_SUCCESS) { if (ret != MBED_SUCCESS) {
ret = kvstore_config.external_fs->reformat(kvstore_config.external_bd); ret = kvstore_config.external_fs->reformat(kvstore_config.external_bd);
@ -889,6 +1019,7 @@ int _storage_config_filesystem_common()
} }
} }
//Create FileSystemStore
kvstore_config.external_store = _get_file_system_store(kvstore_config.external_fs); kvstore_config.external_store = _get_file_system_store(kvstore_config.external_fs);
if (kvstore_config.external_store == NULL) { if (kvstore_config.external_store == NULL) {
tr_error("KV Config: Fail to get FileSystemStore"); tr_error("KV Config: Fail to get FileSystemStore");
@ -901,6 +1032,7 @@ int _storage_config_filesystem_common()
return ret; return ret;
} }
//Create SecureStore and set it as main KVStore
static SecureStore secst(kvstore_config.external_store, kvstore_config.internal_store); static SecureStore secst(kvstore_config.external_store, kvstore_config.internal_store);
ret = secst.init(); ret = secst.init();
@ -911,6 +1043,7 @@ int _storage_config_filesystem_common()
kvstore_config.kvstore_main_instance = &secst; kvstore_config.kvstore_main_instance = &secst;
//Init kv_map and add the configuration struct to KVStore map.
KVMap &kv_map = KVMap::get_instance(); KVMap &kv_map = KVMap::get_instance();
ret = kv_map.init(); ret = kv_map.init();
if (MBED_SUCCESS != ret) { if (MBED_SUCCESS != ret) {
@ -930,6 +1063,17 @@ int _storage_config_filesystem_common()
#endif #endif
} }
int _storage_config_default()
{
#if COMPONENT_QSPIF || COMPONENT_SPIF || COMPONENT_DATAFLASH
return _storage_config_TDB_EXTERNAL();
#elif COMPONENT_SD
return _storage_config_FILESYSTEM();
#elif COMPONENT_FLASHIAP
return _storage_config_TDB_INTERNAL();
#endif
}
MBED_WEAK int kv_init_storage_config() MBED_WEAK int kv_init_storage_config()
{ {

View File

@ -2,8 +2,8 @@
"name": "storage", "name": "storage",
"config": { "config": {
"storage_type": { "storage_type": {
"help": "Options are TDB_INTERNAL, TDB_EXTERNAL, TDB_EXTERNAL_NO_RBP, FILESYSTEM or FILESYSTEM_NO_RBP.", "help": "Options are TDB_INTERNAL, TDB_EXTERNAL, TDB_EXTERNAL_NO_RBP, FILESYSTEM, FILESYSTEM_NO_RBP or default. If default, the storage type will be chosen according to the component defined in targets.json",
"value": "TDB_EXTERNAL" "value": "default"
}, },
"default_kv": { "default_kv": {
"help": "A string name for the default kvstore configuration", "help": "A string name for the default kvstore configuration",

View File

@ -3,13 +3,9 @@
"name": "storage_tdb_external", "name": "storage_tdb_external",
"config": { "config": {
"rbp_internal_size": { "rbp_internal_size": {
"help": "If default the size will be 4K*#entries/32", "help": "Default is the size of the 2 last sectors of internal flash",
"value": "0" "value": "0"
}, },
"rbp_number_of_entries": {
"help": "If not defined default is 64",
"value": "64"
},
"internal_base_address": { "internal_base_address": {
"help": "If default, the base address is set to the first sector after the application code ends.", "help": "If default, the base address is set to the first sector after the application code ends.",
"value": "0" "value": "0"