xref: /optee_os/core/drivers/firewall/firewall.c (revision ef3bc69c72b8d46493eab724eab6e018423088e1)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (C) 2024, STMicroelectronics
4  */
5 
6 #include <assert.h>
7 #include <config.h>
8 #include <drivers/firewall.h>
9 #include <kernel/dt_driver.h>
10 #include <kernel/panic.h>
11 #include <libfdt.h>
12 #include <malloc.h>
13 #include <trace.h>
14 
15 /* The firewall framework requires device tree support */
16 static_assert(IS_ENABLED(CFG_DT));
17 
18 static TEE_Result firewall_get(struct dt_pargs *parg, void *data,
19 			       struct firewall_query **out_fw)
20 {
21 	struct firewall_query *fw = NULL;
22 	unsigned int i = 0;
23 
24 	assert(parg->args_count >= 0);
25 
26 	fw = calloc(1, sizeof(*fw));
27 	if (!fw)
28 		return TEE_ERROR_OUT_OF_MEMORY;
29 
30 	fw->ctrl = (struct firewall_controller *)data;
31 	fw->arg_count = parg->args_count;
32 
33 	if (fw->arg_count) {
34 		fw->args = calloc(fw->arg_count, sizeof(*fw->args));
35 		if (!fw->args) {
36 			free(fw);
37 			return TEE_ERROR_OUT_OF_MEMORY;
38 		}
39 	}
40 
41 	for (i = 0; i < (unsigned int)parg->args_count; i++)
42 		fw->args[i] = parg->args[i];
43 
44 	*out_fw = fw;
45 
46 	return TEE_SUCCESS;
47 }
48 
49 /* Firewall device API */
50 
51 void firewall_put(struct firewall_query *fw)
52 {
53 	if (fw) {
54 		free(fw->args);
55 		free(fw);
56 	}
57 }
58 
59 TEE_Result firewall_dt_get_by_index(const void *fdt, int node, uint32_t index,
60 				    struct firewall_query **out_fw)
61 {
62 	return dt_driver_device_from_node_idx_prop("access-controllers", fdt,
63 						   node, index,
64 						   DT_DRIVER_FIREWALL,
65 						   out_fw);
66 }
67 
68 TEE_Result firewall_dt_get_by_name(const void *fdt, int node, const char *name,
69 				   struct firewall_query **out_fw)
70 {
71 	int index = 0;
72 
73 	index = fdt_stringlist_search(fdt, node, "access-controllers-names",
74 				      name);
75 	if (index == -FDT_ERR_NOTFOUND)
76 		return TEE_ERROR_ITEM_NOT_FOUND;
77 	else if (index < 0)
78 		return TEE_ERROR_GENERIC;
79 
80 	return firewall_dt_get_by_index(fdt, node, index, out_fw);
81 }
82 
83 TEE_Result firewall_set_configuration(struct firewall_query *fw)
84 {
85 	assert(fw && fw->ctrl && fw->ctrl->ops);
86 
87 	if (!fw->ctrl->ops->set_conf)
88 		return TEE_ERROR_NOT_SUPPORTED;
89 
90 	return fw->ctrl->ops->set_conf(fw);
91 }
92 
93 TEE_Result firewall_set_memory_configuration(struct firewall_query *fw,
94 					     paddr_t paddr, size_t size)
95 {
96 	assert(fw && fw->ctrl && fw->ctrl->ops);
97 
98 	if (!fw->ctrl->ops->set_memory_conf)
99 		return TEE_ERROR_NOT_SUPPORTED;
100 
101 	return fw->ctrl->ops->set_memory_conf(fw, paddr, size);
102 }
103 
104 TEE_Result firewall_check_access(struct firewall_query *fw)
105 {
106 	assert(fw && fw->ctrl && fw->ctrl->ops);
107 
108 	if (!fw->ctrl->ops->check_access)
109 		return TEE_ERROR_NOT_SUPPORTED;
110 
111 	return fw->ctrl->ops->check_access(fw);
112 }
113 
114 TEE_Result firewall_acquire_access(struct firewall_query *fw)
115 {
116 	assert(fw && fw->ctrl && fw->ctrl->ops);
117 
118 	if (!fw->ctrl->ops->acquire_access)
119 		return TEE_ERROR_NOT_SUPPORTED;
120 
121 	return fw->ctrl->ops->acquire_access(fw);
122 }
123 
124 TEE_Result firewall_check_memory_access(struct firewall_query *fw,
125 					paddr_t paddr, size_t size, bool read,
126 					bool write)
127 {
128 	assert(fw && fw->ctrl && fw->ctrl->ops);
129 
130 	if (!fw->ctrl->ops->check_memory_access)
131 		return TEE_ERROR_NOT_SUPPORTED;
132 
133 	return fw->ctrl->ops->check_memory_access(fw, paddr, size, read, write);
134 }
135 
136 TEE_Result firewall_acquire_memory_access(struct firewall_query *fw,
137 					  paddr_t paddr, size_t size, bool read,
138 					  bool write)
139 {
140 	assert(fw && fw->ctrl && fw->ctrl->ops);
141 
142 	if (!fw->ctrl->ops->acquire_memory_access)
143 		return TEE_ERROR_NOT_SUPPORTED;
144 
145 	return fw->ctrl->ops->acquire_memory_access(fw, paddr, size, read,
146 						    write);
147 }
148 
149 void firewall_release_access(struct firewall_query *fw)
150 {
151 	assert(fw && fw->ctrl && fw->ctrl->ops);
152 
153 	if (fw->ctrl->ops->release_access)
154 		fw->ctrl->ops->release_access(fw);
155 }
156 
157 void firewall_release_memory_access(struct firewall_query *fw, paddr_t paddr,
158 				    size_t size, bool read, bool write)
159 {
160 	assert(fw && fw->ctrl && fw->ctrl->ops);
161 
162 	if (fw->ctrl->ops->release_memory_access)
163 		fw->ctrl->ops->release_memory_access(fw, paddr, size, read,
164 						     write);
165 }
166 
167 /* Firewall controller API */
168 
169 TEE_Result firewall_dt_controller_register(const void *fdt, int node,
170 					   struct firewall_controller *ctrl)
171 {
172 	assert(ctrl);
173 
174 	DMSG("Registering %s firewall controller", ctrl->name);
175 
176 	return dt_driver_register_provider(fdt, node,
177 					   (get_of_device_func)firewall_get,
178 					   ctrl, DT_DRIVER_FIREWALL);
179 }
180