Move TDB bounds computation for better reuse

Migrate into TDBStore so that DirectAccessDeviceKey can use it as well.
pull/11629/head
Kyle Kearney 2019-10-03 17:05:58 -07:00
parent afa88b76d4
commit cda0af66eb
4 changed files with 185 additions and 178 deletions

View File

@ -270,140 +270,10 @@ FileSystem *_get_filesystem_default(const char *mount)
#endif
}
int get_default_flash_addresses(bd_addr_t *start_address, bd_size_t *size)
{
int ret = MBED_SUCCESS;
#if COMPONENT_FLASHIAP
FlashIAP flash;
if (flash.init() != 0) {
return MBED_ERROR_INITIALIZATION_FAILED;
}
// Use the last 2 sectors or 10 pages of flash for the TDBStore by default (whichever is larger)
// For each area: must be a minimum of 1 page of reserved and 2 pages for master record
static const int STORE_SECTORS = 2;
static const int STORE_PAGES = 10;
// Let's work from end of the flash backwards
bd_addr_t curr_addr = flash.get_flash_start() + flash.get_flash_size();
bd_size_t sector_space = 0;
for (int i = STORE_SECTORS; i; i--) {
bd_size_t sector_size = flash.get_sector_size(curr_addr - 1);
sector_space += sector_size;
}
bd_size_t page_space = flash.get_page_size() * STORE_PAGES;
if (sector_space > page_space) {
curr_addr -= sector_space;
*size = sector_space;
} else {
curr_addr -= page_space;
*size = page_space;
}
// Store- and application-sectors mustn't overlap
uint32_t first_wrtbl_sector_addr =
(uint32_t)(align_up(FLASHIAP_APP_ROM_END_ADDR, flash.get_sector_size(FLASHIAP_APP_ROM_END_ADDR)));
MBED_ASSERT(curr_addr >= first_wrtbl_sector_addr);
if (curr_addr < first_wrtbl_sector_addr) {
ret = MBED_ERROR_MEDIA_FULL;
} else {
*start_address = curr_addr;
}
flash.deinit();
#endif
return ret;
}
int get_flash_bounds_from_config(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;
if (!start_address || !size) {
return MBED_ERROR_INVALID_ARGUMENT;
}
int ret = flash.init();
if (ret != 0) {
return MBED_ERROR_INITIALIZATION_FAILED;
}
// Get flash parameters
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();
if (*start_address == 0) {
if (*size == 0) {
flash.deinit();
return MBED_ERROR_INVALID_ARGUMENT;
}
*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) {
// Start address not aligned - size should likely be changed so that it is
flash.deinit();
return MBED_ERROR_INVALID_SIZE;
}
} else {
aligned_start_address = align_down(*start_address, flash.get_sector_size(*start_address));
if (*start_address != aligned_start_address) {
// Start address not aligned - size should likely be changed so that it is
flash.deinit();
return MBED_ERROR_INVALID_SIZE;
}
if (*size == 0) {
//The block device will have all space from start address to the end of the flash
*size = (flash_end_address - *start_address);
} else {
// Do checks on end address to make sure configured start address/size are good
end_address = *start_address + *size;
if (end_address > flash_end_address) {
// End address is out of flash bounds
flash.deinit();
return MBED_ERROR_INVALID_SIZE;
}
aligned_end_address = align_up(end_address, flash.get_sector_size(end_address - 1));
if (end_address != aligned_end_address) {
// End address not aligned - size should likely be changed so that it is
flash.deinit();
return MBED_ERROR_INVALID_SIZE;
}
}
}
flash.deinit();
if (*start_address < flash_first_writable_sector_address) {
// Calculated start address overlaps with ROM
return MBED_ERROR_MEDIA_FULL;
}
#endif
return MBED_SUCCESS;
}
BlockDevice *_get_blockdevice_FLASHIAP(bd_addr_t &start_address, bd_size_t &size)
{
#if COMPONENT_FLASHIAP
int ret = get_flash_bounds_from_config(&start_address, &size);
int ret = TDBStore::get_flash_bounds_from_config(&start_address, &size);
if (ret != 0) {
tr_error("KV Config: Determination of internal block device bounds failed. The configured start address/size is likely invalid.");
return NULL;
@ -689,13 +559,14 @@ MBED_WEAK BlockDevice *get_other_blockdevice()
return NULL;
}
int _create_internal_tdb(BlockDevice **internal_bd, KVStore **internal_tdb, bd_size_t *size, bd_addr_t *start_address) {
int _create_internal_tdb(BlockDevice **internal_bd, KVStore **internal_tdb, bd_size_t *size, bd_addr_t *start_address)
{
int ret;
//Get the default address and size for the TDBStore
if (*size == 0 && *start_address == 0) {
//Calculate the block device size and start address in case default values are used.
ret = get_default_flash_addresses(start_address, size);
ret = TDBStore::get_default_flash_addresses(start_address, size);
if (ret != MBED_SUCCESS) {
return MBED_ERROR_FAILED_OPERATION;
}

View File

@ -23,6 +23,7 @@
#include "mbed_error.h"
#include "MbedCRC.h"
#include "mbed_trace.h"
#include "TDBStore.h"
#define TRACE_GROUP "DADK"
using namespace mbed;
@ -82,7 +83,7 @@ int direct_access_to_devicekey(uint32_t tdb_start_offset, uint32_t tdb_end_offse
status = calc_area_params(&flash, tdb_start_offset, tdb_end_offset, area_params);
if (status != MBED_SUCCESS) {
tr_error("Couldn't calulate Area Params - err: %d", status);
tr_error("Couldn't calculate Area Params - err: %d", status);
goto exit_point;
}
@ -108,21 +109,17 @@ exit_point:
return status;
}
int get_expected_internal_TDBStore_position(uint32_t *out_tdb_start_offset, uint32_t *out_tdb_end_offset)
int get_expected_internal_TDBStore_position(uint32_t *out_tdb_start_offset, uint32_t *out_tdb_end_offset)
{
uint32_t flash_end_address;
uint32_t flash_start_address;
uint32_t aligned_start_address;
uint32_t aligned_end_address;
bd_addr_t tdb_start_address;
bd_size_t tdb_size;
FlashIAP flash;
bool is_default_configuration = false;
uint32_t tdb_size;
if (strcmp(STR(MBED_CONF_STORAGE_STORAGE_TYPE), "FILESYSTEM") == 0) {
#ifndef MBED_CONF_STORAGE_FILESYSTEM_INTERNAL_BASE_ADDRESS
return MBED_ERROR_ITEM_NOT_FOUND;
#else
*out_tdb_start_offset = MBED_CONF_STORAGE_FILESYSTEM_INTERNAL_BASE_ADDRESS;
tdb_start_address = MBED_CONF_STORAGE_FILESYSTEM_INTERNAL_BASE_ADDRESS;
tdb_size = MBED_CONF_STORAGE_FILESYSTEM_RBP_INTERNAL_SIZE;
#endif
@ -130,7 +127,7 @@ int get_expected_internal_TDBStore_position(uint32_t *out_tdb_start_offset, uin
#ifndef MBED_CONF_STORAGE_TDB_EXTERNAL_INTERNAL_BASE_ADDRESS
return MBED_ERROR_ITEM_NOT_FOUND;
#else
*out_tdb_start_offset = MBED_CONF_STORAGE_TDB_EXTERNAL_INTERNAL_BASE_ADDRESS;
tdb_start_address = MBED_CONF_STORAGE_TDB_EXTERNAL_INTERNAL_BASE_ADDRESS;
tdb_size = MBED_CONF_STORAGE_TDB_EXTERNAL_RBP_INTERNAL_SIZE;
#endif
@ -139,52 +136,28 @@ int get_expected_internal_TDBStore_position(uint32_t *out_tdb_start_offset, uin
#ifndef MBED_CONF_STORAGE_TDB_INTERNAL_INTERNAL_BASE_ADDRESS
return MBED_ERROR_ITEM_NOT_FOUND;
#else
*out_tdb_start_offset = MBED_CONF_STORAGE_TDB_INTERNAL_INTERNAL_BASE_ADDRESS;
tdb_start_address = MBED_CONF_STORAGE_TDB_INTERNAL_INTERNAL_BASE_ADDRESS;
tdb_size = MBED_CONF_STORAGE_TDB_INTERNAL_INTERNAL_SIZE;
#endif
} else {
return MBED_ERROR_UNSUPPORTED;
}
*out_tdb_end_offset = (*out_tdb_start_offset) + tdb_size;
if ((*out_tdb_start_offset == 0) && (tdb_size == 0)) {
is_default_configuration = true;
} else if ((*out_tdb_start_offset == 0) || (tdb_size == 0)) {
return MBED_ERROR_UNSUPPORTED;
int ret;
if ((tdb_start_address == 0) && (tdb_size == 0)) {
ret = TDBStore::get_default_flash_addresses(&tdb_start_address, &tdb_size);
if (ret != MBED_SUCCESS) {
return MBED_ERROR_FAILED_OPERATION;
}
}
int ret = flash.init();
if (ret != 0) {
ret = TDBStore::get_flash_bounds_from_config(&tdb_start_address, &tdb_size);
if (ret != MBED_SUCCESS) {
return MBED_ERROR_FAILED_OPERATION;
}
uint32_t flash_first_writable_sector_address = (uint32_t)(align_up(FLASHIAP_APP_ROM_END_ADDR,
flash.get_sector_size(FLASHIAP_APP_ROM_END_ADDR)));
//Get flash parameters before starting
flash_start_address = flash.get_flash_start();
flash_end_address = flash_start_address + flash.get_flash_size();
if (!is_default_configuration) {
aligned_start_address = align_down(*out_tdb_start_offset, flash.get_sector_size(*out_tdb_start_offset));
aligned_end_address = align_up(*out_tdb_end_offset, flash.get_sector_size(*out_tdb_end_offset - 1));
if ((*out_tdb_start_offset != aligned_start_address) || (*out_tdb_end_offset != aligned_end_address)
|| (*out_tdb_end_offset > flash_end_address)) {
flash.deinit();
return MBED_ERROR_INVALID_OPERATION;
}
} else {
aligned_start_address = flash_end_address - (flash.get_sector_size(flash_end_address - 1) * 2);
if (aligned_start_address < flash_first_writable_sector_address) {
flash.deinit();
return MBED_ERROR_INVALID_OPERATION;
}
*out_tdb_start_offset = aligned_start_address;
*out_tdb_end_offset = flash_end_address;
}
flash.deinit();
*out_tdb_start_offset = tdb_start_address;
*out_tdb_end_offset = tdb_start_address + tdb_size;
return MBED_SUCCESS;
}

View File

@ -25,6 +25,7 @@
#include "mbed_assert.h"
#include "mbed_wait_api.h"
#include "MbedCRC.h"
#include "FlashIAP.h"
using namespace mbed;
@ -110,6 +111,11 @@ static inline uint32_t align_up(uint32_t val, uint32_t size)
return (((val - 1) / size) + 1) * size;
}
static inline uint32_t align_down(uint64_t val, uint64_t size)
{
return (((val) / size)) * size;
}
static uint32_t calc_crc(uint32_t init_crc, uint32_t data_size, const void *data_buf)
{
@ -1422,6 +1428,136 @@ int TDBStore::reserved_data_get(void *reserved_data, size_t reserved_data_buf_si
return ret;
}
int TDBStore::get_default_flash_addresses(bd_addr_t *start_address, bd_size_t *size)
{
int ret = MBED_SUCCESS;
#if COMPONENT_FLASHIAP
FlashIAP flash;
if (flash.init() != 0) {
return MBED_ERROR_INITIALIZATION_FAILED;
}
// Use the last 2 sectors or 10 pages of flash for the TDBStore by default (whichever is larger)
// For each area: must be a minimum of 1 page of reserved and 2 pages for master record
static const int STORE_SECTORS = 2;
static const int STORE_PAGES = 10;
// Let's work from end of the flash backwards
bd_addr_t curr_addr = flash.get_flash_start() + flash.get_flash_size();
bd_size_t sector_space = 0;
for (int i = STORE_SECTORS; i; i--) {
bd_size_t sector_size = flash.get_sector_size(curr_addr - 1);
sector_space += sector_size;
}
bd_size_t page_space = flash.get_page_size() * STORE_PAGES;
if (sector_space > page_space) {
curr_addr -= sector_space;
*size = sector_space;
} else {
curr_addr -= page_space;
*size = page_space;
}
// Store- and application-sectors mustn't overlap
uint32_t first_wrtbl_sector_addr =
(uint32_t)(align_up(FLASHIAP_APP_ROM_END_ADDR, flash.get_sector_size(FLASHIAP_APP_ROM_END_ADDR)));
MBED_ASSERT(curr_addr >= first_wrtbl_sector_addr);
if (curr_addr < first_wrtbl_sector_addr) {
ret = MBED_ERROR_MEDIA_FULL;
} else {
*start_address = curr_addr;
}
flash.deinit();
#endif
return ret;
}
int TDBStore::get_flash_bounds_from_config(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;
if (!start_address || !size) {
return MBED_ERROR_INVALID_ARGUMENT;
}
int ret = flash.init();
if (ret != 0) {
return MBED_ERROR_INITIALIZATION_FAILED;
}
// Get flash parameters
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();
if (*start_address == 0) {
if (*size == 0) {
flash.deinit();
return MBED_ERROR_INVALID_ARGUMENT;
}
*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) {
// Start address not aligned - size should likely be changed so that it is
flash.deinit();
return MBED_ERROR_INVALID_SIZE;
}
} else {
aligned_start_address = align_down(*start_address, flash.get_sector_size(*start_address));
if (*start_address != aligned_start_address) {
// Start address not aligned - size should likely be changed so that it is
flash.deinit();
return MBED_ERROR_INVALID_SIZE;
}
if (*size == 0) {
//The block device will have all space from start address to the end of the flash
*size = (flash_end_address - *start_address);
} else {
// Do checks on end address to make sure configured start address/size are good
end_address = *start_address + *size;
if (end_address > flash_end_address) {
// End address is out of flash bounds
flash.deinit();
return MBED_ERROR_INVALID_SIZE;
}
aligned_end_address = align_up(end_address, flash.get_sector_size(end_address - 1));
if (end_address != aligned_end_address) {
// End address not aligned - size should likely be changed so that it is
flash.deinit();
return MBED_ERROR_INVALID_SIZE;
}
}
}
flash.deinit();
if (*start_address < flash_first_writable_sector_address) {
// Calculated start address overlaps with ROM
return MBED_ERROR_MEDIA_FULL;
}
#endif
return MBED_SUCCESS;
}
void TDBStore::offset_in_erase_unit(uint8_t area, uint32_t offset,
uint32_t &offset_from_start, uint32_t &dist_to_end)

View File

@ -280,6 +280,33 @@ public:
virtual int reserved_data_get(void *reserved_data, size_t reserved_data_buf_size,
size_t *actual_data_size = 0);
/**
* @brief Get the default TDBStore flash start address and size.
*
* @param[out] start_address Default TDBStore start address in flash.
* @param[out] size Default TDBStore size.
*
* @returns MBED_SUCCESS Success.
* MBED_ERROR_INITIALIZATION_FAILED Failed to initialize flash driver.
* MBED_ERROR_MEDIA_FULL Default TDBStore space overlaps with program memory.
*/
static int get_default_flash_addresses(bd_addr_t *start_address, bd_size_t *size);
/**
* @brief Get the TDBStore flash bounds from the configured start address and size.
* Configured start address/size must not both be 0.
*
* @param[inout] start_address Configured TDBStore start address in flash.
* @param[inout] size Configured TDBStore size.
*
* @returns MBED_SUCCESS Success.
* MBED_ERROR_INVALID_ARGUMENT One of the arguments is NULL or both the configured start address and size are 0.
* MBED_ERROR_INITIALIZATION_FAILED Failed to initialize flash driver.
* MBED_ERROR_INVALID_SIZE Configured size results in misaligned start/end address or end address past the end of flash.
* MBED_ERROR_MEDIA_FULL Configured start address/size results in bounds overlapping with program memory.
*/
static int get_flash_bounds_from_config(bd_addr_t *start_address, bd_size_t *size);
#if !defined(DOXYGEN_ONLY)
private: