Add null_block_store component
A block_store that actually has no storage. Writes are ignored and
read blocks return all zeros. Can be used as a placeholder during
integration.
Signed-off-by: Julian Hall <julian.hall@arm.com>
Change-Id: I25fa2b56cfa5a87a782aa2d2d730f1095eeedaca
diff --git a/components/service/block_storage/block_store/device/null/component.cmake b/components/service/block_storage/block_store/device/null/component.cmake
new file mode 100644
index 0000000..50a102c
--- /dev/null
+++ b/components/service/block_storage/block_store/device/null/component.cmake
@@ -0,0 +1,13 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+if (NOT DEFINED TGT)
+ message(FATAL_ERROR "mandatory parameter TGT is not defined.")
+endif()
+
+target_sources(${TGT} PRIVATE
+ "${CMAKE_CURRENT_LIST_DIR}/null_block_store.c"
+ )
diff --git a/components/service/block_storage/block_store/device/null/null_block_store.c b/components/service/block_storage/block_store/device/null/null_block_store.c
new file mode 100644
index 0000000..3b0ad2e
--- /dev/null
+++ b/components/service/block_storage/block_store/device/null/null_block_store.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <string.h>
+#include "null_block_store.h"
+
+static psa_status_t null_block_store_get_partition_info(void *context,
+ const struct uuid_octets *partition_guid,
+ struct storage_partition_info *info)
+{
+ struct null_block_store *null_block_store = (struct null_block_store*)context;
+ return block_device_get_partition_info(
+ &null_block_store->base_block_device, partition_guid, info);
+}
+
+static psa_status_t null_block_store_open(void *context,
+ uint32_t client_id,
+ const struct uuid_octets *partition_guid,
+ storage_partition_handle_t *handle)
+{
+ struct null_block_store *null_block_store = (struct null_block_store*)context;
+ return block_device_open(
+ &null_block_store->base_block_device, client_id, partition_guid, handle);
+}
+
+static psa_status_t null_block_store_close(void *context,
+ uint32_t client_id,
+ storage_partition_handle_t handle)
+{
+ struct null_block_store *null_block_store = (struct null_block_store*)context;
+ return block_device_close(
+ &null_block_store->base_block_device, client_id, handle);
+}
+
+static psa_status_t null_block_store_read(void *context,
+ uint32_t client_id,
+ storage_partition_handle_t handle,
+ uint32_t lba,
+ size_t offset,
+ size_t buffer_size,
+ uint8_t *buffer,
+ size_t *data_len)
+{
+ const struct null_block_store *null_block_store = (struct null_block_store*)context;
+ psa_status_t status = block_device_check_access_permitted(
+ &null_block_store->base_block_device, client_id, handle);
+
+ if (status == PSA_SUCCESS) {
+
+ const struct storage_partition *storage_partition =
+ &null_block_store->base_block_device.storage_partition;
+
+ if (storage_partition_is_lba_legal(storage_partition, lba) &&
+ (offset < storage_partition->block_size)) {
+
+ /* Just real zeros */
+ size_t bytes_remaining = storage_partition->block_size - offset;
+ size_t bytes_to_read = (buffer_size < bytes_remaining) ?
+ buffer_size :
+ bytes_remaining;
+
+ memset(buffer, 0, bytes_to_read);
+ *data_len = bytes_to_read;
+ }
+ else {
+
+ status = PSA_ERROR_INVALID_ARGUMENT;
+ }
+ }
+
+ return status;
+}
+
+static psa_status_t null_block_store_write(void *context,
+ uint32_t client_id,
+ storage_partition_handle_t handle,
+ uint32_t lba,
+ size_t offset,
+ const uint8_t *data,
+ size_t data_len,
+ size_t *num_written)
+{
+ struct null_block_store *null_block_store = (struct null_block_store*)context;
+ psa_status_t status = block_device_check_access_permitted(
+ &null_block_store->base_block_device, client_id, handle);
+
+ if (status == PSA_SUCCESS) {
+
+ const struct storage_partition *storage_partition =
+ &null_block_store->base_block_device.storage_partition;
+
+ if (storage_partition_is_lba_legal(storage_partition, lba) &&
+ (offset < storage_partition->block_size)) {
+
+ /* Don't actually write anything */
+ size_t bytes_remaining = storage_partition->block_size - offset;
+ size_t bytes_to_write = (data_len < bytes_remaining) ?
+ data_len :
+ bytes_remaining;
+
+ *num_written = bytes_to_write;
+ }
+ else {
+
+ status = PSA_ERROR_INVALID_ARGUMENT;
+ }
+ }
+
+ return status;
+}
+
+static psa_status_t null_block_store_erase(void *context,
+ uint32_t client_id,
+ storage_partition_handle_t handle,
+ uint32_t begin_lba,
+ size_t num_blocks)
+{
+ struct null_block_store *null_block_store = (struct null_block_store*)context;
+ const struct storage_partition *storage_partition =
+ &null_block_store->base_block_device.storage_partition;
+ psa_status_t status = block_device_check_access_permitted(
+ &null_block_store->base_block_device, client_id, handle);
+
+ /* Sanitize the erase starting point */
+ if ((status == PSA_SUCCESS) &&
+ !storage_partition_is_lba_legal(storage_partition, begin_lba))
+ status = PSA_ERROR_INVALID_ARGUMENT;
+
+ /* Do nothing */
+
+ return status;
+}
+
+struct block_store *null_block_store_init(
+ struct null_block_store *null_block_store,
+ const struct uuid_octets *disk_guid,
+ size_t num_blocks,
+ size_t block_size)
+{
+ /* Define concrete block store interface */
+ static const struct block_store_interface interface =
+ {
+ null_block_store_get_partition_info,
+ null_block_store_open,
+ null_block_store_close,
+ null_block_store_read,
+ null_block_store_write,
+ null_block_store_erase
+ };
+
+ /* Initialize base block_store */
+ null_block_store->base_block_device.base_block_store.context = null_block_store;
+ null_block_store->base_block_device.base_block_store.interface = &interface;
+
+ return block_device_init(
+ &null_block_store->base_block_device, disk_guid, num_blocks, block_size);
+}
+
+void null_block_store_deinit(
+ struct null_block_store *null_block_store)
+{
+ block_device_deinit(&null_block_store->base_block_device);
+}
diff --git a/components/service/block_storage/block_store/device/null/null_block_store.h b/components/service/block_storage/block_store/device/null/null_block_store.h
new file mode 100644
index 0000000..8c4e843
--- /dev/null
+++ b/components/service/block_storage/block_store/device/null/null_block_store.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef NULL_BLOCK_STORE_H
+#define NULL_BLOCK_STORE_H
+
+#include "service/block_storage/block_store/device/block_device.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief null_block_store structure
+ *
+ * A null_block_store is a block_device that will ignore write operations and
+ * always return zero for read blocks. Because there is no storage, a null_block_store
+ * can be any size and support any block size. It is intended to be used as a placeholder
+ * block device during integration.
+ */
+struct null_block_store
+{
+ struct block_device base_block_device;
+};
+
+/**
+ * \brief Initialize a null_block_store
+ *
+ * \param[in] null_block_store The subject null_block_store
+ * \param[in] disk_guid The disk GUID (nil uuid for any)
+ * \param[in] num_blocks The number of contiguous blocks
+ * \param[in] block_size Block size in bytes
+ *
+ * \return Pointer to block_store or NULL on failure
+ */
+struct block_store *null_block_store_init(
+ struct null_block_store *null_block_store,
+ const struct uuid_octets *disk_guid,
+ size_t num_blocks,
+ size_t block_size);
+
+/**
+ * \brief De-initialize a null_block_store
+ *
+ * \param[in] null_block_store The subject null_block_store
+ */
+void null_block_store_deinit(
+ struct null_block_store *null_block_store);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NULL_BLOCK_STORE_H */
diff --git a/deployments/component-test/component-test.cmake b/deployments/component-test/component-test.cmake
index c1b0317..a1be1dd 100644
--- a/deployments/component-test/component-test.cmake
+++ b/deployments/component-test/component-test.cmake
@@ -80,6 +80,7 @@
"components/service/block_storage/block_store/device"
"components/service/block_storage/block_store/device/ram"
"components/service/block_storage/block_store/device/ram/test"
+ "components/service/block_storage/block_store/device/null"
"components/service/block_storage/block_store/partitioned"
"components/service/block_storage/block_store/partitioned/test"
"components/service/crypto/client/cpp"