Add disk formatter component

Provides a way of initializing a storage volume. Initially, only
the clone method is currently supported where the contents of a
uint8_t array is used as the initialization data. Uses an
io_dev to initialize the storage volume so it can be used with
any supported storage.

Signed-off-by: Julian Hall <julian.hall@arm.com>
Change-Id: Ieac317abba605451e4ba81773d62fd680309ab19
diff --git a/components/media/disk/formatter/component.cmake b/components/media/disk/formatter/component.cmake
new file mode 100644
index 0000000..27b1110
--- /dev/null
+++ b/components/media/disk/formatter/component.cmake
@@ -0,0 +1,13 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2022, 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}/disk_formatter.c"
+)
\ No newline at end of file
diff --git a/components/media/disk/formatter/disk_formatter.c b/components/media/disk/formatter/disk_formatter.c
new file mode 100644
index 0000000..6b6d146
--- /dev/null
+++ b/components/media/disk/formatter/disk_formatter.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <media/volume/index/volume_index.h>
+#include <media/volume/base_io_dev/base_io_dev.h>
+#include "disk_formatter.h"
+
+int disk_formatter_clone(
+	uintptr_t dev_handle,
+	uintptr_t volume_spec,
+	const uint8_t *source_image,
+	size_t source_image_size)
+{
+	uintptr_t volume_handle;
+	int result;
+
+	result = io_open(dev_handle, volume_spec, &volume_handle);
+	if (result != 0)
+		return result;
+
+	result = io_seek(volume_handle, IO_SEEK_SET, 0);
+
+	if (result == 0) {
+
+		size_t length_written = 0;
+
+		result = io_write(volume_handle,
+			(const uintptr_t)source_image,
+			source_image_size,
+			&length_written);
+	}
+
+	io_close(volume_handle);
+	return result;
+}
\ No newline at end of file
diff --git a/components/media/disk/formatter/disk_formatter.h b/components/media/disk/formatter/disk_formatter.h
new file mode 100644
index 0000000..95b058e
--- /dev/null
+++ b/components/media/disk/formatter/disk_formatter.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MEDIA_DISK_FORMATTER_H
+#define MEDIA_DISK_FORMATTER_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief  Format a storage volume by cloning a disk image
+ *
+ * @param[in] dev_handle    IO device handle
+ * @param[in] volume_spec   Opaque volume spec
+ * @param[in] source_image  The source disk image to clone
+ * @param[in] source_image_size  The size of the source image
+ *
+ * @return 0 on success
+ */
+int disk_formatter_clone(
+	uintptr_t dev_handle,
+	uintptr_t volume_spec,
+	const uint8_t *source_image,
+	size_t source_image_size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MEDIA_DISK_FORMATTER_H */
diff --git a/components/media/disk/test/partition_table_tests.cpp b/components/media/disk/test/partition_table_tests.cpp
index c02e7a9..5e2e61f 100644
--- a/components/media/disk/test/partition_table_tests.cpp
+++ b/components/media/disk/test/partition_table_tests.cpp
@@ -14,6 +14,7 @@
 #include <media/volume/block_io_dev/block_io_dev.h>
 #include <media/volume/base_io_dev/base_io_dev.h>
 #include <media/disk/disk_images/ref_partition.h>
+#include <media/disk/formatter/disk_formatter.h>
 #include <media/disk/partition_table.h>
 #include <CppUTest/TestHarness.h>
 
@@ -27,7 +28,7 @@
 
 		m_block_store = ram_block_store_init(&m_ram_block_store,
 			NULL,
-			num_blocks, block_size, ref_partition_data);
+			num_blocks, block_size);
 
 		CHECK_TRUE(m_block_store);
 
@@ -44,6 +45,12 @@
 		CHECK_TRUE(m_dev_handle);
 		CHECK_TRUE(m_volume_spec);
 
+		result = disk_formatter_clone(
+			m_dev_handle, m_volume_spec,
+			ref_partition_data, ref_partition_data_length);
+
+		LONGS_EQUAL(0, result);
+
 		volume_index_init();
 		volume_index_add(TEST_VOLUME_ID, m_dev_handle, m_volume_spec);
 	}
diff --git a/components/media/volume/block_io_dev/test/block_io_dev_tests.cpp b/components/media/volume/block_io_dev/test/block_io_dev_tests.cpp
index 0ad7db0..f6ae2c4 100644
--- a/components/media/volume/block_io_dev/test/block_io_dev_tests.cpp
+++ b/components/media/volume/block_io_dev/test/block_io_dev_tests.cpp
@@ -22,7 +22,7 @@
 			m_partition_guid.octets, sizeof(m_partition_guid.octets));
 
 		m_block_store = ram_block_store_init(&m_ram_block_store,
-			&m_partition_guid, NUM_BLOCKS, BLOCK_SIZE, NULL);
+			&m_partition_guid, NUM_BLOCKS, BLOCK_SIZE);
 
 		CHECK_TRUE(m_block_store);
 
diff --git a/components/service/block_storage/block_store/device/ram/ram_block_store.c b/components/service/block_storage/block_store/device/ram/ram_block_store.c
index 2418412..4dd0a2d 100644
--- a/components/service/block_storage/block_store/device/ram/ram_block_store.c
+++ b/components/service/block_storage/block_store/device/ram/ram_block_store.c
@@ -196,8 +196,7 @@
 	struct ram_block_store *ram_block_store,
 	const struct uuid_octets *disk_guid,
 	size_t num_blocks,
-	size_t block_size,
-	const uint8_t *initial_data)
+	size_t block_size)
 {
 	struct block_store *retval = NULL;
 
@@ -222,10 +221,7 @@
 
 	if (ram_block_store->ram_back_store) {
 
-		if (initial_data)
-			memcpy(ram_block_store->ram_back_store, initial_data, back_store_size);
-		else
-			memset(ram_block_store->ram_back_store, RAM_BLOCK_STORE_ERASED_VALUE, back_store_size);
+		memset(ram_block_store->ram_back_store, RAM_BLOCK_STORE_ERASED_VALUE, back_store_size);
 
 		retval = block_device_init(
 			&ram_block_store->base_block_device, disk_guid, num_blocks, block_size);
diff --git a/components/service/block_storage/block_store/device/ram/ram_block_store.h b/components/service/block_storage/block_store/device/ram/ram_block_store.h
index 5030cbb..2b847e4 100644
--- a/components/service/block_storage/block_store/device/ram/ram_block_store.h
+++ b/components/service/block_storage/block_store/device/ram/ram_block_store.h
@@ -35,7 +35,6 @@
  * \param[in]  disk_guid   		The disk GUID
  * \param[in]  num_blocks       The number of contiguous blocks
  * \param[in]  block_size       Block size in bytes
- * \param[in]  initial_data		Initial image data (NULL if none)
  *
  * \return Pointer to block_store or NULL on failure
  */
@@ -43,8 +42,7 @@
 	struct ram_block_store *ram_block_store,
 	const struct uuid_octets *disk_guid,
 	size_t num_blocks,
-	size_t block_size,
-	const uint8_t *initial_data);
+	size_t block_size);
 
 /**
  * \brief De-initialize a ram_block_store
diff --git a/components/service/block_storage/block_store/device/ram/test/ram_block_store_tests.cpp b/components/service/block_storage/block_store/device/ram/test/ram_block_store_tests.cpp
index 808dbc0..dd3e4fc 100644
--- a/components/service/block_storage/block_store/device/ram/test/ram_block_store_tests.cpp
+++ b/components/service/block_storage/block_store/device/ram/test/ram_block_store_tests.cpp
@@ -18,7 +18,7 @@
 			m_partition_guid.octets, sizeof(m_partition_guid.octets));
 
 		m_block_store = ram_block_store_init(&m_ram_block_store,
-			&m_partition_guid, NUM_BLOCKS, BLOCK_SIZE, NULL);
+			&m_partition_guid, NUM_BLOCKS, BLOCK_SIZE);
 
 		CHECK_TRUE(m_block_store);
 	}
diff --git a/components/service/block_storage/block_store/partitioned/test/partitioned_block_store_tests.cpp b/components/service/block_storage/block_store/partitioned/test/partitioned_block_store_tests.cpp
index 421f988..efce19e 100644
--- a/components/service/block_storage/block_store/partitioned/test/partitioned_block_store_tests.cpp
+++ b/components/service/block_storage/block_store/partitioned/test/partitioned_block_store_tests.cpp
@@ -22,8 +22,7 @@
 			&m_ram_store,
 			&back_store_guid,
 			BACK_STORE_NUM_BLOCKS,
-			BACK_STORE_BLOCK_SIZE,
-			NULL);
+			BACK_STORE_BLOCK_SIZE);
 
 		CHECK_TRUE(back_store);
 
diff --git a/components/service/block_storage/factory/ref_ram/block_store_factory.c b/components/service/block_storage/factory/ref_ram/block_store_factory.c
index 2b414c4..631a933 100644
--- a/components/service/block_storage/factory/ref_ram/block_store_factory.c
+++ b/components/service/block_storage/factory/ref_ram/block_store_factory.c
@@ -36,8 +36,7 @@
 			&assembly->ram_block_store,
 			&back_store_guid,
 			REF_PARTITION_BACK_STORE_SIZE,
-			REF_PARTITION_BLOCK_SIZE,
-			NULL);
+			REF_PARTITION_BLOCK_SIZE);
 
 		/* Stack a partitioned_block_store over the back store */
 		product = partitioned_block_store_init(
diff --git a/deployments/component-test/component-test.cmake b/deployments/component-test/component-test.cmake
index 53ee351..7b888af 100644
--- a/deployments/component-test/component-test.cmake
+++ b/deployments/component-test/component-test.cmake
@@ -163,6 +163,7 @@
 		"components/service/smm_variable/backend/test"
 		"components/media/disk"
 		"components/media/disk/disk_images"
+		"components/media/disk/formatter"
 		"components/media/disk/test"
 		"components/media/volume/index"
 		"components/media/volume/base_io_dev"