Allow sp_discovery to return more than one SP

sp_discovery_partition_info_get() could only return a single SP when
passing a UUID. Change it to enable returning multiple SPs when there
are multiple SPs with the same UUID.

Signed-off-by: Jelle Sels <jelle.sels@arm.com>
Signed-off-by: Imre Kis <imre.kis@arm.com>
Change-Id: I167432152395a62db766b18d60c3487bb814b990
diff --git a/components/messaging/ffa/libsp/sp_discovery.c b/components/messaging/ffa/libsp/sp_discovery.c
index 15cb0be..7f92b6b 100644
--- a/components/messaging/ffa/libsp/sp_discovery.c
+++ b/components/messaging/ffa/libsp/sp_discovery.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: BSD-3-Clause
 /*
- * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2023, Arm Limited and Contributors. All rights reserved.
  */
 
 #include "sp_discovery.h"
@@ -38,74 +38,7 @@
 	return SP_RESULT_FFA(ffa_res);
 }
 
-static sp_result
-partition_info_get(const struct sp_uuid *uuid,
-		   const struct ffa_partition_information **info,
-		   uint32_t *count)
-{
-	const void *buffer = NULL;
-	size_t buffer_size = 0;
-	struct ffa_uuid ffa_uuid = { 0 };
-	sp_result sp_res = SP_RESULT_OK;
-	ffa_result ffa_res = FFA_OK;
-
-	sp_res = sp_rxtx_buffer_rx_get(&buffer, &buffer_size);
-	if (sp_res != SP_RESULT_OK) {
-		*count = UINT32_C(0);
-		return sp_res;
-	}
-
-	/* Safely convert to FF-A UUID format */
-	memcpy(&ffa_uuid.uuid, uuid->uuid, sizeof(ffa_uuid.uuid));
-
-	ffa_res = ffa_partition_info_get(&ffa_uuid, count);
-	if (ffa_res != FFA_OK) {
-		*count = UINT32_C(0);
-		return SP_RESULT_FFA(ffa_res);
-	}
-
-	if ((*count * sizeof(struct ffa_partition_information)) > buffer_size) {
-		/*
-		 * The indicated amount of info structures doesn't fit into the
-		 * RX buffer.
-		 */
-		*count = UINT32_C(0);
-		return SP_RESULT_INTERNAL_ERROR;
-	}
-
-	*info = (const struct ffa_partition_information *)buffer;
-
-	return SP_RESULT_OK;
-}
-
-static sp_result
-partition_info_get_single(const struct sp_uuid *uuid,
-			  const struct ffa_partition_information **info)
-{
-	uint32_t count = 0;
-	sp_result sp_res = SP_RESULT_OK;
-
-	if (uuid == NULL)
-		return SP_RESULT_INVALID_PARAMETERS;
-
-	/*
-	 * Nil UUID means querying all partitions which is handled by a separate
-	 * function.
-	 */
-	if (memcmp(&uuid_nil, uuid, sizeof(struct sp_uuid)) == 0)
-		return SP_RESULT_INVALID_PARAMETERS;
-
-	sp_res = partition_info_get(uuid, info, &count);
-	if (sp_res != SP_RESULT_OK)
-		return sp_res;
-
-	if (count == 0)
-		return SP_RESULT_NOT_FOUND;
-
-	return SP_RESULT_OK;
-}
-
-static void unpack_ffa_info(const struct ffa_partition_information ffa_info[],
+static void unpack_ffa_info(const struct ffa_partition_information *ffa_info,
 			    struct sp_partition_info *sp_info)
 {
 	uint32_t props = ffa_info->partition_properties;
@@ -120,53 +53,20 @@
 		props & FFA_PARTITION_SUPPORTS_INDIRECT_REQUESTS;
 }
 
-sp_result sp_discovery_partition_id_get(const struct sp_uuid *uuid,
-					uint16_t *id)
-{
-	const struct ffa_partition_information *ffa_info = NULL;
-	sp_result sp_res = SP_RESULT_OK;
-
-	if (id == NULL)
-		return SP_RESULT_INVALID_PARAMETERS;
-
-	sp_res = partition_info_get_single(uuid, &ffa_info);
-	if (sp_res != SP_RESULT_OK) {
-		*id = FFA_ID_GET_ID_MASK;
-		return sp_res;
-	}
-
-	*id = ffa_info->partition_id;
-
-	return SP_RESULT_OK;
-}
-
-sp_result sp_discovery_partition_info_get(const struct sp_uuid *uuid,
-					  struct sp_partition_info *info)
-{
-	const struct ffa_partition_information *ffa_info = NULL;
-	sp_result sp_res = SP_RESULT_OK;
-
-	if (info == NULL)
-		return SP_RESULT_INVALID_PARAMETERS;
-
-	sp_res = partition_info_get_single(uuid, &ffa_info);
-	if (sp_res != SP_RESULT_OK) {
-		*info = (struct sp_partition_info){ 0 };
-		return sp_res;
-	}
-
-	unpack_ffa_info(ffa_info, info);
-
-	return SP_RESULT_OK;
-}
-
-sp_result sp_discovery_partition_info_get_all(struct sp_partition_info info[],
-					      uint32_t *count)
+static sp_result
+partition_info_get(const struct sp_uuid *uuid,
+		   struct sp_partition_info info[],
+		   uint32_t *count,
+		   bool allow_nil_uuid)
 {
 	const struct ffa_partition_information *ffa_info = NULL;
 	uint32_t ffa_count = 0;
 	uint32_t i = 0;
 	sp_result sp_res = SP_RESULT_OK;
+	const void *buffer = NULL;
+	size_t buffer_size = 0;
+	struct ffa_uuid ffa_uuid = { 0 };
+	ffa_result ffa_res = FFA_OK;
 
 	if (count == NULL)
 		return SP_RESULT_INVALID_PARAMETERS;
@@ -176,10 +76,40 @@
 		return SP_RESULT_INVALID_PARAMETERS;
 	}
 
-	sp_res = partition_info_get(&uuid_nil, &ffa_info, &ffa_count);
+	if (uuid == NULL || (!allow_nil_uuid &&
+	    memcmp(&uuid_nil, uuid, sizeof(struct sp_uuid)) == 0)) {
+		sp_res = SP_RESULT_INVALID_PARAMETERS;
+		goto out;
+	}
+
+	sp_res = sp_rxtx_buffer_rx_get(&buffer, &buffer_size);
 	if (sp_res != SP_RESULT_OK) {
-		*count = UINT32_C(0);
-		return sp_res;
+		goto out;
+	}
+
+	/* Safely convert to FF-A UUID format */
+	memcpy(&ffa_uuid.uuid, uuid->uuid, sizeof(ffa_uuid.uuid));
+
+	ffa_res = ffa_partition_info_get(&ffa_uuid, &ffa_count);
+	if (ffa_res != FFA_OK) {
+		sp_res = SP_RESULT_FFA(ffa_res);
+		goto out;
+	}
+
+	if ((ffa_count * sizeof(struct ffa_partition_information)) > buffer_size) {
+		/*
+		 * The indicated amount of info structures doesn't fit into the
+		 * RX buffer.
+		 */
+		sp_res = SP_RESULT_INTERNAL_ERROR;
+		goto out;
+	}
+
+	ffa_info = (const struct ffa_partition_information *)buffer;
+
+	if (ffa_count == 0) {
+		sp_res = SP_RESULT_NOT_FOUND;
+		goto out;
 	}
 
 	*count = MIN(*count, ffa_count);
@@ -187,4 +117,48 @@
 		unpack_ffa_info(&ffa_info[i], &info[i]);
 
 	return SP_RESULT_OK;
+
+out:
+	for (i = 0; i < *count; i++)
+		info[i] =  (struct sp_partition_info){ 0 };
+	*count = UINT32_C(0);
+
+	return sp_res;
+}
+
+sp_result sp_discovery_partition_id_get(const struct sp_uuid *uuid,
+					uint16_t *id)
+{
+	struct sp_partition_info sp_info = { 0 };
+	sp_result sp_res = SP_RESULT_OK;
+	uint32_t count = 1;
+
+	if (id == NULL)
+		return SP_RESULT_INVALID_PARAMETERS;
+
+	*id = FFA_ID_GET_ID_MASK;
+
+	if (uuid == NULL || memcmp(&uuid_nil, uuid, sizeof(struct sp_uuid)) == 0)
+		return SP_RESULT_INVALID_PARAMETERS;
+
+	sp_res = partition_info_get(uuid, &sp_info, &count, false);
+	if (sp_res != SP_RESULT_OK)
+		return sp_res;
+
+	*id = sp_info.partition_id;
+
+	return SP_RESULT_OK;
+}
+
+sp_result sp_discovery_partition_info_get(const struct sp_uuid *uuid,
+					  struct sp_partition_info info[],
+					  uint32_t *count)
+{
+	return partition_info_get(uuid, info, count, false);
+}
+
+sp_result sp_discovery_partition_info_get_all(struct sp_partition_info info[],
+					      uint32_t *count)
+{
+	return partition_info_get(&uuid_nil, info, count, true);
 }