Add service locator component

Change-Id: I58ad588deff3c0904b3ba8b9162b20440e9ff7d3
Signed-off-by: Julian Hall <julian.hall@arm.com>
diff --git a/components/service/locator/standalone/component.cmake b/components/service/locator/standalone/component.cmake
new file mode 100644
index 0000000..cb75c82
--- /dev/null
+++ b/components/service/locator/standalone/component.cmake
@@ -0,0 +1,17 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2020, 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}/standalone_env.cpp"
+	"${CMAKE_CURRENT_LIST_DIR}/standalone_service_context.cpp"
+	"${CMAKE_CURRENT_LIST_DIR}/standalone_service_registry.cpp"
+	"${CMAKE_CURRENT_LIST_DIR}/standalone_location_strategy.cpp"
+	)
+
diff --git a/components/service/locator/standalone/services/crypto/component.cmake b/components/service/locator/standalone/services/crypto/component.cmake
new file mode 100644
index 0000000..0e5529b
--- /dev/null
+++ b/components/service/locator/standalone/services/crypto/component.cmake
@@ -0,0 +1,14 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2020, 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}/crypto_service_context.cpp"
+	)
+
diff --git a/components/service/locator/standalone/services/crypto/crypto_service_context.cpp b/components/service/locator/standalone/services/crypto/crypto_service_context.cpp
new file mode 100644
index 0000000..e3bc2e8
--- /dev/null
+++ b/components/service/locator/standalone/services/crypto/crypto_service_context.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "crypto_service_context.h"
+
+crypto_service_context::crypto_service_context(const char *sn) :
+    standalone_service_context(sn),
+    m_crypto_provider(),
+    m_storage_provider(),
+    m_storage_caller()
+{
+
+}
+
+crypto_service_context::~crypto_service_context()
+{
+
+}
+
+void crypto_service_context::do_init()
+{
+    struct call_ep *storage_ep = sfs_provider_init(&m_storage_provider);
+    struct rpc_caller *storage_caller = direct_caller_init_default(&m_storage_caller, storage_ep);
+    struct call_ep *crypto_ep = mbed_crypto_provider_init(&m_crypto_provider, storage_caller);
+
+    standalone_service_context::set_call_ep(crypto_ep);
+}
+
+void crypto_service_context::do_deinit()
+{
+    mbed_crypto_provider_deinit(&m_crypto_provider);
+    direct_caller_deinit(&m_storage_caller);
+}
diff --git a/components/service/locator/standalone/services/crypto/crypto_service_context.h b/components/service/locator/standalone/services/crypto/crypto_service_context.h
new file mode 100644
index 0000000..6e79163
--- /dev/null
+++ b/components/service/locator/standalone/services/crypto/crypto_service_context.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STANDALONE_CRYPTO_SERVICE_CONTEXT_H
+#define STANDALONE_CRYPTO_SERVICE_CONTEXT_H
+
+#include <service/locator/standalone/standalone_service_context.h>
+#include <rpc/direct/direct_caller.h>
+#include <service/crypto/provider/mbedcrypto/crypto_provider.h>
+#include <service/secure_storage/provider/secure_flash_store/sfs_provider.h>
+
+class crypto_service_context : public standalone_service_context
+{
+public:
+    crypto_service_context(const char *sn);
+    virtual ~crypto_service_context();
+
+private:
+
+    void do_init();
+    void do_deinit();
+
+    struct mbed_crypto_provider m_crypto_provider;
+    struct sfs_provider m_storage_provider;
+    struct direct_caller m_storage_caller;
+};
+
+#endif /* STANDALONE_CRYPTO_SERVICE_CONTEXT_H */
diff --git a/components/service/locator/standalone/standalone_env.cpp b/components/service/locator/standalone/standalone_env.cpp
new file mode 100644
index 0000000..80d1777
--- /dev/null
+++ b/components/service/locator/standalone/standalone_env.cpp
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <service_locator.h>
+#include <service/locator/standalone/services/crypto/crypto_service_context.h>
+#include "standalone_location_strategy.h"
+#include "standalone_service_registry.h"
+
+void service_locator_envinit(void)
+{
+    static crypto_service_context crypto_context("sn:trustedfirmware.org:crypto:0");
+    standalone_service_registry::instance()->regsiter_service_instance(&crypto_context);
+    service_locator_register_strategy(standalone_location_strategy());
+}
\ No newline at end of file
diff --git a/components/service/locator/standalone/standalone_location_strategy.cpp b/components/service/locator/standalone/standalone_location_strategy.cpp
new file mode 100644
index 0000000..57e370c
--- /dev/null
+++ b/components/service/locator/standalone/standalone_location_strategy.cpp
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "standalone_location_strategy.h"
+#include "standalone_service_registry.h"
+#include "standalone_service_context.h"
+
+static struct service_context *query(const char *sn, int *status)
+{
+    struct service_context *result = NULL;
+    standalone_service_registry *registry = standalone_service_registry::instance();
+    standalone_service_context *query_result = registry->query(sn, status);
+
+    if (query_result) {
+
+        result = query_result->get_service_context();
+    }
+
+    return result;
+}
+
+const struct service_location_strategy *standalone_location_strategy(void)
+{
+    static const struct service_location_strategy strategy = { query };
+    return &strategy;
+}
diff --git a/components/service/locator/standalone/standalone_location_strategy.h b/components/service/locator/standalone/standalone_location_strategy.h
new file mode 100644
index 0000000..7ea57ea
--- /dev/null
+++ b/components/service/locator/standalone/standalone_location_strategy.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STANDALONE_LOCATION_STRATEGY_H
+#define STANDALONE_LOCATION_STRATEGY_H
+
+#include <service_locator.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Returns a service_location_strategy for locating a service instance
+ * from a bundle of standalone service instances that are part of the
+ * client execution context.
+ */
+const struct service_location_strategy *standalone_location_strategy(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* STANDALONE_LOCATION_STRATEGY_H */
\ No newline at end of file
diff --git a/components/service/locator/standalone/standalone_service_context.cpp b/components/service/locator/standalone/standalone_service_context.cpp
new file mode 100644
index 0000000..5e53ebe
--- /dev/null
+++ b/components/service/locator/standalone/standalone_service_context.cpp
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "standalone_service_context.h"
+#include <cassert>
+
+/* Concrete C service_context methods */
+static rpc_session_handle standalone_service_context_open(void *context, struct rpc_caller **caller);
+static void standalone_service_context_close(void *context, rpc_session_handle session_handle);
+static void standalone_service_context_relinquish(void *context);
+
+
+standalone_service_context::standalone_service_context(const char *sn) :
+    m_sn(sn),
+    m_ref_count(0),
+    m_service_context(),
+    m_call_ep(NULL)
+{
+    m_service_context.context = this;
+    m_service_context.open = standalone_service_context_open;
+    m_service_context.close = standalone_service_context_close;
+    m_service_context.relinquish = standalone_service_context_relinquish;
+}
+
+standalone_service_context::~standalone_service_context()
+{
+
+}
+
+void standalone_service_context::init()
+{
+    assert(m_ref_count >= 0);
+
+    if (!m_ref_count) do_init();
+    ++m_ref_count;
+}
+
+void standalone_service_context::deinit()
+{
+    assert(m_ref_count > 0);
+
+    --m_ref_count;
+    if (!m_ref_count) do_deinit();
+}
+
+rpc_session_handle standalone_service_context::open(struct rpc_caller **caller)
+{
+    struct rpc_session *session = new rpc_session(m_call_ep);
+    *caller = session->m_rpc_caller;
+    return static_cast<rpc_session_handle>(session);
+}
+
+void standalone_service_context::close(rpc_session_handle session_handle)
+{
+    struct rpc_session *session = reinterpret_cast<struct rpc_session*>(session_handle);
+    delete session;
+}
+
+const std::string &standalone_service_context::get_service_name() const
+{
+    return m_sn;
+}
+
+struct service_context *standalone_service_context::get_service_context()
+{
+    return &m_service_context;
+}
+
+void standalone_service_context::set_call_ep(call_ep *ep)
+{
+    m_call_ep = ep;
+}
+
+standalone_service_context::rpc_session::rpc_session(struct call_ep *call_ep) :
+    m_direct_caller(),
+    m_rpc_caller()
+{
+    m_rpc_caller = direct_caller_init_default(&m_direct_caller, call_ep);
+}
+
+standalone_service_context::rpc_session::~rpc_session()
+{
+    direct_caller_deinit(&m_direct_caller);
+}
+
+static rpc_session_handle standalone_service_context_open(void *context, struct rpc_caller **caller)
+{
+    rpc_session_handle handle = NULL;
+    standalone_service_context *this_context = reinterpret_cast<standalone_service_context*>(context);
+
+    if (this_context) {
+        handle = this_context->open(caller);
+    }
+
+    return handle;
+}
+
+static void standalone_service_context_close(void *context, rpc_session_handle session_handle)
+{
+    standalone_service_context *this_context = reinterpret_cast<standalone_service_context*>(context);
+
+    if (this_context) {
+        this_context->close(session_handle);
+    }
+}
+
+static void standalone_service_context_relinquish(void *context)
+{
+    standalone_service_context *this_context = reinterpret_cast<standalone_service_context*>(context);
+
+    if (this_context) {
+        this_context->deinit();
+    }
+}
diff --git a/components/service/locator/standalone/standalone_service_context.h b/components/service/locator/standalone/standalone_service_context.h
new file mode 100644
index 0000000..d8ebb1f
--- /dev/null
+++ b/components/service/locator/standalone/standalone_service_context.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STANDALONE_SERVICE_CONTEXT_H
+#define STANDALONE_SERVICE_CONTEXT_H
+
+#include <service_locator.h>
+#include <rpc/common/endpoint/call_ep.h>
+#include <rpc/direct/direct_caller.h>
+#include <string>
+
+class standalone_service_context
+{
+public:
+    standalone_service_context(const char *sn);
+    virtual ~standalone_service_context();
+
+    void init();
+    void deinit();
+
+    rpc_session_handle open(struct rpc_caller **caller);
+    void close(rpc_session_handle session_handle);
+
+    const std::string &get_service_name() const;
+    struct service_context *get_service_context();
+
+protected:
+    void set_call_ep(call_ep *ep);
+
+    virtual void do_init() {}
+    virtual void do_deinit() {}
+
+private:
+
+    struct rpc_session
+    {
+        rpc_session(struct call_ep *call_ep);
+        ~rpc_session();
+
+        struct direct_caller m_direct_caller;
+        struct rpc_caller *m_rpc_caller;
+    };
+
+    std::string m_sn;
+    int m_ref_count;
+    struct service_context m_service_context;
+    struct call_ep *m_call_ep;
+};
+
+#endif /* STANDALONE_SERVICE_CONTEXT_H */
diff --git a/components/service/locator/standalone/standalone_service_registry.cpp b/components/service/locator/standalone/standalone_service_registry.cpp
new file mode 100644
index 0000000..5625bc0
--- /dev/null
+++ b/components/service/locator/standalone/standalone_service_registry.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "standalone_service_registry.h"
+
+standalone_service_registry::standalone_service_registry() :
+    m_service_instances()
+{
+
+}
+
+standalone_service_registry::~standalone_service_registry()
+{
+
+}
+
+standalone_service_registry *standalone_service_registry::instance()
+{
+    static standalone_service_registry singleton_instance;
+    return &singleton_instance;
+}
+
+void standalone_service_registry::regsiter_service_instance(standalone_service_context *service_context)
+{
+    size_t index;
+
+    if (find_context_index(service_context->get_service_name().c_str(), &index)) {
+
+        m_service_instances[index] = service_context;
+    }
+    else {
+
+        m_service_instances.push_back(service_context);
+    }
+}
+
+standalone_service_context *standalone_service_registry::deregsiter_service_instance(const char *sn)
+{
+    size_t index;
+    standalone_service_context *context = NULL;
+
+    if (find_context_index(sn, &index)) {
+
+        context = m_service_instances[index];
+        m_service_instances.erase(m_service_instances.begin() + index);
+    }
+
+    return context;
+}
+
+standalone_service_context *standalone_service_registry::query(const char *sn, int *status)
+{
+    size_t index;
+    standalone_service_context *context = NULL;
+    (void)status;
+
+    if (find_context_index(sn, &index)) {
+
+        context = m_service_instances[index];
+        context->init();
+    }
+
+    return context;
+}
+
+bool standalone_service_registry::find_context_index(const char *sn, size_t *index) const
+{
+    bool found = false;
+
+    for (size_t i = 0; !found && i < m_service_instances.size(); i++) {
+
+        if (m_service_instances[i]->get_service_name().compare(sn) == 0) {
+
+            *index = i;
+            found = true;
+        }
+    }
+
+    return found;
+}
\ No newline at end of file
diff --git a/components/service/locator/standalone/standalone_service_registry.h b/components/service/locator/standalone/standalone_service_registry.h
new file mode 100644
index 0000000..7a76aeb
--- /dev/null
+++ b/components/service/locator/standalone/standalone_service_registry.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STANDALONE_SERVICE_REGISTRY_H
+#define STANDALONE_SERVICE_REGISTRY_H
+
+#include "standalone_service_context.h"
+#include <vector>
+
+/*
+ * The standalone_service_registry supports a set of standalone
+ * service instances that are deployed as part of a standalone exectable
+ * or library.  A standalone deployment of service providers should only
+ * be used for test and development.  Because service provider instances
+ * are running within the same execution context as the client, a
+ * standalone deployment offers no isolation from the client.
+ */
+class standalone_service_registry
+{
+public:
+    standalone_service_registry();
+    virtual ~standalone_service_registry();
+
+    static standalone_service_registry *instance();
+
+    void regsiter_service_instance(standalone_service_context *service_context);
+    standalone_service_context *deregsiter_service_instance(const char *sn);
+
+    standalone_service_context *query(const char *sn, int *status);
+
+private:
+    bool find_context_index(const char *sn, size_t *index) const;
+
+    std::vector<standalone_service_context*> m_service_instances;
+};
+
+#endif /* STANDALONE_SERVICE_REGISTRY_H */
\ No newline at end of file