Introduce block_store factory
To allow for reuse of code concerned with constructing different
block_store stacks, a factory directory is added for different
factories to live. Two factories have been added so far: the
ref_ram factory constructs a ram-backed block store, partitioned
using the reference partition configuration expected by test cases.
The client factory constructs a block_storage_client that talks to
a remote block storage service provider.
Signed-off-by: Julian Hall <julian.hall@arm.com>
Change-Id: Ib4c02f12a0742fc9b75143de612dd273f2bfffa9
diff --git a/components/service/block_storage/factory/block_store_factory.h b/components/service/block_storage/factory/block_store_factory.h
new file mode 100644
index 0000000..a45f517
--- /dev/null
+++ b/components/service/block_storage/factory/block_store_factory.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef BLOCK_STORE_FACTORY_H
+#define BLOCK_STORE_FACTORY_H
+
+#include <util.h>
+#include "service/block_storage/block_store/block_store.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Defines a common interface for constructing the block_store
+ * stack needed for a deployment. The concrete factory will depend
+ * on which factory component has been deployed. This interface
+ * is only intended to be used where only one type block store
+ * factory is needed in a deployment. This ifdef allows multiple
+ * block_store factory methods to be combined within a single build,
+ * each with a distinct function name. This is needed for some test
+ * deployments where different block_store stacks are constructed
+ * for different test cases.
+ */
+#ifdef CONCRETE_BLOCK_STORE_FACTORY
+
+#define BLOCK_STORE_FACTORY_FUNC_CREATE CONCAT(CONCRETE_BLOCK_STORE_FACTORY, _create)
+#define BLOCK_STORE_FACTORY_FUNC_DESTROY CONCAT(CONCRETE_BLOCK_STORE_FACTORY, _destroy)
+
+struct block_store *BLOCK_STORE_FACTORY_FUNC_CREATE(void);
+void BLOCK_STORE_FACTORY_FUNC_DESTROY(struct block_store *block_store);
+
+#endif
+
+/**
+ * \brief Factory method to create a block_store
+ *
+ * \return A pointer to the constructed block_store (NULL on failure)
+ */
+static inline struct block_store *block_store_factory_create(void)
+{
+#ifdef CONCRETE_BLOCK_STORE_FACTORY
+ return BLOCK_STORE_FACTORY_FUNC_CREATE();
+#else
+ #error No concrete block store factory
+#endif
+}
+
+/**
+ * \brief Destroys a block_store created with block_store_factory_create
+ *
+ * \param[in] block_store The block store to destroy
+ */
+static inline void block_store_factory_destroy(struct block_store *block_store)
+{
+#ifdef CONCRETE_BLOCK_STORE_FACTORY
+ return BLOCK_STORE_FACTORY_FUNC_DESTROY(block_store);
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BLOCK_STORE_FACTORY_H */
diff --git a/components/service/block_storage/factory/client/block_store_factory.c b/components/service/block_storage/factory/client/block_store_factory.c
new file mode 100644
index 0000000..c84faef
--- /dev/null
+++ b/components/service/block_storage/factory/client/block_store_factory.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include "service/block_storage/block_store/client/block_storage_client.h"
+#include "protocols/rpc/common/packed-c/encoding.h"
+#include "service_locator.h"
+
+struct block_store_assembly {
+ struct block_storage_client client;
+ rpc_session_handle rpc_session_handle;
+ struct service_context *service_context;
+};
+
+struct block_store *client_block_store_factory_create(const char *sn)
+{
+ struct block_store *product = NULL;
+ struct block_store_assembly *assembly =
+ (struct block_store_assembly *)calloc(1, sizeof(struct block_store_assembly));
+
+ if (assembly) {
+
+ int status;
+
+ assembly->rpc_session_handle = NULL;
+ assembly->service_context = NULL;
+
+ service_locator_init();
+
+ assembly->service_context = service_locator_query(sn, &status);
+
+ if (assembly->service_context) {
+
+ struct rpc_caller *caller;
+
+ assembly->rpc_session_handle = service_context_open(
+ assembly->service_context,
+ TS_RPC_ENCODING_PACKED_C,
+ &caller);
+
+ if (assembly->rpc_session_handle)
+ product = block_storage_client_init(&assembly->client, caller);
+ }
+
+ if (!product) {
+
+ /* Something went wrong! */
+ free(assembly);
+ }
+ }
+
+ return product;
+}
+
+void client_block_store_factory_destroy(struct block_store *block_store)
+{
+ if (block_store) {
+
+ size_t offset_into_assembly =
+ offsetof(struct block_store_assembly, client) +
+ offsetof(struct block_storage_client, base_block_store);
+
+ struct block_store_assembly *assembly = (struct block_store_assembly *)
+ ((uint8_t *)block_store - offset_into_assembly);
+
+ block_storage_client_deinit(&assembly->client);
+
+ if (assembly->service_context) {
+
+ if (assembly->rpc_session_handle) {
+ service_context_close(
+ assembly->service_context, assembly->rpc_session_handle);
+ assembly->rpc_session_handle = NULL;
+ }
+
+ service_context_relinquish(assembly->service_context);
+ assembly->service_context = NULL;
+ }
+
+ free(assembly);
+ }
+}
diff --git a/components/service/block_storage/factory/client/block_store_factory.h b/components/service/block_storage/factory/client/block_store_factory.h
new file mode 100644
index 0000000..6feebf4
--- /dev/null
+++ b/components/service/block_storage/factory/client/block_store_factory.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef CLIENT_BLOCK_STORE_FACTORY_H
+#define CLIENT_BLOCK_STORE_FACTORY_H
+
+#include "service/block_storage/block_store/block_store.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * A block store factory that constructs a block_storage_client
+ * (which is a block_store specialization). The constructed client
+ * establishes a session with the discovered block storage service
+ * provider.
+ */
+
+/**
+ * \brief Factory method to create a block_store
+ *
+ * \param[in] sn Service name identifying block storage provider
+ * \return A pointer to the constructed block_store (NULL on failure)
+ */
+struct block_store *client_block_store_factory_create(const char *sn);
+
+/**
+ * \brief Destroys a block_store created with block_store_factory_create
+ *
+ * \param[in] block_store The block store to destroy
+ */
+void client_block_store_factory_destroy(struct block_store *block_store);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CLIENT_BLOCK_STORE_FACTORY_H */
diff --git a/components/service/block_storage/factory/client/component.cmake b/components/service/block_storage/factory/client/component.cmake
new file mode 100644
index 0000000..759da54
--- /dev/null
+++ b/components/service/block_storage/factory/client/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}/block_store_factory.c"
+ )
diff --git a/components/service/block_storage/factory/ref_ram/block_store_factory.c b/components/service/block_storage/factory/ref_ram/block_store_factory.c
new file mode 100644
index 0000000..631a933
--- /dev/null
+++ b/components/service/block_storage/factory/ref_ram/block_store_factory.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include "block_store_factory.h"
+#include "service/block_storage/block_store/device/ram/ram_block_store.h"
+#include "service/block_storage/block_store/partitioned/partitioned_block_store.h"
+#include "service/block_storage/config/ref/ref_partition_configurator.h"
+
+struct block_store_assembly {
+ struct ram_block_store ram_block_store;
+ struct partitioned_block_store partitioned_block_store;
+};
+
+struct block_store *ref_ram_block_store_factory_create(void)
+{
+ struct block_store *product = NULL;
+ struct block_store_assembly *assembly =
+ (struct block_store_assembly *)calloc(1, sizeof(struct block_store_assembly));
+
+ if (assembly) {
+
+ struct uuid_octets back_store_guid;
+
+ memset(&back_store_guid, 0, sizeof(back_store_guid));
+
+ /* Initialise a ram_block_store to provide underlying storage */
+ struct block_store *back_store = ram_block_store_init(
+ &assembly->ram_block_store,
+ &back_store_guid,
+ REF_PARTITION_BACK_STORE_SIZE,
+ REF_PARTITION_BLOCK_SIZE);
+
+ /* Stack a partitioned_block_store over the back store */
+ product = partitioned_block_store_init(
+ &assembly->partitioned_block_store,
+ 0,
+ &back_store_guid,
+ back_store,
+ NULL);
+
+ /* Use the reference partition configuration */
+ ref_partition_configure(&assembly->partitioned_block_store);
+
+ if (!product) {
+
+ /* Something went wrong! */
+ free(assembly);
+ }
+ }
+
+ return product;
+}
+
+void ref_ram_block_store_factory_destroy(struct block_store *block_store)
+{
+ if (block_store) {
+
+ size_t offset_into_assembly =
+ offsetof(struct block_store_assembly, partitioned_block_store) +
+ offsetof(struct partitioned_block_store, base_block_store);
+
+ struct block_store_assembly *assembly = (struct block_store_assembly *)
+ ((uint8_t *)block_store - offset_into_assembly);
+
+ partitioned_block_store_deinit(&assembly->partitioned_block_store);
+ ram_block_store_deinit(&assembly->ram_block_store);
+
+ free(assembly);
+ }
+}
diff --git a/components/service/block_storage/factory/ref_ram/block_store_factory.h b/components/service/block_storage/factory/ref_ram/block_store_factory.h
new file mode 100644
index 0000000..189d208
--- /dev/null
+++ b/components/service/block_storage/factory/ref_ram/block_store_factory.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef REF_RAM_BLOCK_STORE_FACTORY_H
+#define REF_RAM_BLOCK_STORE_FACTORY_H
+
+#include "service/block_storage/block_store/block_store.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * A block store factory that constructs a partitioned block store with
+ * a ram back store. The reference partition configuration is used to
+ * provide a set of storage partitions that match the expectations of
+ * test cases. This factory should only really be used for test deployments.
+ */
+
+/**
+ * \brief Factory method to create a block_store
+ *
+ * \return A pointer to the constructed block_store (NULL on failure)
+ */
+struct block_store *ref_ram_block_store_factory_create(void);
+
+/**
+ * \brief Destroys a block_store created with block_store_factory_create
+ *
+ * \param[in] block_store The block store to destroy
+ */
+void ref_ram_block_store_factory_destroy(struct block_store *block_store);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* REF_RAM_BLOCK_STORE_FACTORY_H */
diff --git a/components/service/block_storage/factory/ref_ram/component.cmake b/components/service/block_storage/factory/ref_ram/component.cmake
new file mode 100644
index 0000000..7277cb3
--- /dev/null
+++ b/components/service/block_storage/factory/ref_ram/component.cmake
@@ -0,0 +1,20 @@
+#-------------------------------------------------------------------------------
+# 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}/block_store_factory.c"
+ )
+
+# If none already defined, make this the default factory for the deployment
+if (NOT DEFINED TS_BLOCK_STORE_FACTORY)
+ set(TS_BLOCK_STORE_FACTORY "ref_ram_block_store_factory")
+ target_compile_definitions(${TGT} PRIVATE
+ CONCRETE_BLOCK_STORE_FACTORY=${TS_BLOCK_STORE_FACTORY})
+endif()
\ No newline at end of file
diff --git a/components/service/block_storage/test/service/block_storage_service_tests.cpp b/components/service/block_storage/test/service/block_storage_service_tests.cpp
index c86f8a8..00521b9 100644
--- a/components/service/block_storage/test/service/block_storage_service_tests.cpp
+++ b/components/service/block_storage/test/service/block_storage_service_tests.cpp
@@ -6,10 +6,9 @@
#include <cstring>
#include "common/uuid/uuid.h"
-#include "service/block_storage/block_store/client/block_storage_client.h"
+#include "service/block_storage/block_store/block_store.h"
+#include "service/block_storage/factory/client/block_store_factory.h"
#include "service/block_storage/config/ref/ref_partition_configurator.h"
-#include "protocols/rpc/common/packed-c/encoding.h"
-#include "service_locator.h"
#include "CppUTest/TestHarness.h"
/**
@@ -24,23 +23,9 @@
{
void setup()
{
- struct rpc_caller *caller;
- int status;
+ m_block_store = client_block_store_factory_create(
+ "sn:trustedfirmware.org:block-storage:0");
- m_rpc_session_handle = NULL;
- m_service_context = NULL;
-
- service_locator_init();
-
- m_service_context =
- service_locator_query("sn:trustedfirmware.org:block-storage:0", &status);
- CHECK_TRUE(m_service_context);
-
- m_rpc_session_handle =
- service_context_open(m_service_context, TS_RPC_ENCODING_PACKED_C, &caller);
- CHECK_TRUE(m_rpc_session_handle);
-
- m_block_store = block_storage_client_init(&m_client, caller);
CHECK_TRUE(m_block_store);
uuid_parse_to_octets(REF_PARTITION_1_GUID,
@@ -55,25 +40,11 @@
void teardown()
{
- block_storage_client_deinit(&m_client);
-
- if (m_service_context) {
-
- if (m_rpc_session_handle) {
- service_context_close(m_service_context, m_rpc_session_handle);
- m_rpc_session_handle = NULL;
- }
-
- service_context_relinquish(m_service_context);
- m_service_context = NULL;
- }
+ client_block_store_factory_destroy(m_block_store);
}
static const uint32_t LOCAL_CLIENT_ID = 1;
- rpc_session_handle m_rpc_session_handle;
- struct service_context *m_service_context;
- struct block_storage_client m_client;
struct block_store *m_block_store;
struct uuid_octets m_partition_1_guid;
struct uuid_octets m_partition_2_guid;
diff --git a/components/service/locator/standalone/services/block-storage/block_storage_service_context.cpp b/components/service/locator/standalone/services/block-storage/block_storage_service_context.cpp
index b105c08..2d1227d 100644
--- a/components/service/locator/standalone/services/block-storage/block_storage_service_context.cpp
+++ b/components/service/locator/standalone/services/block-storage/block_storage_service_context.cpp
@@ -6,15 +6,14 @@
#include <assert.h>
#include <cstring>
-#include "service/block_storage/config/ref/ref_partition_configurator.h"
#include "service/block_storage/provider/serializer/packed-c/packedc_block_storage_serializer.h"
+#include "service/block_storage/factory/ref_ram/block_store_factory.h"
#include "block_storage_service_context.h"
block_storage_service_context::block_storage_service_context(const char *sn) :
standalone_service_context(sn),
m_block_storage_provider(),
- m_ram_block_store(),
- m_partitioned_block_store()
+ m_block_store(NULL)
{
}
@@ -26,33 +25,14 @@
void block_storage_service_context::do_init()
{
- /* Initialize a ram_block_store to use as the back store */
- struct uuid_octets back_store_guid;
- memset(&back_store_guid, 0, sizeof(back_store_guid));
-
- struct block_store *back_store = ram_block_store_init(
- &m_ram_block_store,
- &back_store_guid,
- REF_PARTITION_BACK_STORE_SIZE,
- REF_PARTITION_BLOCK_SIZE);
- assert(back_store);
-
- /* Stack a partitioned_block_store over the back store */
- struct block_store *front_store = partitioned_block_store_init(
- &m_partitioned_block_store,
- 0,
- &back_store_guid,
- back_store,
- NULL);
- assert(front_store);
-
- /* Use the reference partition configuration */
- ref_partition_configure(&m_partitioned_block_store);
+ /* Create backend block store */
+ m_block_store = ref_ram_block_store_factory_create();
+ assert(m_block_store);
/* Initialise the block storage service provider */
struct rpc_interface *rpc_iface = block_storage_provider_init(
&m_block_storage_provider,
- front_store);
+ m_block_store);
assert(rpc_iface);
block_storage_provider_register_serializer(
@@ -66,6 +46,5 @@
void block_storage_service_context::do_deinit()
{
block_storage_provider_deinit(&m_block_storage_provider);
- partitioned_block_store_deinit(&m_partitioned_block_store);
- ram_block_store_deinit(&m_ram_block_store);
+ ref_ram_block_store_factory_destroy(m_block_store);
}
diff --git a/components/service/locator/standalone/services/block-storage/block_storage_service_context.h b/components/service/locator/standalone/services/block-storage/block_storage_service_context.h
index 81a03dd..c47aede 100644
--- a/components/service/locator/standalone/services/block-storage/block_storage_service_context.h
+++ b/components/service/locator/standalone/services/block-storage/block_storage_service_context.h
@@ -10,8 +10,7 @@
#include <service/locator/standalone/standalone_service_context.h>
#include <rpc/direct/direct_caller.h>
#include <service/block_storage/provider/block_storage_provider.h>
-#include <service/block_storage/block_store/device/ram/ram_block_store.h>
-#include <service/block_storage/block_store/partitioned/partitioned_block_store.h>
+#include <service/block_storage/block_store/block_store.h>
class block_storage_service_context : public standalone_service_context
{
@@ -25,8 +24,7 @@
void do_deinit();
struct block_storage_provider m_block_storage_provider;
- struct ram_block_store m_ram_block_store;
- struct partitioned_block_store m_partitioned_block_store;
+ struct block_store *m_block_store;
};
#endif /* STANDALONE_BLOCK_STORAGE_SERVICE_CONTEXT_H */
diff --git a/deployments/component-test/component-test.cmake b/deployments/component-test/component-test.cmake
index d5edf4f..ad67ad7 100644
--- a/deployments/component-test/component-test.cmake
+++ b/deployments/component-test/component-test.cmake
@@ -87,6 +87,7 @@
"components/service/block_storage/provider"
"components/service/block_storage/provider/serializer/packed-c"
"components/service/block_storage/config/ref"
+ "components/service/block_storage/factory/ref_ram"
"components/service/crypto/client/cpp"
"components/service/crypto/client/cpp/protocol/protobuf"
"components/service/crypto/client/cpp/protocol/packed-c"
diff --git a/deployments/libts/linux-pc/CMakeLists.txt b/deployments/libts/linux-pc/CMakeLists.txt
index e034e80..832983b 100644
--- a/deployments/libts/linux-pc/CMakeLists.txt
+++ b/deployments/libts/linux-pc/CMakeLists.txt
@@ -70,6 +70,7 @@
"components/service/block_storage/provider"
"components/service/block_storage/provider/serializer/packed-c"
"components/service/block_storage/config/ref"
+ "components/service/block_storage/factory/ref_ram"
"components/service/crypto/provider"
"components/service/crypto/provider/serializer/protobuf"
"components/service/crypto/provider/serializer/packed-c"
diff --git a/deployments/ts-service-test/linux-pc/CMakeLists.txt b/deployments/ts-service-test/linux-pc/CMakeLists.txt
index 2690dab..99c1db2 100644
--- a/deployments/ts-service-test/linux-pc/CMakeLists.txt
+++ b/deployments/ts-service-test/linux-pc/CMakeLists.txt
@@ -84,6 +84,7 @@
"components/service/smm_variable/test/service"
"components/service/block_storage/block_store"
"components/service/block_storage/block_store/client"
+ "components/service/block_storage/factory/client"
"components/service/block_storage/test/service"
"components/common/uuid"
)