Update the RPC layer

This commit merges the 'tforg/topics/ts-rpc' into integration. The
change overhauls the RPC layer implement the following changes:
  - allow RPC compatibility check be adding versioning to the RPC layer
  - allow multiple memory shares between FF-A endpoints. (This was a
     concerning limitation for NWd endpoints where multiple clients
     may operate).
  - add service discovery support. After this change all SPs use the
    same FF-A UUID. This means the FF-A UUID identifies the protocol and
    not the service as before. As a result, to locate a service further
    discovery is needed on top of FF-A discovery. This is implemented
    in the RPC layer for performance reasons.
  - update discovery implementation and add the new discovery step
    needed after service locator locates the SP.
  - change protocol encoding types to be represented as dedicated
    interfaces of an SP. This removes encoding type identifiers and
    replaces these with service UUIDs.
  - add RPC ABI documentation

Change-Id: I7fbb28b17d44b04578595c8725674624297f01a0
Signed-off-by: Gyorgy Szing <Gyorgy.Szing@arm.com>
diff --git a/components/service/fwu/test/ref_scenarios/update_fmp_tests.cpp b/components/service/fwu/test/ref_scenarios/update_fmp_tests.cpp
index aaa8fd3..310899a 100644
--- a/components/service/fwu/test/ref_scenarios/update_fmp_tests.cpp
+++ b/components/service/fwu/test/ref_scenarios/update_fmp_tests.cpp
@@ -44,13 +44,20 @@
 	explicit fmp(fwu_client *m_fwu_client)
 		: client(m_fwu_client)
 		, is_staging(false)
+		, payload_max_size(0)
 		, img_info(NULL)
 		, num_images(0)
-		, payload_max_size(0)
+
 	{
 		parse_img_directory();
 	}
 
+	~fmp()
+	{
+		if (img_info)
+			delete[] img_info;
+	}
+
 	int get_image_info(uint64_t *ImageInfoSize, EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageInfo,
 			   uint32_t *DescriptorVersion, uint8_t *DescriptorCount,
 			   uint64_t *DescriptorSize, uint32_t *PackageVersion,
diff --git a/components/service/secure_storage/backend/mock_store/mock_store.c b/components/service/secure_storage/backend/mock_store/mock_store.c
index 5e43d5f..23c336e 100644
--- a/components/service/secure_storage/backend/mock_store/mock_store.c
+++ b/components/service/secure_storage/backend/mock_store/mock_store.c
@@ -6,6 +6,7 @@
 
 #include "mock_store.h"
 #include <protocols/service/psa/packed-c/status.h>
+#include "util.h"
 #include <stdlib.h>
 #include <string.h>
 
@@ -29,17 +30,24 @@
     /* Check length limit */
     if (data_length > MOCK_STORE_ITEM_SIZE_LIMIT) return psa_status;
 
+    if (!uid)
+        return PSA_ERROR_INVALID_ARGUMENT;
+
     /* Replace existing or add new item */
     struct mock_store_slot *slot = find_slot(this_context, uid);
-    if (slot) free_slot(slot);
-    else slot = find_empty_slot(this_context);
+    if (slot) {
+        if (slot->flags & PSA_STORAGE_FLAG_WRITE_ONCE)
+            return PSA_ERROR_NOT_PERMITTED;
+
+        free_slot(slot);
+    } else {
+        slot = find_empty_slot(this_context);
+    }
 
     if (slot) {
-
         slot->item = malloc(data_length);
 
         if (slot->item) {
-
             slot->uid = uid;
             slot->flags = create_flags;
             slot->len = slot->capacity = data_length;
@@ -60,22 +68,26 @@
                             void *p_data,
                             size_t *p_data_length)
 {
-    (void)client_id;
-    (void)data_offset;
-
-    psa_status_t psa_status = PSA_ERROR_DOES_NOT_EXIST;
     struct mock_store *this_context = (struct mock_store*)context;
 
+    (void)client_id;
+
+    if (!uid)
+        return PSA_ERROR_INVALID_ARGUMENT;
+
     /* Find the item */
     struct mock_store_slot *slot = find_slot(this_context, uid);
 
-    if (slot && (slot->len <= data_size)) {
-        memcpy(p_data, slot->item, slot->len);
-        *p_data_length = slot->len;
-        psa_status = PSA_SUCCESS;
-    }
+    if (!slot)
+        return PSA_ERROR_DOES_NOT_EXIST;
 
-    return psa_status;
+    if (slot->len < data_offset)
+        return PSA_ERROR_INVALID_ARGUMENT;
+
+    *p_data_length = MIN(slot->len - data_offset, data_size);
+    memcpy(p_data, slot->item + data_offset, *p_data_length);
+
+    return PSA_SUCCESS;
 }
 
 static psa_status_t mock_store_get_info(void *context,
@@ -88,6 +100,9 @@
     psa_status_t psa_status = PSA_ERROR_DOES_NOT_EXIST;
     struct mock_store *this_context = (struct mock_store*)context;
 
+    if (!uid)
+        return PSA_ERROR_INVALID_ARGUMENT;
+
     /* Find item to get info about */
     struct mock_store_slot *slot = find_slot(this_context, uid);
 
@@ -115,12 +130,19 @@
     psa_status_t psa_status = PSA_ERROR_DOES_NOT_EXIST;
     struct mock_store *this_context = (struct mock_store*)context;
 
+    if (!uid)
+        return PSA_ERROR_INVALID_ARGUMENT;
+
     /* Find and remove the item */
     struct mock_store_slot *slot = find_slot(this_context, uid);
 
     if (slot) {
-        free_slot(slot);
-        psa_status = PSA_SUCCESS;
+        if (!(slot->flags & PSA_STORAGE_FLAG_WRITE_ONCE)) {
+            free_slot(slot);
+            psa_status = PSA_SUCCESS;
+        } else {
+            psa_status = PSA_ERROR_NOT_PERMITTED;
+        }
     }
 
     return psa_status;
diff --git a/components/service/spm_test/sp.c b/components/service/spm_test/sp.c
index 5bbc545..663e29b 100644
--- a/components/service/spm_test/sp.c
+++ b/components/service/spm_test/sp.c
@@ -54,7 +54,8 @@
 	EP_SP_MEM_SHARING_MULTI,
 	EP_SP_MEM_SHARING_EXC,
 	EP_SP_MEM_INCORRECT_ACCESS,
-	EP_SP_NOP
+	EP_SP_NOP,
+	EP_TEST_SP_COMMUNICATION_RESPONSE,
 };
 
 const char* sp_test_str[]= {
@@ -281,34 +282,144 @@
 static void test_communication(struct ffa_direct_msg *msg)
 {
 	struct ffa_direct_msg sp_msg = {0};
+	uint16_t caller = msg->source_id;
+	uint16_t src = msg->destination_id;
 	uint16_t dst = (uint16_t)msg->args.args64[1];
 	ffa_result res = FFA_OK;
+	struct ffa_params raw_params = { 0 };
 
 	sp_msg.args.args64[1] =  0x55;
 	sp_msg.args.args64[2] =  0xAA;
 	sp_msg.args.args64[3] =  0xBB;
 	sp_msg.args.args64[4] =  0xCC;
 
-	res = ffa_msg_send_direct_req_64(msg->destination_id, dst,
+	res = ffa_msg_send_direct_req_64(src, dst,
 				      EP_TEST_SP_INCREASE,0x55, 0xAA, 0xBB,
 				      0xCC, &sp_msg);
-
 	if (res != FFA_OK) {
 		EMSG("error % in %s:%d"PRId32, res, __FILE__, __LINE__);
-		return_error((uint32_t)ERR_SP_SHARE, msg);
-		return;
+		goto err;
 	}
 
-	if (sp_msg.args.args64[1] == 0x56 && sp_msg.args.args64[2] == 0xAB &&
-	    sp_msg.args.args64[3] == 0xBC &&sp_msg.args.args64[4] == 0xCD) {
-		return_ok(msg);
-	} else {
+	if (sp_msg.args.args64[1] != 0x56 || sp_msg.args.args64[2] != 0xAB ||
+	    sp_msg.args.args64[3] != 0xBC || sp_msg.args.args64[4] != 0xCD) {
 		DMSG("Failed SP communication %lx %lx %lx %lx",
 		     sp_msg.args.args64[1], sp_msg.args.args64[2],
 		     sp_msg.args.args64[3], sp_msg.args.args64[4]);
-
-		return_error(ERR_SP_COMMUNICATION, msg);
+		goto err;
 	}
+
+	/* Non-null flags (W2) register */
+	ffa_svc(FFA_MSG_SEND_DIRECT_REQ_64, (uint32_t)(src << 16 | 0x1000), 1, 0, 0, 0, 0, 0,
+		&raw_params);
+	if (raw_params.a0 != FFA_ERROR || (uint32_t)raw_params.a2 != FFA_INVALID_PARAMETERS) {
+		EMSG("Unexpected error code: %d != %ld", FFA_INVALID_PARAMETERS, raw_params.a2);
+		goto err;
+	}
+
+	/* Testing non-matching source ID */
+	res = ffa_msg_send_direct_req_64(src + 1, dst, 0, 0, 0, 0, 0, &sp_msg);
+	if (res != FFA_INVALID_PARAMETERS) {
+		EMSG("Unexpected error code: %d != %d", FFA_INVALID_PARAMETERS, res);
+		goto err;
+	}
+
+	/* Sending message to own ID */
+	res = ffa_msg_send_direct_req_64(src, src, 0, 0, 0, 0, 0, &sp_msg);
+	if (res != FFA_INVALID_PARAMETERS) {
+		EMSG("Unexpected error code: %d != %d", FFA_INVALID_PARAMETERS, res);
+		goto err;
+	}
+
+	/* Sending message to normal world */
+	res = ffa_msg_send_direct_req_64(src, 0, 0, 0, 0, 0, 0, &sp_msg);
+	if (res != FFA_NOT_SUPPORTED) {
+		EMSG("Unexpected error code: %d != %d", FFA_NOT_SUPPORTED, res);
+		goto err;
+	}
+
+	/* Sending message for starting direct message response test */
+	if (!caller) {
+		res = ffa_msg_send_direct_req_64(src, dst, EP_TEST_SP_COMMUNICATION_RESPONSE, 0, 0,
+						 0, 0, &sp_msg);
+		if (res != FFA_OK) {
+			EMSG("Unexpected error code: %d != %d", FFA_OK, res);
+			goto err;
+		}
+
+		if (sp_msg.args.args64[0] != SP_TEST_OK) {
+			EMSG("Unexpected test result: %d != %ld", SP_TEST_OK, sp_msg.args.args64[0]);
+			goto err;
+		}
+	}
+
+	return_ok(msg);
+	return;
+
+err:
+	return_error(ERR_SP_COMMUNICATION, msg);
+}
+
+static void test_communication_response(struct ffa_direct_msg *msg)
+{
+	struct ffa_direct_msg sp_msg = {0};
+	uint16_t caller = msg->source_id;
+	uint16_t src = msg->destination_id;
+	ffa_result res = FFA_OK;
+	struct ffa_params raw_params = { 0 };
+
+	/* Non-null flags (W2) register */
+	ffa_svc(FFA_MSG_SEND_DIRECT_RESP_64, (uint32_t)(src << 16 | 0x1000), 1, 0, 0, 0, 0, 1,
+		&raw_params);
+	if (raw_params.a0 != FFA_ERROR || (uint32_t)raw_params.a2 != FFA_INVALID_PARAMETERS) {
+		EMSG("Unexpected error code: %d != %ld", FFA_INVALID_PARAMETERS, raw_params.a2);
+		goto err;
+	}
+
+	/* Testing non-matching source ID */
+	res = ffa_msg_send_direct_resp_64(src + 1, caller, 0, 0, 0, 0, 2, &sp_msg);
+	if (res != FFA_INVALID_PARAMETERS) {
+		EMSG("Unexpected error code: %d != %d", FFA_INVALID_PARAMETERS, res);
+		goto err;
+	}
+
+	/* Sending message to own ID */
+	res = ffa_msg_send_direct_resp_64(src, src, 0, 0, 0, 0, 3, &sp_msg);
+	if (res != FFA_INVALID_PARAMETERS) {
+		EMSG("Unexpected error code: %d != %d", FFA_INVALID_PARAMETERS, res);
+		goto err;
+	}
+
+	/* Sending message request to caller SP which is busy */
+	if (caller) {
+		/* Sending message to normal world */
+		res = ffa_msg_send_direct_resp_64(src, 0, 0, 0, 0, 0, 4, &sp_msg);
+		if (res != FFA_INVALID_PARAMETERS) {
+			EMSG("Unexpected error code: %d != %d", FFA_INVALID_PARAMETERS, res);
+			goto err;
+		}
+
+		/* Sending message to invalid SP */
+		res = ffa_msg_send_direct_resp_64(src, 0x1000, 0, 0, 0, 0, 5, &sp_msg);
+		if (res != FFA_INVALID_PARAMETERS) {
+			EMSG("Unexpected error code: %d != %d", FFA_INVALID_PARAMETERS, res);
+			goto err;
+		}
+
+		/* Sending message request to caller SP which is busy */
+		res = ffa_msg_send_direct_req_64(src, caller, 0, 0, 0, 0, 6, &sp_msg);
+		if (res != FFA_BUSY) {
+			EMSG("Unexpected error code: %d != %d", FFA_BUSY, res);
+			goto err;
+		}
+	}
+
+	ffa_msg_send_direct_resp_64(src, caller, SP_TEST_OK, 0, 0, 0, 0, msg);
+	return;
+
+err:
+	ffa_msg_send_direct_resp_64(src, caller, ERR_SP_COMMUNICATION, 0, 0, 0, 0, msg);
+
 }
 
 static void test_internal_sp(struct ffa_direct_msg *msg)
@@ -793,6 +904,9 @@
 		case EP_TEST_SP_COMMUNICATION:
 			test_communication(&msg);
 			break;
+		case EP_TEST_SP_COMMUNICATION_RESPONSE:
+			test_communication_response(&msg);
+			break;
 		case EP_TEST_SP_INCREASE:
 			test_increase(&msg);
 			break;
diff --git a/tools/cmake/common/LazyFetch.cmake b/tools/cmake/common/LazyFetch.cmake
index 68e790e..0c00bce 100644
--- a/tools/cmake/common/LazyFetch.cmake
+++ b/tools/cmake/common/LazyFetch.cmake
@@ -16,6 +16,24 @@
 #[===[.rst:
 Common fetch interface for external dependencies.
 -------------------------------------------------
+
+The following variables can be set in cmake or in the environment to configure various aspect of
+building and external component.
+Note: <DEP_NAME> is the name of the dependency as set int the cmake files with all characters
+converted to uppercase.
+
+``<DEP_NAME>_VERBOSE_CONFIG``
+	Global variable or environment variable.
+	Pass `--trace-expand` to cmake if set.
+
+``<DEP_NAME>_VERBOSE_BUILD``
+	Global variable or environment variable.
+	Turn the build step to verbose mode if set.
+
+``<DEP_NAME>_GENERATOR``
+	Global variable or environment variable.
+	Set the cmake generator to a specific value. If not set, the value of CMAKE_GENERATOR
+	will be used.
 #]===]
 
 #[===[.rst:
@@ -68,6 +86,12 @@
 	can be used to pass variables to the external project.
 	``INSTALL_DIR``
 	Install path. If not set, the install step will be skipped.
+	``<DEP_NAME>_VERBOSE_CONFIG``
+	Global variable or environment variable.
+	Pass `--trace-expand` to cmake if set.
+	``<DEP_NAME>_VERBOSE_BUILD``
+	Global variable or environment variable.
+	Turn the build step to verbose mode if set.
 	#]===]
 
 function(LazyFetch_ConfigAndBuild)
@@ -87,13 +111,27 @@
 							"component specific. Pleas refer to the upstream documentation for more information.")
 	endif()
 
+	if (DEFINED ${UC_DEP_NAME}_VERBOSE_CONFIG OR DEFINED ENV{${UC_DEP_NAME}_VERBOSE_CONFIG})
+		set(_CMAKE_VERBOSE_CFG_FLAG "--trace-expand")
+	endif()
+
+	if(NOT DEFINED ${UC_DEP_NAME}_GENERATOR)
+		if(DEFINED ENV{${UC_DEP_NAME}_GENERATOR})
+			set(${UC_DEP_NAME}_GENERATOR ENV{${UC_DEP_NAME}_GENERATOR} CACHE STRING "CMake generator used for ${UC_DEP_NAME}.")
+		else()
+			set(${UC_DEP_NAME}_GENERATOR ${CMAKE_GENERATOR} CACHE STRING "CMake generator used for ${UC_DEP_NAME}.")
+		endif()
+	endif()
+
 	execute_process(COMMAND
 		${CMAKE_COMMAND} -E env "CROSS_COMPILE=${CROSS_COMPILE}"
 		${CMAKE_COMMAND}
 			"-C${CONFIGURED_CACHE_FILE}"
 			-DCMAKE_BUILD_TYPE=${${UC_DEP_NAME}_BUILD_TYPE}
+			-G${${UC_DEP_NAME}_GENERATOR}
 			-S ${BUILD_SRC_DIR}
 			-B ${BUILD_BIN_DIR}
+			${_CMAKE_VERBOSE_CFG_FLAG}
 		RESULT_VARIABLE
 			_exec_error
 		)
@@ -101,6 +139,10 @@
 		message(FATAL_ERROR "Configuring ${BUILD_DEP_NAME} build failed. `${_exec_error}`")
 	endif()
 
+	if (DEFINED ${UC_DEP_NAME}_VERBOSE_BUILD OR DEFINED ENV{${UC_DEP_NAME}_VERBOSE_BUILD})
+		set(_CMAKE_VERBOSE_CFG_FLAG "--verbose")
+	endif()
+
 	if (BUILD_INSTALL_DIR)
 		execute_process(COMMAND
 			${CMAKE_COMMAND} -E env "CROSS_COMPILE=${CROSS_COMPILE}"
@@ -108,6 +150,7 @@
 				--build ${BUILD_BIN_DIR}
 				--parallel ${PROCESSOR_COUNT}
 				--target install
+				${_CMAKE_VERBOSE_BLD_FLAG}
 			RESULT_VARIABLE
 				_exec_error
 			)
@@ -117,6 +160,7 @@
 			${CMAKE_COMMAND}
 				--build ${BUILD_BIN_DIR}
 				--parallel ${PROCESSOR_COUNT}
+				${_CMAKE_VERBOSE_BLD_FLAG}
 			RESULT_VARIABLE
 				_exec_error
 			)
@@ -153,6 +197,12 @@
 	``SOURCE_SUBDIR``
 	A subdirectory relative to the top level directory of the fetched component, where the CMakeLists.txt file
 	can be found.
+	``<DEP_NAME>_VERBOSE_CONFIG``
+	Global variable or environment variable.
+	Pass `--trace-expand` to cmake if set.
+	``<DEP_NAME>_VERBOSE_BUILD``
+	Global variable or environment variable.
+	Turn the build step to verbose mode if set.
 	#]===]
 
 macro(LazyFetch_MakeAvailable)
@@ -167,6 +217,8 @@
 
 	# FetchContent* functions use this form
 	string(TOLOWER ${MY_DEP_NAME} MY_LC_DEP_NAME)
+	# We also need the upper case version
+	string(TOUPPER ${MY_DEP_NAME} MY_UC_DEP_NAME)
 
 	# Look for name collision. We can collide with project() commands, other external components defined with
 	# LazyFetch, FetchCOntent or ExternalProject.
@@ -221,12 +273,17 @@
 					)
 			endif()
 		elseif(DEFINED MY_INSTALL_DIR)
+			if(DEFINED ${MY_UC_DEP_NAME}_VERBOSE_BUILD OR DEFINED ENV{${MY_UC_DEP_NAME}_VERBOSE_BUILD})
+				set(_CMAKE_VERBOSE_BLD_FLAG "--verbose")
+			endif()
+
 			execute_process(COMMAND
 				${CMAKE_COMMAND} -E env "CROSS_COMPILE=${CROSS_COMPILE}"
 				${CMAKE_COMMAND}
 					--build ${${MY_LC_DEP_NAME}_BINARY_DIR}
 					--parallel ${PROCESSOR_COUNT}
 					--target install
+					${_CMAKE_VERBOSE_BLD_FLAG}
 				RESULT_VARIABLE
 					_exec_error
 				)