Integrate discovery into crypto service provider

Integrates the discovery provider into the crypto provider to
support common discovery operations.  Will initially be used
to discover the max_payload value to allow a client to
use multi-step crypto operations where prior knowledge of
the max_payload size is needed.  This commit also includes
service level tests for discovery.

Signed-off-by: Julian Hall <julian.hall@arm.com>
Change-Id: I0213aeb5a5423b3bec962a6e27d8e83bf8e7a763
diff --git a/components/service/common/client/service_client.c b/components/service/common/client/service_client.c
index 3849843..d5e8735 100644
--- a/components/service/common/client/service_client.c
+++ b/components/service/common/client/service_client.c
@@ -15,8 +15,8 @@
 	context->caller = caller;
 	context->rpc_status = TS_RPC_CALL_ACCEPTED;
 
-	context->service_access_info.supported_encodings = 0;
-	context->service_access_info.max_req_size = 0;
+	context->service_info.supported_encodings = 0;
+	context->service_info.max_payload = 0;
 
 	return PSA_SUCCESS;
 }
@@ -27,9 +27,9 @@
 	context->caller = NULL;
 }
 
-void service_client_set_service_access_info(
+void service_client_set_service_info(
 	struct service_client *context,
-	const struct service_access_info *service_access_info)
+	const struct service_info *service_info)
 {
-	context->service_access_info = *service_access_info;
+	context->service_info = *service_info;
 }
diff --git a/components/service/common/client/service_client.h b/components/service/common/client/service_client.h
index b20f734..df5b31b 100644
--- a/components/service/common/client/service_client.h
+++ b/components/service/common/client/service_client.h
@@ -10,7 +10,7 @@
 #include <stddef.h>
 #include <psa/error.h>
 #include <rpc_caller.h>
-#include <service/common/client/service_access_info.h>
+#include <service/common/client/service_info.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -22,14 +22,14 @@
  * Holds common service objects needed for client access to a service instance.
  * Includes common information about the service that will have been discovered
  * in some way.  The TS discovery protocol provides a way to do this.  If
- * service info is not available, the service_access_info structure stays in its
+ * service info is not available, the service_info structure stays in its
  * initialied state.
  */
 struct service_client
 {
 	struct rpc_caller *caller;
 	int rpc_status;
-	struct service_access_info service_access_info;
+	struct service_info service_info;
 };
 
 /**
@@ -61,11 +61,11 @@
  * Service info will have been discovered in some way.
  *
  * @param[in]  context 	service_client instance
- * @param[in]  service_access_info service_access_info object
+ * @param[in]  service_info service_info object
  */
-void service_client_set_service_access_info(
+void service_client_set_service_info(
 	struct service_client *context,
-	const struct service_access_info *service_access_info);
+	const struct service_info *service_info);
 
 #ifdef __cplusplus
 }
diff --git a/components/service/common/client/service_access_info.h b/components/service/common/client/service_info.h
similarity index 66%
rename from components/service/common/client/service_access_info.h
rename to components/service/common/client/service_info.h
index 83b88ce..4a39b6b 100644
--- a/components/service/common/client/service_access_info.h
+++ b/components/service/common/client/service_info.h
@@ -4,8 +4,8 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#ifndef SERVICE_ACCESS_INFO_H
-#define SERVICE_ACCESS_INFO_H
+#ifndef SERVICE_INFO_H
+#define SERVICE_INFO_H
 
 #include <stddef.h>
 #include <stdint.h>
@@ -15,19 +15,19 @@
 #endif
 
 /**
- * @brief      Information about accessing a service
+ * @brief      Information about a service
  *
  * Provides information to a client about accessing a service provided
  * by a remote service provider instance.
  */
-struct service_access_info
+struct service_info
 {
 	uint32_t supported_encodings;
-	size_t max_req_size;
+	size_t max_payload;
 };
 
 #ifdef __cplusplus
 }
 #endif
 
-#endif /* SERVICE_ACCESS_INFO_H */
+#endif /* SERVICE_INFO_H */
diff --git a/components/service/crypto/client/psa/psa_crypto_client.c b/components/service/crypto/client/psa/psa_crypto_client.c
index bda68e9..41e21a4 100644
--- a/components/service/crypto/client/psa/psa_crypto_client.c
+++ b/components/service/crypto/client/psa/psa_crypto_client.c
@@ -5,6 +5,7 @@
  */
 
 #include <stddef.h>
+#include <service/discovery/client/discovery_client.h>
 #include "psa_crypto_client.h"
 
 /* The singleton psa_crypto_client state */
@@ -31,7 +32,14 @@
 
 psa_status_t psa_crypto_client_init(struct rpc_caller *caller)
 {
-	return service_client_init(&psa_crypto_client_instance.base, caller);
+	psa_status_t status = service_client_init(&psa_crypto_client_instance.base, caller);
+
+	if (status == PSA_SUCCESS) {
+
+		status = discovery_client_get_service_info(&psa_crypto_client_instance.base);
+	}
+
+	return status;
 }
 
 void psa_crypto_client_deinit(void)
diff --git a/components/service/crypto/factory/full/crypto_provider_factory.c b/components/service/crypto/factory/full/crypto_provider_factory.c
index cc22b28..2d926eb 100644
--- a/components/service/crypto/factory/full/crypto_provider_factory.c
+++ b/components/service/crypto/factory/full/crypto_provider_factory.c
@@ -17,6 +17,8 @@
 #include <service/crypto/provider/extension/key_derivation/serializer/packed-c/packedc_key_derivation_provider_serializer.h>
 #include <service/crypto/provider/extension/mac/mac_provider.h>
 #include <service/crypto/provider/extension/mac/serializer/packed-c/packedc_mac_provider_serializer.h>
+#include <service/discovery/provider/discovery_provider.h>
+#include <service/discovery/provider/serializer/packed-c/packedc_discovery_provider_serializer.h>
 
 /**
  * A crypto provider factory that constucts a crypto provider
@@ -38,15 +40,20 @@
 struct crypto_provider *crypto_provider_factory_create(void)
 {
 	/**
-	 * Initialize the base crypto provider
+	 * Initialize the core crypto provider
 	 */
 	crypto_provider_init(&instance.crypto_provider);
 
+	/* Register serializers for the core crypto provider */
 	crypto_provider_register_serializer(&instance.crypto_provider,
 		TS_RPC_ENCODING_PROTOBUF, pb_crypto_provider_serializer_instance());
 	crypto_provider_register_serializer(&instance.crypto_provider,
 		TS_RPC_ENCODING_PACKED_C, packedc_crypto_provider_serializer_instance());
 
+	/* Register serializer for the associated discovery provider */
+	discovery_provider_register_serializer(&instance.crypto_provider.discovery_provider,
+		TS_RPC_ENCODING_PACKED_C, packedc_discovery_provider_serializer_instance());
+
 	/**
 	 * Extend with hash operations
 	 */
diff --git a/components/service/crypto/provider/crypto_provider.c b/components/service/crypto/provider/crypto_provider.c
index 89fc86d..ea9cce6 100644
--- a/components/service/crypto/provider/crypto_provider.c
+++ b/components/service/crypto/provider/crypto_provider.c
@@ -44,25 +44,33 @@
 
 struct rpc_interface *crypto_provider_init(struct crypto_provider *context)
 {
+	/* Initialise the crypto provider */
 	for (size_t encoding = 0; encoding < TS_RPC_ENCODING_LIMIT; ++encoding)
 		context->serializers[encoding] = NULL;
 
 	service_provider_init(&context->base_provider, context,
 					handler_table, sizeof(handler_table)/sizeof(struct service_handler));
 
+	/* Initialise the associated discovery provider */
+	discovery_provider_init(&context->discovery_provider);
+	service_provider_extend(&context->base_provider, &context->discovery_provider.base_provider);
+
 	return service_provider_get_rpc_interface(&context->base_provider);
 }
 
 void crypto_provider_deinit(struct crypto_provider *context)
 {
-
+	discovery_provider_deinit(&context->discovery_provider);
 }
 
 void crypto_provider_register_serializer(struct crypto_provider *context,
 				unsigned int encoding, const struct crypto_provider_serializer *serializer)
 {
-	if (encoding < TS_RPC_ENCODING_LIMIT)
+	if (encoding < TS_RPC_ENCODING_LIMIT) {
+
 		context->serializers[encoding] = serializer;
+		discovery_provider_register_supported_encoding(&context->discovery_provider, encoding);
+	}
 }
 
 void crypto_provider_extend(struct crypto_provider *context,
diff --git a/components/service/crypto/provider/crypto_provider.h b/components/service/crypto/provider/crypto_provider.h
index 788e501..ce33c23 100644
--- a/components/service/crypto/provider/crypto_provider.h
+++ b/components/service/crypto/provider/crypto_provider.h
@@ -10,6 +10,7 @@
 #include <rpc/common/endpoint/rpc_interface.h>
 #include <service/common/provider/service_provider.h>
 #include <service/crypto/provider/serializer/crypto_provider_serializer.h>
+#include <service/discovery/provider/discovery_provider.h>
 #include <protocols/rpc/common/packed-c/encoding.h>
 
 #ifdef __cplusplus
@@ -18,8 +19,9 @@
 
 struct crypto_provider
 {
-    struct service_provider base_provider;
-    const struct crypto_provider_serializer *serializers[TS_RPC_ENCODING_LIMIT];
+	struct service_provider base_provider;
+	const struct crypto_provider_serializer *serializers[TS_RPC_ENCODING_LIMIT];
+	struct discovery_provider discovery_provider;
 };
 
 /*
@@ -42,13 +44,14 @@
  * for compatibility with different types of client.
  */
 void crypto_provider_register_serializer(struct crypto_provider *context,
-                    unsigned int encoding, const struct crypto_provider_serializer *serializer);
+	unsigned int encoding,
+	const struct crypto_provider_serializer *serializer);
 
 /*
  * Extend the core set of operations provided by the crypto provider.
  */
 void crypto_provider_extend(struct crypto_provider *context,
-                    struct service_provider *sub_provider);
+	struct service_provider *sub_provider);
 
 #ifdef __cplusplus
 } /* extern "C" */
diff --git a/components/service/discovery/client/component.cmake b/components/service/discovery/client/component.cmake
new file mode 100644
index 0000000..ce48d00
--- /dev/null
+++ b/components/service/discovery/client/component.cmake
@@ -0,0 +1,13 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2021, 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}/discovery_client.c"
+	)
diff --git a/components/service/discovery/client/discovery_client.c b/components/service/discovery/client/discovery_client.c
new file mode 100644
index 0000000..2ab9731
--- /dev/null
+++ b/components/service/discovery/client/discovery_client.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+#include <common/tlv/tlv.h>
+#include <protocols/service/discovery/packed-c/get_service_info.h>
+#include <protocols/service/discovery/packed-c/opcodes.h>
+#include <protocols/rpc/common/packed-c/status.h>
+#include "discovery_client.h"
+
+psa_status_t discovery_client_get_service_info(
+	struct service_client *service_client)
+{
+	psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
+	rpc_call_handle call_handle;
+	uint8_t *req_buf;
+
+	call_handle = rpc_caller_begin(service_client->caller, &req_buf, 0);
+
+	if (call_handle) {
+
+		uint8_t *resp_buf;
+		size_t resp_len;
+		int opstatus;
+
+		service_client->rpc_status = rpc_caller_invoke(service_client->caller, call_handle,
+			TS_DISCOVERY_OPCODE_GET_SERVICE_INFO, &opstatus, &resp_buf, &resp_len);
+
+		if (service_client->rpc_status == TS_RPC_CALL_ACCEPTED) {
+
+			psa_status = opstatus;
+
+			if (psa_status == PSA_SUCCESS) {
+
+				if (resp_len >= sizeof(struct ts_discovery_get_service_info_out)) {
+
+					struct ts_discovery_get_service_info_out resp_msg;
+					memcpy(&resp_msg, resp_buf, sizeof(struct ts_discovery_get_service_info_out));
+
+					service_client->service_info.supported_encodings =
+						resp_msg.supported_encodings;
+
+					service_client->service_info.max_payload =
+						resp_msg.max_payload;
+				}
+				else {
+					/* Failed to decode response message */
+					psa_status = PSA_ERROR_GENERIC_ERROR;
+				}
+			}
+		}
+
+		rpc_caller_end(service_client->caller, call_handle);
+	}
+
+	return psa_status;
+}
diff --git a/components/service/discovery/client/discovery_client.h b/components/service/discovery/client/discovery_client.h
new file mode 100644
index 0000000..7be4338
--- /dev/null
+++ b/components/service/discovery/client/discovery_client.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef DISCOVERY_CLIENT_H
+#define DISCOVERY_CLIENT_H
+
+#include <psa/error.h>
+#include <service/common/client/service_client.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Get service info
+ *
+ * Discover service information from the service provider
+ * instance associated with the provided service_client
+ * object. If information is discovered, the service_client
+ * object is updated with the discovered information.
+ *
+ * @param[in]  service_client 	An initialized service client
+ *
+ * @return     Success if information discovered
+ */
+psa_status_t discovery_client_get_service_info(
+	struct service_client *service_client);
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* DISCOVERY_CLIENT_H */
diff --git a/components/service/discovery/provider/discovery_info.h b/components/service/discovery/provider/discovery_info.h
index 33ef5c9..2d46a5a 100644
--- a/components/service/discovery/provider/discovery_info.h
+++ b/components/service/discovery/provider/discovery_info.h
@@ -7,6 +7,7 @@
 #ifndef DISCOVERY_INFO_H
 #define DISCOVERY_INFO_H
 
+#include <stddef.h>
 #include <stdint.h>
 
 #ifdef __cplusplus
@@ -18,18 +19,34 @@
  */
 struct discovery_deployment_info
 {
+	/**
+	 * The RPC interface id that should be used for directing call
+	 * requests to this service provider instance.
+	 */
 	uint16_t interface_id;
-	uint16_t instance;
-	uint32_t max_req_size;
-};
 
-/**
- * Information about service identity
- */
-struct discovery_identity_info
-{
-	const char *name_authority;
-	const char *service_name;
+	/**
+	 * The instance number assigned to this service provider instance.
+	 * This can be used by a client for identifying a particular instance
+	 * of a service provider for cases where multple instances of the same
+	 * type of service provider are deployed.  The instance may be reflected
+	 * to clients using a standard convention such as a device numder
+	 * e.g. /dev/ps0 on Linux.
+	 */
+	uint16_t instance;
+
+	/**
+	 * When the discovery provider and associated service provider are
+	 * co-located (e.g. running in the same SP or TA), the max_payload
+	 * value reported by the discovery provider is determined from the
+	 * response buffer size associated with an incoming call_req object.
+	 * However in cases where call requests are forwarded, say to a
+	 * secure enclave, a different max_payload value may apply.  This
+	 * value allows for a deployment specific override that will
+	 * be reported instead.  Should be set to zero if no override
+	 * applies.
+	 */
+	size_t max_payload_override;
 };
 
 /**
@@ -38,7 +55,6 @@
 struct discovery_info
 {
 	struct discovery_deployment_info deployment;
-	struct discovery_identity_info identity;
 
 	uint32_t supported_encodings;
 };
diff --git a/components/service/discovery/provider/discovery_provider.c b/components/service/discovery/provider/discovery_provider.c
index d32e8f5..2297d52 100644
--- a/components/service/discovery/provider/discovery_provider.c
+++ b/components/service/discovery/provider/discovery_provider.c
@@ -11,9 +11,14 @@
 #include <psa/error.h>
 
 /* Service request handlers */
-static rpc_status_t get_service_info_handler(void *context, struct call_req* req);
-static rpc_status_t get_provider_info_handler(void *context, struct call_req* req);
-static rpc_status_t get_service_caps_handler(void *context, struct call_req* req);
+static rpc_status_t get_service_info_handler(void *context, struct call_req *req);
+static rpc_status_t get_provider_info_handler(void *context, struct call_req *req);
+static rpc_status_t get_service_caps_handler(void *context, struct call_req *req);
+
+/* Other private functions */
+static size_t determine_max_payload(
+	const struct discovery_deployment_info *deployment_info,
+	const struct call_req *req);
 
 /* Handler mapping table for service */
 static const struct service_handler handler_table[] = {
@@ -23,23 +28,24 @@
 };
 
 
-struct rpc_interface *discovery_provider_init(
-	struct discovery_provider *context,
-	const struct discovery_deployment_info *deployment_info,
-	const struct discovery_identity_info *identity_info)
+void discovery_provider_init(struct discovery_provider *context)
 {
+	/* Initialise the base provider */
 	for (size_t encoding = 0; encoding < TS_RPC_ENCODING_LIMIT; ++encoding)
 		context->serializers[encoding] = NULL;
 
 	service_provider_init(&context->base_provider, context,
 					handler_table, sizeof(handler_table)/sizeof(struct service_handler));
 
-	context->info.deployment = *deployment_info;
-	context->info.identity = *identity_info;
+	/* Set default deployment settings.  Deployment specific settings may be
+	 * applied using discovery_provider_set_deployment_info().
+	 */
+	context->info.deployment.interface_id = 0;
+	context->info.deployment.instance = 0;
+	context->info.deployment.max_payload_override = 0;
 
+	/* Bitmap is set when serializers are registered */
 	context->info.supported_encodings = 0;
-
-	return service_provider_get_rpc_interface(&context->base_provider);
 }
 
 void discovery_provider_deinit(struct discovery_provider *context)
@@ -61,6 +67,13 @@
 	context->info.supported_encodings |= (1U << encoding);
 }
 
+void discovery_provider_set_deployment_info(
+	struct discovery_provider *context,
+	const struct discovery_deployment_info *deployment_info)
+{
+	context->info.deployment = *deployment_info;
+}
+
 static const struct discovery_provider_serializer* get_discovery_serializer(void *context,
 														const struct call_req *req)
 {
@@ -81,9 +94,13 @@
 
 	if (serializer) {
 
+		size_t max_payload = determine_max_payload(&this_instance->info.deployment, req);
 		struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
 
-		rpc_status = serializer->serialize_get_service_info_resp(resp_buf, &this_instance->info);
+		rpc_status = serializer->serialize_get_service_info_resp(resp_buf,
+			max_payload,
+			&this_instance->info);
+
 		call_req_set_opstatus(req, PSA_SUCCESS);
 	}
 
@@ -93,7 +110,7 @@
 static rpc_status_t get_provider_info_handler(void *context, struct call_req* req)
 {
 	(void)context;
-	(void)req;
+
 	call_req_set_opstatus(req, PSA_ERROR_NOT_SUPPORTED);
 	return TS_RPC_CALL_ACCEPTED;
 }
@@ -101,7 +118,36 @@
 static rpc_status_t get_service_caps_handler(void *context, struct call_req* req)
 {
 	(void)context;
-	(void)req;
+
 	call_req_set_opstatus(req, PSA_ERROR_NOT_SUPPORTED);
 	return TS_RPC_CALL_ACCEPTED;
 }
+
+static size_t determine_max_payload(
+	const struct discovery_deployment_info *deployment_info,
+	const struct call_req *req)
+{
+	size_t max_payload;
+
+	if (!deployment_info->max_payload_override) {
+
+		/* No deployment specific override has been provided so
+		 * determine the maximum payload value from the call_req
+		 * buffer sizes.  This will have been set by the
+		 * underlying RPC layer.
+		 */
+		const struct call_param_buf *req_buf = &req->req_buf;
+		const struct call_param_buf *resp_buf = &req->resp_buf;
+
+		max_payload = (req_buf->size < resp_buf->size) ?
+			req_buf->size :
+			resp_buf->size;
+	}
+	else {
+
+		/* A deployment specific override has been provided */
+		max_payload = deployment_info->max_payload_override;
+	}
+
+	return max_payload;
+}
diff --git a/components/service/discovery/provider/discovery_provider.h b/components/service/discovery/provider/discovery_provider.h
index f2b3ccf..298cef0 100644
--- a/components/service/discovery/provider/discovery_provider.h
+++ b/components/service/discovery/provider/discovery_provider.h
@@ -8,7 +8,6 @@
 #define DISCOVERY_PROVIDER_H
 
 #include <stdint.h>
-#include <rpc/common/endpoint/rpc_interface.h>
 #include <service/common/provider/service_provider.h>
 #include <service/discovery/provider/serializer/discovery_provider_serializer.h>
 #include <service/discovery/provider/discovery_info.h>
@@ -32,10 +31,8 @@
 /**
  * Initializes an instance of the discovery service provider.
  */
-struct rpc_interface *discovery_provider_init(
-	struct discovery_provider *context,
-	const struct discovery_deployment_info *deployment_info,
-	const struct discovery_identity_info *identity_info);
+void discovery_provider_init(
+	struct discovery_provider *context);
 
 /**
  * When operation of the provider is no longer required, this function
@@ -60,6 +57,13 @@
 	struct discovery_provider *context,
 	unsigned int encoding);
 
+/**
+ * Sets deployment specific information that is adverstised by the
+ * discovery provider.
+ */
+void discovery_provider_set_deployment_info(
+	struct discovery_provider *context,
+	const struct discovery_deployment_info *deployment_info);
 
 #ifdef __cplusplus
 } /* extern "C" */
diff --git a/components/service/discovery/provider/serializer/discovery_provider_serializer.h b/components/service/discovery/provider/serializer/discovery_provider_serializer.h
index 643bab1..89d166f 100644
--- a/components/service/discovery/provider/serializer/discovery_provider_serializer.h
+++ b/components/service/discovery/provider/serializer/discovery_provider_serializer.h
@@ -7,6 +7,7 @@
 #ifndef DISCOVERY_PROVIDER_SERIALIZER_H
 #define DISCOVERY_PROVIDER_SERIALIZER_H
 
+#include <stddef.h>
 #include <service/discovery/provider/discovery_info.h>
 #include <rpc/common/endpoint/rpc_interface.h>
 
@@ -20,6 +21,7 @@
 
 	/* Operation: get_service_info */
 	rpc_status_t (*serialize_get_service_info_resp)(struct call_param_buf *resp_buf,
+		size_t max_payload,
 		const struct discovery_info *info);
 };
 
diff --git a/components/service/discovery/provider/serializer/packed-c/packedc_discovery_provider_serializer.c b/components/service/discovery/provider/serializer/packed-c/packedc_discovery_provider_serializer.c
index 69362f9..5550ce7 100644
--- a/components/service/discovery/provider/serializer/packed-c/packedc_discovery_provider_serializer.c
+++ b/components/service/discovery/provider/serializer/packed-c/packedc_discovery_provider_serializer.c
@@ -4,14 +4,13 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 #include <string.h>
-#include <stdlib.h>
-#include <common/tlv/tlv.h>
 #include <protocols/rpc/common/packed-c/status.h>
 #include <protocols/service/discovery/packed-c/get_service_info.h>
 #include "packedc_discovery_provider_serializer.h"
 
 /* Operation: get_service_info */
 static rpc_status_t serialize_get_service_info_resp(struct call_param_buf *resp_buf,
+	size_t max_payload,
 	const struct discovery_info *info)
 {
 	rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL;
@@ -20,44 +19,16 @@
 
 	resp_msg.instance = info->deployment.instance;
 	resp_msg.interface_id = info->deployment.interface_id;
-	resp_msg.max_req_size = info->deployment.max_req_size;
+
+	resp_msg.max_payload = max_payload;
 	resp_msg.supported_encodings = info->supported_encodings;
 
 	if (fixed_len <= resp_buf->size) {
 
-		struct tlv_record out_record;
-		struct tlv_iterator resp_iter;
-		int encoded_tlv_count = 0;
-
 		memcpy(resp_buf->data, &resp_msg, fixed_len);
 		resp_buf->data_len = fixed_len;
 
-		tlv_iterator_begin(&resp_iter,
-			(uint8_t*)resp_buf->data + fixed_len,
-			resp_buf->size - fixed_len);
-
-		out_record.tag = TS_DISOVERY_GET_SERVICE_INFO_OUT_TAG_NAME_AUTHORITY;
-		out_record.length = strlen(info->identity.name_authority) + 1;
-		out_record.value = info->identity.name_authority;
-
-		if (tlv_encode(&resp_iter, &out_record)) {
-
-			resp_buf->data_len += tlv_required_space(out_record.length);
-			++encoded_tlv_count;
-		}
-
-		out_record.tag = TS_DISOVERY_GET_SERVICE_INFO_OUT_TAG_SERVICE_NAME;
-		out_record.length = strlen(info->identity.service_name) + 1;
-		out_record.value = info->identity.service_name;
-
-		if (tlv_encode(&resp_iter, &out_record)) {
-
-			resp_buf->data_len += tlv_required_space(out_record.length);
-			++encoded_tlv_count;
-		}
-
-		/* Check that expected TLV records have been encoded */
-		if (encoded_tlv_count == 2) rpc_status = TS_RPC_CALL_ACCEPTED;
+		rpc_status = TS_RPC_CALL_ACCEPTED;
 	}
 
 	return rpc_status;
diff --git a/components/service/discovery/test/service/component.cmake b/components/service/discovery/test/service/component.cmake
new file mode 100644
index 0000000..7f8a18a
--- /dev/null
+++ b/components/service/discovery/test/service/component.cmake
@@ -0,0 +1,13 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2021, 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}/discovery_service_tests.cpp"
+	)
diff --git a/components/service/discovery/test/service/discovery_service_tests.cpp b/components/service/discovery/test/service/discovery_service_tests.cpp
new file mode 100644
index 0000000..654986e
--- /dev/null
+++ b/components/service/discovery/test/service/discovery_service_tests.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <service/discovery/client/discovery_client.h>
+#include <protocols/rpc/common/packed-c/encoding.h>
+#include <service_locator.h>
+#include <CppUTest/TestHarness.h>
+
+/*
+ * Service-level tests for the discovery service.  The discovery service
+ * provides common operations that may be called at all service endpoints.
+ * These tests use the crypto service as the target.
+ */
+TEST_GROUP(DiscoveryServiceTests)
+{
+	void setup()
+	{
+		int status;
+
+		m_rpc_session_handle = NULL;
+		m_service_context = NULL;
+
+		service_locator_init();
+
+		m_service_context =
+			service_locator_query("sn:trustedfirmware.org:crypto:0", &status);
+		CHECK_TRUE(m_service_context);
+
+		m_rpc_session_handle =
+			service_context_open(m_service_context, TS_RPC_ENCODING_PACKED_C, &m_caller);
+		CHECK_TRUE(m_rpc_session_handle);
+	}
+
+	void teardown()
+	{
+		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;
+	}
+
+	struct rpc_caller *m_caller;
+	rpc_session_handle m_rpc_session_handle;
+	struct service_context *m_service_context;
+};
+
+TEST(DiscoveryServiceTests, checkServiceInfo)
+{
+	struct service_client service_client;
+	psa_status_t status;
+
+	status = service_client_init(&service_client, m_caller);
+	LONGS_EQUAL(PSA_SUCCESS, status);
+
+	status = discovery_client_get_service_info(&service_client);
+	LONGS_EQUAL(PSA_SUCCESS, status);
+
+	/* Check discovered service info looks reasonable */
+	CHECK_TRUE(service_client.service_info.max_payload);
+	CHECK_TRUE(service_client.service_info.supported_encodings);
+}
diff --git a/deployments/component-test/component-test.cmake b/deployments/component-test/component-test.cmake
index 4065ab3..f6790b5 100644
--- a/deployments/component-test/component-test.cmake
+++ b/deployments/component-test/component-test.cmake
@@ -44,8 +44,10 @@
 		"components/service/locator/standalone/services/protected-storage"
 		"components/service/locator/standalone/services/test-runner"
 		"components/service/locator/standalone/services/attestation"
+		"components/service/discovery/client"
 		"components/service/discovery/provider"
 		"components/service/discovery/provider/serializer/packed-c"
+		"components/service/discovery/test/service"
 		"components/service/attestation/include"
 		"components/service/attestation/claims"
 		"components/service/attestation/claims/sources/boot_seed_generator"
diff --git a/deployments/crypto/opteesp/CMakeLists.txt b/deployments/crypto/opteesp/CMakeLists.txt
index 6b8246c..79f238b 100644
--- a/deployments/crypto/opteesp/CMakeLists.txt
+++ b/deployments/crypto/opteesp/CMakeLists.txt
@@ -46,6 +46,8 @@
 		"components/service/common/client"
 		"components/service/common/serializer/protobuf"
 		"components/service/common/provider"
+		"components/service/discovery/provider"
+		"components/service/discovery/provider/serializer/packed-c"
 		"components/service/crypto/provider"
 		"components/service/crypto/provider/serializer/protobuf"
 		"components/service/crypto/provider/serializer/packed-c"
diff --git a/deployments/libts/linux-pc/CMakeLists.txt b/deployments/libts/linux-pc/CMakeLists.txt
index d15dc76..3aa69ae 100644
--- a/deployments/libts/linux-pc/CMakeLists.txt
+++ b/deployments/libts/linux-pc/CMakeLists.txt
@@ -37,6 +37,8 @@
 		"components/service/common/client"
 		"components/service/common/serializer/protobuf"
 		"components/service/common/provider"
+		"components/service/discovery/provider"
+		"components/service/discovery/provider/serializer/packed-c"
 		"components/service/locator/standalone"
 		"components/service/locator/standalone/services/crypto"
 		"components/service/locator/standalone/services/internal-trusted-storage"
diff --git a/deployments/psa-api-test/psa-api-test.cmake b/deployments/psa-api-test/psa-api-test.cmake
index 0a84c65..ecb3a9c 100644
--- a/deployments/psa-api-test/psa-api-test.cmake
+++ b/deployments/psa-api-test/psa-api-test.cmake
@@ -29,6 +29,7 @@
 		"components/common/tlv"
 		"components/service/common/client"
 		"components/service/common/include"
+		"components/service/discovery/client"
 		"components/rpc/common/caller"
 		"components/rpc/common/logging"
 )
diff --git a/deployments/se-proxy/opteesp/CMakeLists.txt b/deployments/se-proxy/opteesp/CMakeLists.txt
index cb34e26..b5bdc64 100644
--- a/deployments/se-proxy/opteesp/CMakeLists.txt
+++ b/deployments/se-proxy/opteesp/CMakeLists.txt
@@ -57,6 +57,8 @@
 		"components/service/common/include"
 		"components/service/common/serializer/protobuf"
 		"components/service/common/provider"
+		"components/service/discovery/provider"
+		"components/service/discovery/provider/serializer/packed-c"
 		"components/service/crypto/provider"
 		"components/service/crypto/provider/serializer/protobuf"
 		"components/service/crypto/provider/serializer/packed-c"
diff --git a/deployments/ts-service-test/ts-service-test.cmake b/deployments/ts-service-test/ts-service-test.cmake
index 9b72089..dfe0bb1 100644
--- a/deployments/ts-service-test/ts-service-test.cmake
+++ b/deployments/ts-service-test/ts-service-test.cmake
@@ -30,6 +30,8 @@
 		"components/common/tlv"
 		"components/service/common/client"
 		"components/service/common/include"
+		"components/service/discovery/client"
+		"components/service/discovery/test/service"
 		"components/service/crypto/include"
 		"components/service/crypto/test/service"
 		"components/service/crypto/test/service/protobuf"
diff --git a/protocols/service/discovery/packed-c/get_service_info.h b/protocols/service/discovery/packed-c/get_service_info.h
index bd0e8fd..1f41701 100644
--- a/protocols/service/discovery/packed-c/get_service_info.h
+++ b/protocols/service/discovery/packed-c/get_service_info.h
@@ -37,11 +37,13 @@
 	 */
 	uint32_t supported_encodings;
 
-	/* The maximum supported size for an RPC call request.  This limit
-	 * will be imposed by the underlying RPC layer used by a client
-	 * to call service operations.
+	/* The maximum supported payloadsize for an RPC call request or
+	 * response.  This limit will be imposed by the underlying RPC
+	 * layer used by a client to call service operations. If the
+	 * maximum payload size is different between call requests and
+	 * responses, the smaller value should be used.
 	 */
-	uint32_t max_req_size;
+	uint32_t max_payload;
 };
 
 /* Variable length output parameter tags */