Introduce volume_index for compatability with tf-a

To allow for reuse of tf-a io_dev volume access components, the
tf-a interface function plat_get_image_source() needs to be
realized. The volume_index provides a realization where the
it acts as a singleton for holding per deployment volume ID
io_dev mappings. Deployment configuration code may add
mappings to suite the needs of the deployment. This helps to
isolate the tf-a io subsystem from tf-a specific configuration
conventions.

Signed-off-by: Julian Hall <julian.hall@arm.com>
Change-Id: I913b6229d78be0c803ebe6a2f6cf06f8d1160c96
diff --git a/components/media/volume/image_source/image_source.c b/components/media/volume/image_source/image_source.c
deleted file mode 100644
index 8dcbac4..0000000
--- a/components/media/volume/image_source/image_source.c
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (c) 2022, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- *
- */
-
-#include <stddef.h>
-#include <stdint.h>
-#include <plat/common/platform.h>
-
-int plat_get_image_source(
-	unsigned int image_id,
-	uintptr_t *dev_handle,
-	uintptr_t *image_spec)
-{
-	/* Needs to allow a TS factory method to define the image source */
-	(void)image_id;
-	*dev_handle = (uintptr_t)NULL;
-	*image_spec = (uintptr_t)NULL;
-	return -1;
-}
\ No newline at end of file
diff --git a/components/media/volume/image_source/component.cmake b/components/media/volume/index/component.cmake
similarity index 89%
rename from components/media/volume/image_source/component.cmake
rename to components/media/volume/index/component.cmake
index 98ef600..2dfcedc 100644
--- a/components/media/volume/image_source/component.cmake
+++ b/components/media/volume/index/component.cmake
@@ -9,5 +9,5 @@
 endif()
 
 target_sources(${TGT} PRIVATE
-	"${CMAKE_CURRENT_LIST_DIR}/image_source.c"
+	"${CMAKE_CURRENT_LIST_DIR}/volume_index.c"
 )
\ No newline at end of file
diff --git a/components/media/volume/index/volume_index.c b/components/media/volume/index/volume_index.c
new file mode 100644
index 0000000..fe8b209
--- /dev/null
+++ b/components/media/volume/index/volume_index.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <plat/common/platform.h>
+#include "volume_index.h"
+
+#ifndef VOLUME_INDEX_MAX_ENTRIES
+#define VOLUME_INDEX_MAX_ENTRIES		(4)
+#endif
+
+/**
+ * Singleton index of volume IDs to IO devices.
+ */
+static struct
+{
+	size_t size;
+	struct
+	{
+		unsigned int volume_id;
+		uintptr_t dev_handle;
+		uintptr_t volume_spec;
+	} entries[VOLUME_INDEX_MAX_ENTRIES];
+
+} volume_index;
+
+/**
+ * @brief  Gets a device for volume IO operations
+ *
+ * @param[in]  volume_id 	Identifies the image
+ * @param[out] dev_handle 	Handle for IO operations
+ * @param[out] volume_spec	Opaque configuration data
+ *
+ * This function realizes the interface expected by tf-a components to
+ * provide a concrete IO device for the specified volume ID. When used in
+ * TS deployments, the set of IO devices required for a deployment
+ * are registered during service configuration.
+ */
+int plat_get_image_source(
+	unsigned int volume_id,
+	uintptr_t *dev_handle,
+	uintptr_t *volume_spec)
+{
+	int result = -1;
+
+	for (size_t i = 0; i < volume_index.size; i++) {
+
+		if (volume_index.entries[i].volume_id == volume_id) {
+
+			*dev_handle = volume_index.entries[i].dev_handle;
+			*volume_spec = volume_index.entries[i].volume_spec;
+
+			result = 0;
+			break;
+		}
+	}
+
+	return result;
+}
+
+void volume_index_init(void)
+{
+	volume_index_clear();
+}
+
+void volume_index_clear(void)
+{
+	memset(&volume_index, 0, sizeof(volume_index));
+}
+
+int volume_index_add(
+	unsigned int volume_id,
+	uintptr_t dev_handle,
+	uintptr_t volume_spec)
+{
+	int result = -1;
+
+	if (volume_index.size < VOLUME_INDEX_MAX_ENTRIES)
+	{
+		size_t i = volume_index.size;
+
+		++volume_index.size;
+		volume_index.entries[i].volume_id = volume_id;
+		volume_index.entries[i].dev_handle = dev_handle;
+		volume_index.entries[i].volume_spec = volume_spec;
+
+		result = 0;
+	}
+
+	return result;
+}
diff --git a/components/media/volume/index/volume_index.h b/components/media/volume/index/volume_index.h
new file mode 100644
index 0000000..dd9964c
--- /dev/null
+++ b/components/media/volume/index/volume_index.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef VOLUME_INDEX_H
+#define VOLUME_INDEX_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief  Initialize the volume index
+ *
+ * The volume_index is a singleton that holds the mapping of volume IDs
+ * to concrete IO devices that can be used to access the volume. The
+ * mappings are setup during deployment configuration to meet the IO needs
+ * of the deployment. The volume_index realizes the tf-a function
+ * plat_get_image_source() to make the mappings available to tf-a components.
+ */
+void volume_index_init(void);
+
+/**
+ * @brief  Clears the volume index
+ *
+ * Clears all mappings.
+ */
+void volume_index_clear(void);
+
+/**
+ * @brief  Add an entry to the volume index
+ *
+ * @param[in] volume_id   Volume identifier
+ * @param[in] dev_handle  Device handle to use
+ * @param[in] volume_spec  Additional information about the volume
+ *
+ * @return 0 if successful
+ */
+int volume_index_add(
+	unsigned int volume_id,
+	uintptr_t dev_handle,
+	uintptr_t volume_spec);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* VOLUME_INDEX_H */
diff --git a/deployments/component-test/component-test.cmake b/deployments/component-test/component-test.cmake
index a14783c..741ca40 100644
--- a/deployments/component-test/component-test.cmake
+++ b/deployments/component-test/component-test.cmake
@@ -163,7 +163,7 @@
 		"components/service/smm_variable/backend/test"
 		"components/media/partition_table"
 		"components/media/volume/storage"
-		"components/media/volume/image_source"
+		"components/media/volume/index"
 		"protocols/rpc/common/protobuf"
 		"protocols/rpc/common/packed-c"
 		"protocols/service/crypto/packed-c"