1 /*
2  * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include "media/volume/factory/volume_factory.h"
8 
9 #include <assert.h>
10 #include <errno.h>
11 #include <stdlib.h>
12 #include <string.h>
13 
14 #include "media/disk/guid.h"
15 #include "media/volume/block_volume/block_volume.h"
16 #include "service/block_storage/block_store/block_store.h"
17 #include "service/block_storage/factory/block_store_factory.h"
18 #include "trace.h"
19 
20 /**
21  * A volume factory for single flash deployments where underlying block-level
22  * access is provided by a block_store object. The block_store used is provided
23  * by the block_store_factory selected for the deployment. This could construct
24  * any suitable block_store.
25  */
26 static struct block_store *single_block_store;
27 
volume_factory_init(struct uuid_octets * device_uuids,size_t device_uuids_size,size_t * num_device_uuids)28 int volume_factory_init(struct uuid_octets *device_uuids, size_t device_uuids_size,
29 			size_t *num_device_uuids)
30 {
31 	assert(device_uuids || !device_uuids_size);
32 	assert(num_device_uuids);
33 
34 	*num_device_uuids = 0;
35 	single_block_store = block_store_factory_create();
36 
37 	if (!single_block_store) {
38 		EMSG("Failed to construct block_store");
39 		return -EIO;
40 	}
41 
42 	if (device_uuids_size > 0) {
43 		struct storage_partition_info device_info;
44 		struct uuid_octets uuid;
45 
46 		/* Query for GPT partition to get info about the parent device */
47 		uuid_guid_octets_from_canonical(&uuid, DISK_GUID_UNIQUE_PARTITION_DISK_HEADER);
48 
49 		psa_status_t psa_status =
50 			block_store_get_partition_info(single_block_store, &uuid, &device_info);
51 
52 		if (psa_status == PSA_SUCCESS)
53 			device_uuids[0] = device_info.parent_guid;
54 		else
55 			memset(&device_uuids[0], 0, sizeof(struct uuid_octets));
56 
57 		*num_device_uuids = 1;
58 	}
59 
60 	return 0;
61 }
62 
volume_factory_deinit(void)63 void volume_factory_deinit(void)
64 {
65 	block_store_factory_destroy(single_block_store);
66 	single_block_store = NULL;
67 }
68 
volume_factory_create_volume(const struct uuid_octets * partition_uuid,const struct uuid_octets * device_uuid)69 struct volume *volume_factory_create_volume(const struct uuid_octets *partition_uuid,
70 					    const struct uuid_octets *device_uuid)
71 {
72 	struct volume *product = NULL;
73 
74 	assert(single_block_store);
75 
76 	/* This factory assumes that all volumes are backed by a single block device */
77 	(void)device_uuid;
78 
79 	struct block_volume *block_volume =
80 		(struct block_volume *)malloc(sizeof(struct block_volume));
81 
82 	if (block_volume) {
83 		int status = block_volume_init(block_volume, single_block_store, partition_uuid,
84 					       &product);
85 
86 		if (status) {
87 			EMSG("Failed to init block volume: %d", status);
88 			product = NULL;
89 			free(block_volume);
90 		}
91 	} else {
92 		EMSG("Failed to alloc block volume");
93 	}
94 
95 	return product;
96 }
97 
volume_factory_destroy_volume(struct volume * volume)98 void volume_factory_destroy_volume(struct volume *volume)
99 {
100 	if (volume && volume->io_spec)
101 		free((void *)volume->io_spec);
102 }
103