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
firewall_get(struct dt_pargs * parg,void * data,struct firewall_query ** out_fw)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
firewall_put(struct firewall_query * fw)51 void firewall_put(struct firewall_query *fw)
52 {
53 if (fw) {
54 free(fw->args);
55 free(fw);
56 }
57 }
58
firewall_dt_get_by_index(const void * fdt,int node,uint32_t index,struct firewall_query ** out_fw)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
firewall_dt_get_by_name(const void * fdt,int node,const char * name,struct firewall_query ** out_fw)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
firewall_set_configuration(struct firewall_query * fw)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
firewall_set_memory_configuration(struct firewall_query * fw,paddr_t paddr,size_t size)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
firewall_check_access(struct firewall_query * fw)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
firewall_acquire_access(struct firewall_query * fw)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
firewall_check_memory_access(struct firewall_query * fw,paddr_t paddr,size_t size,bool read,bool write)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
firewall_acquire_memory_access(struct firewall_query * fw,paddr_t paddr,size_t size,bool read,bool write)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
firewall_release_access(struct firewall_query * fw)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
firewall_release_memory_access(struct firewall_query * fw,paddr_t paddr,size_t size,bool read,bool write)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
firewall_dt_controller_register(const void * fdt,int node,struct firewall_controller * ctrl)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