1 /*
2  * Copyright (c) 2022, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include <stddef.h>
9 #include <stdint.h>
10 #include <string.h>
11 #include "volume_index.h"
12 
13 #ifndef VOLUME_INDEX_MAX_ENTRIES
14 #define VOLUME_INDEX_MAX_ENTRIES		(8)
15 #endif
16 
17 /**
18  * Singleton index of volume IDs to IO devices.
19  */
20 static struct {
21 
22 	size_t size;
23 	struct {
24 		unsigned int volume_id;
25 		struct volume *volume;
26 	} entries[VOLUME_INDEX_MAX_ENTRIES];
27 
28 } volume_index;
29 
30 /**
31  * @brief  Gets a device for volume IO operations
32  *
33  * @param[in]  volume_id 	Identifies the image
34  * @param[out] dev_handle 	Handle for IO operations
35  * @param[out] io_spec	Opaque configuration data
36  *
37  * This function realizes the interface expected by tf-a components to
38  * provide a concrete IO device for the specified volume ID. When used in
39  * TS deployments, the set of IO devices required for a deployment
40  * are registered during service configuration.
41  */
plat_get_image_source(unsigned int volume_id,uintptr_t * dev_handle,uintptr_t * io_spec)42 int plat_get_image_source(
43 	unsigned int volume_id,
44 	uintptr_t *dev_handle,
45 	uintptr_t *io_spec)
46 {
47 	struct volume *volume = NULL;
48 	int result = volume_index_find(volume_id, &volume);
49 
50 	if (result == 0) {
51 
52 		if (volume) {
53 
54 			*dev_handle = volume->dev_handle;
55 			*io_spec = volume->io_spec;
56 		} else
57 			result = -1;
58 	}
59 
60 	return result;
61 }
62 
volume_index_init(void)63 void volume_index_init(void)
64 {
65 	volume_index_clear();
66 }
67 
volume_index_clear(void)68 void volume_index_clear(void)
69 {
70 	memset(&volume_index, 0, sizeof(volume_index));
71 }
72 
volume_index_add(unsigned int volume_id,struct volume * volume)73 int volume_index_add(
74 	unsigned int volume_id,
75 	struct volume *volume)
76 {
77 	int result = -1;
78 
79 	if (volume_index.size < VOLUME_INDEX_MAX_ENTRIES) {
80 		size_t i = volume_index.size;
81 
82 		++volume_index.size;
83 		volume_index.entries[i].volume_id = volume_id;
84 		volume_index.entries[i].volume = volume;
85 
86 		result = 0;
87 	}
88 
89 	return result;
90 }
91 
volume_index_find(unsigned int volume_id,struct volume ** volume)92 int volume_index_find(
93 	unsigned int volume_id,
94 	struct volume **volume)
95 {
96 	int result = -1;
97 
98 	for (size_t i = 0; i < volume_index.size; i++) {
99 
100 		if (volume_index.entries[i].volume_id == volume_id) {
101 
102 			*volume = volume_index.entries[i].volume;
103 			result = 0;
104 			break;
105 		}
106 	}
107 
108 	return result;
109 }
110 
volume_index_get(unsigned int index)111 struct volume *volume_index_get(unsigned int index)
112 {
113 	struct volume *volume = NULL;
114 
115 	if (index < volume_index.size)
116 		volume = volume_index.entries[index].volume;
117 
118 	return volume;
119 }
120