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