Decouple SFS block size from underlying block store
The secure flash store limits the maximum file size to the block
size of the associated flash driver. In practice, the block size
of real flash devices will be too small to accommodate objects
such as RSA keys or certificates. To lift this restriction,
the sfs_flash_block_store_adapter can now present a larger block
size to the SFS and map read, write and erase operations to
multiple block store blocks. This allows the SFS to meet
storage requirements when working with real storage devices.
Signed-off-by: Julian Hall <julian.hall@arm.com>
Change-Id: I113ae825d5373b67d9d2b32451d112cce047dfa3
diff --git a/components/service/secure_storage/backend/secure_flash_store/flash/block_store_adapter/sfs_flash_block_store_adapter.c b/components/service/secure_storage/backend/secure_flash_store/flash/block_store_adapter/sfs_flash_block_store_adapter.c
index 9c05b30..0ff0c99 100644
--- a/components/service/secure_storage/backend/secure_flash_store/flash/block_store_adapter/sfs_flash_block_store_adapter.c
+++ b/components/service/secure_storage/backend/secure_flash_store/flash/block_store_adapter/sfs_flash_block_store_adapter.c
@@ -15,6 +15,22 @@
return (struct sfs_flash_block_store_adapter *)info->flash_dev;
}
+static void calc_sub_block_pos(
+ const struct sfs_flash_block_store_adapter *context,
+ uint32_t block_id,
+ size_t offset,
+ uint32_t *sub_block_lba,
+ size_t *sub_block_offset)
+{
+ size_t sub_block_size = context->flash_info.sector_size;
+
+ *sub_block_lba =
+ block_id * context->blocks_per_flash_block +
+ offset / sub_block_size;
+
+ *sub_block_offset = offset % sub_block_size;
+}
+
static psa_status_t sfs_flash_init(
const struct sfs_flash_info_t *info)
{
@@ -34,20 +50,40 @@
size_t offset,
size_t size)
{
- psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+ psa_status_t status = PSA_SUCCESS;
struct sfs_flash_block_store_adapter *context = get_context(info);
- size_t bytes_read = 0;
+ size_t total_bytes_read = 0;
+ uint32_t sub_block_lba;
+ size_t sub_block_offset;
- status = block_store_read(context->block_store,
- context->client_id,
- context->partition_handle,
- block_id,
- offset,
- size,
- buff,
- &bytes_read);
+ calc_sub_block_pos(context, block_id, offset, &sub_block_lba, &sub_block_offset);
- if ((status == PSA_SUCCESS) && (bytes_read != size))
+ while (total_bytes_read < size) {
+
+ size_t bytes_read = 0;
+ size_t bytes_to_read = size - total_bytes_read;
+
+ if (bytes_to_read > context->flash_info.sector_size)
+ bytes_to_read = context->flash_info.sector_size;
+
+ status = block_store_read(context->block_store,
+ context->client_id,
+ context->partition_handle,
+ sub_block_lba,
+ sub_block_offset,
+ bytes_to_read,
+ &buff[total_bytes_read],
+ &bytes_read);
+
+ if (status != PSA_SUCCESS)
+ break;
+
+ total_bytes_read += bytes_read;
+ ++sub_block_lba;
+ sub_block_offset = 0;
+ }
+
+ if ((status == PSA_SUCCESS) && (total_bytes_read != size))
/* Requested size invalid */
status = PSA_ERROR_INVALID_ARGUMENT;
@@ -61,20 +97,40 @@
size_t offset,
size_t size)
{
- psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+ psa_status_t status = PSA_SUCCESS;
struct sfs_flash_block_store_adapter *context = get_context(info);
- size_t bytes_written = 0;
+ size_t total_bytes_written = 0;
+ uint32_t sub_block_lba;
+ size_t sub_block_offset;
- status = block_store_write(context->block_store,
- context->client_id,
- context->partition_handle,
- block_id,
- offset,
- buff,
- size,
- &bytes_written);
+ calc_sub_block_pos(context, block_id, offset, &sub_block_lba, &sub_block_offset);
- if ((status == PSA_SUCCESS) && (bytes_written != size))
+ while (total_bytes_written < size) {
+
+ size_t bytes_written = 0;
+ size_t bytes_to_write = size - total_bytes_written;
+
+ if (bytes_to_write > context->flash_info.sector_size)
+ bytes_to_write = context->flash_info.sector_size;
+
+ status = block_store_write(context->block_store,
+ context->client_id,
+ context->partition_handle,
+ sub_block_lba,
+ sub_block_offset,
+ &buff[total_bytes_written],
+ bytes_to_write,
+ &bytes_written);
+
+ if (status != PSA_SUCCESS)
+ break;
+
+ total_bytes_written += bytes_written;
+ ++sub_block_lba;
+ sub_block_offset = 0;
+ }
+
+ if ((status == PSA_SUCCESS) && (total_bytes_written != size))
/* Requested size invalid */
status = PSA_ERROR_INVALID_ARGUMENT;
@@ -95,11 +151,16 @@
{
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
struct sfs_flash_block_store_adapter *context = get_context(info);
+ uint32_t sub_block_lba;
+ size_t sub_block_offset;
+
+ calc_sub_block_pos(context, block_id, 0, &sub_block_lba, &sub_block_offset);
status = block_store_erase(context->block_store,
context->client_id,
context->partition_handle,
- block_id, 1);
+ sub_block_lba,
+ context->blocks_per_flash_block);
return status;
}
@@ -109,6 +170,7 @@
uint32_t client_id,
struct block_store *block_store,
const struct uuid_octets *partition_guid,
+ size_t min_flash_block_size,
size_t max_num_files,
const struct sfs_flash_info_t **flash_info)
{
@@ -130,21 +192,27 @@
/* Initialise interface used by sfs */
info->flash_dev = context;
- info->init = sfs_flash_init,
- info->read = sfs_flash_read,
- info->write = sfs_flash_write,
- info->flush = sfs_flash_flush,
- info->erase = sfs_flash_erase,
+ info->init = sfs_flash_init;
+ info->read = sfs_flash_read;
+ info->write = sfs_flash_write;
+ info->flush = sfs_flash_flush;
+ info->erase = sfs_flash_erase;
/* Attributes that are fixed when using a block_store */
info->flash_area_addr = 0;
info->program_unit = sizeof(uint8_t);
info->erase_val = 0xff;
- /* Underlying storage partition parameters */
+ /* Flash block size is an integer multiple of the underlying
+ * block size that accommodates the specified minimum flash block size.
+ */
+ context->blocks_per_flash_block =
+ (min_flash_block_size + partition_info.block_size - 1) / partition_info.block_size;
+
+ /* Set partition parameters presented to SFS */
info->sector_size = (uint16_t)partition_info.block_size;
- info->block_size = (uint16_t)partition_info.block_size;
- info->num_blocks = (uint16_t)partition_info.num_blocks;
+ info->block_size = (uint16_t)(partition_info.block_size * context->blocks_per_flash_block);
+ info->num_blocks = (uint16_t)(partition_info.num_blocks / context->blocks_per_flash_block);
/* sfs specific configuration */
info->max_file_size = (uint16_t)info->block_size;
diff --git a/components/service/secure_storage/backend/secure_flash_store/flash/block_store_adapter/sfs_flash_block_store_adapter.h b/components/service/secure_storage/backend/secure_flash_store/flash/block_store_adapter/sfs_flash_block_store_adapter.h
index a88f1b9..270170e 100644
--- a/components/service/secure_storage/backend/secure_flash_store/flash/block_store_adapter/sfs_flash_block_store_adapter.h
+++ b/components/service/secure_storage/backend/secure_flash_store/flash/block_store_adapter/sfs_flash_block_store_adapter.h
@@ -36,6 +36,7 @@
struct block_store *block_store;
storage_partition_handle_t partition_handle;
uint32_t client_id;
+ size_t blocks_per_flash_block;
};
/**
@@ -49,6 +50,7 @@
* \param[in] client_id The client id for the environment
* \param[in] block_store The associated block store
* \param[in] partition_guid The storage partition to use
+ * \param[in] min_flash_block_size Minimum sfs block size
* \param[in] max_num_files An sfs configuration parameter
* \param[out] flash_info The sfs flash interface structure
*
@@ -59,6 +61,7 @@
uint32_t client_id,
struct block_store *block_store,
const struct uuid_octets *partition_guid,
+ size_t min_flash_block_size,
size_t max_num_files,
const struct sfs_flash_info_t **flash_info);
diff --git a/components/service/secure_storage/backend/secure_flash_store/test/sfs_block_store_tests.cpp b/components/service/secure_storage/backend/secure_flash_store/test/sfs_block_store_tests.cpp
index c77ad27..64fb952 100644
--- a/components/service/secure_storage/backend/secure_flash_store/test/sfs_block_store_tests.cpp
+++ b/components/service/secure_storage/backend/secure_flash_store/test/sfs_block_store_tests.cpp
@@ -19,65 +19,67 @@
*/
TEST_GROUP(SfsBlockStoreTests)
{
- void setup()
- {
- struct uuid_octets guid;
- const struct sfs_flash_info_t *flash_info = NULL;
+ void setup()
+ {
+ struct uuid_octets guid;
+ const struct sfs_flash_info_t *flash_info = NULL;
- uuid_parse_to_octets(REF_PARTITION_1_GUID, guid.octets, sizeof(guid.octets));
+ uuid_parse_to_octets(REF_PARTITION_2_GUID, guid.octets, sizeof(guid.octets));
- block_store = ref_ram_block_store_factory_create();
- CHECK_TRUE(block_store);
+ block_store = ref_ram_block_store_factory_create();
+ CHECK_TRUE(block_store);
- psa_status_t status = sfs_flash_block_store_adapter_init(
- &sfs_flash_adapter,
- CLIENT_ID,
- block_store,
- &guid,
- MAX_NUM_FILES,
- &flash_info);
+ psa_status_t status = sfs_flash_block_store_adapter_init(
+ &sfs_flash_adapter,
+ CLIENT_ID,
+ block_store,
+ &guid,
+ MIN_FLASH_BLOCK_SIZE,
+ MAX_NUM_FILES,
+ &flash_info);
- LONGS_EQUAL(PSA_SUCCESS, status);
- CHECK_TRUE(flash_info);
+ LONGS_EQUAL(PSA_SUCCESS, status);
+ CHECK_TRUE(flash_info);
- struct storage_backend *storage_backend = sfs_init(flash_info);
- CHECK_TRUE(storage_backend);
+ struct storage_backend *storage_backend = sfs_init(flash_info);
+ CHECK_TRUE(storage_backend);
- psa_its_frontend_init(storage_backend);
- psa_ps_frontend_init(storage_backend);
- }
+ psa_its_frontend_init(storage_backend);
+ psa_ps_frontend_init(storage_backend);
+ }
- void teardown()
- {
- sfs_flash_block_store_adapter_deinit(&sfs_flash_adapter);
- ref_ram_block_store_factory_destroy(block_store);
+ void teardown()
+ {
+ sfs_flash_block_store_adapter_deinit(&sfs_flash_adapter);
+ ref_ram_block_store_factory_destroy(block_store);
- block_store = NULL;
- }
+ block_store = NULL;
+ }
- static const uint32_t CLIENT_ID = 10;
- static const size_t MAX_NUM_FILES = 2;
+ static const uint32_t CLIENT_ID = 10;
+ static const size_t MAX_NUM_FILES = 10;
+ static const size_t MIN_FLASH_BLOCK_SIZE = 4096;
- struct block_store *block_store;
- struct sfs_flash_block_store_adapter sfs_flash_adapter;
+ struct block_store *block_store;
+ struct sfs_flash_block_store_adapter sfs_flash_adapter;
};
TEST(SfsBlockStoreTests, itsStoreNewItem)
{
- its_api_tests::storeNewItem();
+ its_api_tests::storeNewItem();
}
TEST(SfsBlockStoreTests, itsStorageLimitTest)
{
- its_api_tests::storageLimitTest(5000);
+ its_api_tests::storageLimitTest(5000);
}
TEST(SfsBlockStoreTests, psCreateAndSet)
{
- ps_api_tests::createAndSet();
+ ps_api_tests::createAndSet();
}
TEST(SfsBlockStoreTests, psCreateAndSetExtended)
{
- ps_api_tests::createAndSetExtended();
+ ps_api_tests::createAndSetExtended();
}