1 /*
2 * Copyright (c) 2019-2021, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #include <stdint.h>
9 #include "firewall.h"
10
11 #define FIREWALL_COMPONENT_SIZE (0x10000)
12 #define FIREWALL_MAX_COMPONENTS (0x20)
13
14 #define FIREWALL_COMMON_REG_OFFSET (0xFA0)
15 struct _firewall_common_reg_map_t {
16 volatile uint32_t fc_cap0;
17 /*!< Offset: 0xFA0 (R/ ) Firewall Component Capability Register 0 */
18 volatile uint32_t fc_cap1;
19 /*!< Offset: 0xFA4 (R/ ) Firewall Component Capability Register 1 */
20 volatile uint32_t fc_cap2;
21 /*!< Offset: 0xFA8 (R/ ) Firewall Component Capability Register 2 */
22 volatile uint32_t fc_cap3;
23 /*!< Offset: 0xFAC (R/ ) Firewall Component Capability Register 3 */
24 volatile uint32_t fc_cfg0;
25 /*!< Offset: 0xFB0 (R/ ) Firewall Component Configuration Register 0 */
26 volatile uint32_t fc_cfg1;
27 /*!< Offset: 0xFB4 (R/ ) Firewall Component Configuration Register 1 */
28 volatile uint32_t fc_cfg2;
29 /*!< Offset: 0xFB8 (R/ ) Firewall Component Configuration Register 2 */
30 volatile uint32_t fc_cfg3;
31 /*!< Offset: 0xFBC (R/ ) Firewall Component Configuration Register 3 */
32 };
33
34 #define FIREWALL_PE_CS_REG_OFFSET (0x100)
35 /*!< Protection Control and Status register type offset */
36 struct _firewall_pe_cs_reg_map_t {
37 volatile uint32_t pe_ctrl;
38 /*!< Offset: 0x100 (R/W) Protection Extenstion Control */
39 volatile uint32_t pe_st;
40 /*!< Offset: 0x104 (R/ ) Protection Extenstion Status */
41 volatile uint32_t pe_bps;
42 /*!< Offset: 0x108 (R/W) Protection Extenstion Bypass */
43 };
44 #define PE_CTRL_EN_MASK (0x1u << PE_CTRL_EN_OFF)
45 #define PE_CTRL_EN_BYPASS_MASK (0x1u << PE_CTRL_EN_BYPASS_OFF)
46 #define PE_ST_EN_MASK (0x1u << PE_ST_EN_OFF)
47 #define PE_BPS_BYPASS_ST_MASK (0x1u << PE_BPS_BYPASS_ST_OFF)
48
49 #define FIREWALL_PE_RWE_REG_OFFSET (0x10C)
50 /*!< Region Window Entry (RWE) register type offset */
51 struct _firewall_pe_rwe_reg_map_t {
52 volatile uint32_t rwe_ctrl;
53 /*!< Offset: 0x10C (R/W) Region Window Entry Control */
54 volatile uint32_t rgn_ctrl0;
55 /*!< Offset: 0x110 (R/W) Region Control 0 */
56 volatile uint32_t rgn_ctrl1;
57 /*!< Offset: 0x114 (R/W) Region Control 1 */
58 volatile uint32_t rgn_lctrl;
59 /*!< Offset: 0x118 (R/W) Region Lock Control */
60 volatile uint32_t rgn_st;
61 /*!< Offset: 0x11C (R/ ) Region Status */
62 volatile uint32_t rgn_cfg0;
63 /*!< Offset: 0x120 (R/W) Region Config 0 */
64 volatile uint32_t rgn_cfg1;
65 /*!< Offset: 0x124 (R/W) Region Config 1 */
66 volatile uint32_t rgn_size;
67 /*!< Offset: 0x128 (R/W) Region Size */
68 volatile uint32_t reserved_0;
69 /*!< Offset: 0x12C Reserved */
70 volatile uint32_t rgn_tcfg0;
71 /*!< Offset: 0x130 (R/W) Region Translation Config 0 */
72 volatile uint32_t rgn_tcfg1;
73 /*!< Offset: 0x134 (R/W) Region Translation Config 1 */
74 volatile uint32_t rgn_tcfg2;
75 /*!< Offset: 0x138 (R/W) Region Translation Config 2 */
76 volatile uint32_t reserved_1;
77 /*!< Offset: 0x13C Reserved */
78 volatile uint32_t rgn_mid0;
79 /*!< Offset: 0x140 (R/W) Region Master ID 0 */
80 volatile uint32_t rgn_mpl0;
81 /*!< Offset: 0x144 (R/W) Region Master Permission List 0 */
82 volatile uint32_t rgn_mid1;
83 /*!< Offset: 0x148 (R/W) Region Master ID 1 */
84 volatile uint32_t rgn_mpl1;
85 /*!< Offset: 0x14C (R/W) Region Master Permission List 1 */
86 volatile uint32_t rgn_mid2;
87 /*!< Offset: 0x150 (R/W) Region Master ID 2 */
88 volatile uint32_t rgn_mpl2;
89 /*!< Offset: 0x154 (R/W) Region Master Permission List 2 */
90 volatile uint32_t rgn_mid3;
91 /*!< Offset: 0x158 (R/W) Region Master ID 3 */
92 volatile uint32_t rgn_mpl3;
93 /*!< Offset: 0x15C (R/W) Region Master Permission List 3 */
94 };
95 #define RWE_CTRL_RGN_INDX_MASK (0xFFu << RWE_CTRL_RGN_INDX_OFF)
96 #define RGN_CTRL0_EN_MASK (0x1u << RGN_EN_OFF)
97 #define RGN_LCTRL_LOCK_MASK (0x1u << RGN_LCTRL_LOCK_OFF)
98 #define RGN_CTRL1_MPE_EN_MASK (0xFu << RGN_MPE0_EN_OFF)
99 #define RGN_MPL_EN_MASK (0x1FFFu)
100 #define RGN_ST_EN_MASK (0x1u << RGN_EN_OFF)
101 #define RGN_ST_MPE0_EN_MASK (0x1u << RGN_MPE0_EN_OFF)
102 #define RGN_ST_MPE1_EN_MASK (0x1u << RGN_MPE1_EN_OFF)
103 #define RGN_ST_MPE2_EN_MASK (0x1u << RGN_MPE2_EN_OFF)
104 #define RGN_ST_MPE3_EN_MASK (0x1u << RGN_MPE3_EN_OFF)
105 #define RGN_SIZE_SIZE_MASK (0xFFu << RGN_SIZE_SIZE_OFF)
106 #define RGN_SIZE_MULnPO2_MASK (0x1u << RGN_SIZE_MULnPO2_OFF)
107 #define RGN_TCFG2_ADDR_TRANS_EN_MASK (0x1u << RGN_TCFG2_ADDR_TRANS_EN_OFF)
108 #define RGN_TCFG2_MA_TRANS_EN_MASK (0x1u << RGN_TCFG2_MA_TRANS_EN_OFF)
109 #define RGN_TCFG2_INST_MASK (0x3u << RGN_TCFG2_INST_OFF)
110 #define RGN_TCFG2_PRIV_MASK (0x3u << RGN_TCFG2_PRIV_OFF)
111 #define RGN_TCFG2_MA_MASK (0xFFu << RGN_TCFG2_MA_OFF)
112 #define RGN_TCFG2_SH_MASK (0x3u << RGN_TCFG2_SH_OFF)
113 #define RGN_TCFG2_NS_MASK (0x3u << RGN_TCFG2_NS_OFF)
114
115 #define FIREWALL_PE_FWE_REG_OFFSET (0x180)
116 /*!< Fault Window Entry (FWE) register type offset */
117 struct _firewall_pe_fwe_reg_map_t {
118 volatile uint32_t fe_tal;
119 /*!< Offset: 0x180 (R/ ) Fault Entry Transaction Address Lower */
120 volatile uint32_t fe_tau;
121 /*!< Offset: 0x184 (R/ ) Fault Entry Transaction Address Upper */
122 volatile uint32_t fe_tp;
123 /*!< Offset: 0x188 (R/ ) Fault Entry Transaction Properties */
124 volatile uint32_t fe_mid;
125 /*!< Offset: 0x18C (R/ ) Fault Entry Master ID */
126 volatile uint32_t fe_ctrl;
127 /*!< Offset: 0x190 (R/W) Fault Entry Control */
128 };
129
130 #define FIREWALL_LDE_REG_OFFSET (0x10)
131 /*!< Lockdown Extension (LDE) register type offset */
132 struct _firewall_lde_reg_map_t {
133 volatile uint32_t ld_ctrl;
134 /*!< Offset: 0x10 (R/W) Lockdown Control */
135 };
136 #define LD_CTRL_LOCK_MASK (0x3u << LD_CTRL_LOCK_OFF)
137 #define LD_CTRL_LDI_ST_MASK (0x1u << LD_CTRL_LDI_ST_OFF)
138
139 #define CS_REG_ADDR(x, y)\
140 (x + (y * FIREWALL_COMPONENT_SIZE) + FIREWALL_PE_CS_REG_OFFSET)
141 #define RWE_REG_ADDR(x, y)\
142 (x + (y * FIREWALL_COMPONENT_SIZE) + FIREWALL_PE_RWE_REG_OFFSET)
143 #define FWE_REG_ADDR(x, y)\
144 (x + (y * FIREWALL_COMPONENT_SIZE) + FIREWALL_PE_FWE_REG_OFFSET)
145 #define LDE_REG_ADDR(x) (x + FIREWALL_LDE_REG_OFFSET)
146
147 struct fw_dev_data_t fw_data;
148
fc_select(void * base_addr,uint32_t comp_id)149 void fc_select(void *base_addr, uint32_t comp_id)
150 {
151 fw_data.base_addr = base_addr;
152 fw_data.comp_id = comp_id;
153 fw_data.cs_ptr = CS_REG_ADDR(fw_data.base_addr, fw_data.comp_id);
154 fw_data.rwe_ptr = RWE_REG_ADDR(fw_data.base_addr, fw_data.comp_id);
155 }
156
fc_enable_bypass(void)157 void fc_enable_bypass(void)
158 {
159 struct _firewall_pe_cs_reg_map_t *ptr =
160 (struct _firewall_pe_cs_reg_map_t *)fw_data.cs_ptr;
161 ptr->pe_ctrl &= ~PE_CTRL_EN_BYPASS_MASK;
162 while (!(ptr->pe_bps & PE_BPS_BYPASS_ST_MASK))
163 ;
164 }
165
fc_disable_bypass(void)166 void fc_disable_bypass(void)
167 {
168 struct _firewall_pe_cs_reg_map_t *ptr =
169 (struct _firewall_pe_cs_reg_map_t *)fw_data.cs_ptr;
170 ptr->pe_ctrl |= PE_CTRL_EN_BYPASS_MASK;
171 while ((ptr->pe_bps & PE_BPS_BYPASS_ST_MASK))
172 ;
173 }
174
fc_pe_enable(void)175 void fc_pe_enable(void)
176 {
177 struct _firewall_pe_cs_reg_map_t *ptr =
178 (struct _firewall_pe_cs_reg_map_t *)fw_data.cs_ptr;
179 ptr->pe_ctrl |= PE_CTRL_EN_MASK;
180 while (!(ptr->pe_st & PE_ST_EN_MASK))
181 ;
182 }
183
fc_pe_disable(void)184 void fc_pe_disable(void)
185 {
186 struct _firewall_pe_cs_reg_map_t *ptr =
187 (struct _firewall_pe_cs_reg_map_t *)fw_data.cs_ptr;
188 ptr->pe_ctrl &= ~PE_CTRL_EN_MASK;
189 while ((ptr->pe_st & PE_ST_EN_MASK))
190 ;
191 }
192
fc_disable_txn_term_error(void * base_addr)193 void fc_disable_txn_term_error(void *base_addr)
194 {
195 uint32_t *ptr = (uint32_t *)base_addr;
196 /* Write 0 to ERR bit field of FW_CTRL register */
197 *ptr = 0;
198 }
199
fc_select_region(uint32_t region_id)200 void fc_select_region(uint32_t region_id)
201 {
202 struct _firewall_pe_rwe_reg_map_t *ptr =
203 (struct _firewall_pe_rwe_reg_map_t *)fw_data.rwe_ptr;
204 ptr->rwe_ctrl = (ptr->rwe_ctrl & ~RWE_CTRL_RGN_INDX_MASK) |
205 (region_id & RWE_CTRL_RGN_INDX_MASK);
206 }
207
fc_enable_regions(void)208 void fc_enable_regions(void)
209 {
210 struct _firewall_pe_rwe_reg_map_t *ptr =
211 (struct _firewall_pe_rwe_reg_map_t *)fw_data.rwe_ptr;
212 ptr->rgn_ctrl0 |= RGN_CTRL0_EN_MASK;
213 }
214
fc_disable_regions(void)215 void fc_disable_regions(void)
216 {
217 struct _firewall_pe_rwe_reg_map_t *ptr =
218 (struct _firewall_pe_rwe_reg_map_t *)fw_data.rwe_ptr;
219 ptr->rgn_ctrl0 &= ~RGN_CTRL0_EN_MASK;
220 }
221
fc_prog_rgn(enum rgn_size_t size,uint32_t base_addr)222 void fc_prog_rgn(enum rgn_size_t size, uint32_t base_addr)
223 {
224 struct _firewall_pe_rwe_reg_map_t *ptr =
225 (struct _firewall_pe_rwe_reg_map_t *)fw_data.rwe_ptr;
226 /*
227 * As the reset value is rgn_size register is UNKNOWN, Arm recommends to set
228 * register to a known value before performing read-modify-write operations
229 */
230 ptr->rgn_size = 0;
231 ptr->rgn_size = (ptr->rgn_size & ~RGN_SIZE_SIZE_MASK) |
232 (size & RGN_SIZE_SIZE_MASK);
233 ptr->rgn_cfg0 = base_addr;
234 }
235
fc_prog_rgn_upper_addr(uint32_t upper_addr)236 void fc_prog_rgn_upper_addr(uint32_t upper_addr)
237 {
238 struct _firewall_pe_rwe_reg_map_t *ptr =
239 (struct _firewall_pe_rwe_reg_map_t *)fw_data.rwe_ptr;
240 ptr->rgn_tcfg0 = upper_addr;
241 }
242
fc_enable_addr_trans(void)243 void fc_enable_addr_trans(void)
244 {
245 struct _firewall_pe_rwe_reg_map_t *ptr =
246 (struct _firewall_pe_rwe_reg_map_t *)fw_data.rwe_ptr;
247 ptr->rgn_tcfg2 |= RGN_TCFG2_ADDR_TRANS_EN_MASK;
248 }
249
fc_disable_addr_trans(void)250 void fc_disable_addr_trans(void)
251 {
252 struct _firewall_pe_rwe_reg_map_t *ptr =
253 (struct _firewall_pe_rwe_reg_map_t *)fw_data.rwe_ptr;
254 ptr->rgn_tcfg2 &= ~RGN_TCFG2_ADDR_TRANS_EN_MASK;
255 }
256
fc_init_mpl(enum rgn_mpe_t mpe)257 void fc_init_mpl(enum rgn_mpe_t mpe)
258 {
259 struct _firewall_pe_rwe_reg_map_t *ptr =
260 (struct _firewall_pe_rwe_reg_map_t *)fw_data.rwe_ptr;
261 /* Before enabling an MPE, it must:
262 * 1) Set the RGN_MPL fields with an UNKNOWN reset value to a known value.
263 * 2) Set either:
264 * RGN_MID{0-3} to a known value.
265 * RGN_MPL.ANY_MST to 0b1.
266 */
267 if (mpe == RGN_MPE0) {
268 ptr->rgn_mpl0 = 0x1000;
269 ptr->rgn_mpl0 = 0x0;
270 } else if (mpe == RGN_MPE1) {
271 ptr->rgn_mpl1 = 0x1000;
272 ptr->rgn_mpl1 = 0x0;
273 } else if (mpe == RGN_MPE2) {
274 ptr->rgn_mpl2 = 0x1000;
275 ptr->rgn_mpl2 = 0x0;
276 } else if (mpe == RGN_MPE3) {
277 ptr->rgn_mpl3 = 0x1000;
278 ptr->rgn_mpl3 = 0x0;
279 }
280 }
281
fc_enable_mpl(enum rgn_mpe_t mpe,enum rgn_mpl_t mpl)282 void fc_enable_mpl(enum rgn_mpe_t mpe, enum rgn_mpl_t mpl)
283 {
284 struct _firewall_pe_rwe_reg_map_t *ptr =
285 (struct _firewall_pe_rwe_reg_map_t *)fw_data.rwe_ptr;
286 if (mpe == RGN_MPE0)
287 ptr->rgn_mpl0 |= (mpl & RGN_MPL_EN_MASK);
288 else if (mpe == RGN_MPE1)
289 ptr->rgn_mpl1 |= (mpl & RGN_MPL_EN_MASK);
290 else if (mpe == RGN_MPE2)
291 ptr->rgn_mpl2 |= (mpl & RGN_MPL_EN_MASK);
292 else if (mpe == RGN_MPE3)
293 ptr->rgn_mpl3 |= (mpl & RGN_MPL_EN_MASK);
294 }
295
fc_read_mpl(enum rgn_mpe_t mpe,enum rgn_mpl_t * mpl)296 void fc_read_mpl(enum rgn_mpe_t mpe, enum rgn_mpl_t* mpl)
297 {
298 struct _firewall_pe_rwe_reg_map_t *ptr =
299 (struct _firewall_pe_rwe_reg_map_t *)fw_data.rwe_ptr;
300 if (mpe == RGN_MPE0)
301 *mpl = (ptr->rgn_mpl0 & RGN_MPL_EN_MASK);
302 else if (mpe == RGN_MPE1)
303 *mpl = (ptr->rgn_mpl1 & RGN_MPL_EN_MASK);
304 else if (mpe == RGN_MPE2)
305 *mpl = (ptr->rgn_mpl2 & RGN_MPL_EN_MASK);
306 else if (mpe == RGN_MPE3)
307 *mpl = (ptr->rgn_mpl3 & RGN_MPL_EN_MASK);
308 }
309
310
fc_disable_mpl(enum rgn_mpe_t mpe,enum rgn_mpl_t mpl)311 void fc_disable_mpl(enum rgn_mpe_t mpe, enum rgn_mpl_t mpl)
312 {
313 struct _firewall_pe_rwe_reg_map_t *ptr =
314 (struct _firewall_pe_rwe_reg_map_t *)fw_data.rwe_ptr;
315 mpl &= RGN_MPL_EN_MASK;
316 if (mpe == RGN_MPE0)
317 ptr->rgn_mpl0 &= ~mpl;
318 else if (mpe == RGN_MPE1)
319 ptr->rgn_mpl1 &= ~mpl;
320 else if (mpe == RGN_MPE2)
321 ptr->rgn_mpl2 &= ~mpl;
322 else if (mpe == RGN_MPE3)
323 ptr->rgn_mpl3 &= ~mpl;
324 }
325
fc_prog_mid(enum rgn_mpe_t mpe,uint32_t mid)326 void fc_prog_mid(enum rgn_mpe_t mpe, uint32_t mid)
327 {
328 struct _firewall_pe_rwe_reg_map_t *ptr =
329 (struct _firewall_pe_rwe_reg_map_t *)fw_data.rwe_ptr;
330 if (mpe == RGN_MPE0)
331 ptr->rgn_mid0 = mid;
332 else if (mpe == RGN_MPE1)
333 ptr->rgn_mid1 = mid;
334 else if (mpe == RGN_MPE2)
335 ptr->rgn_mid2 = mid;
336 else if (mpe == RGN_MPE3)
337 ptr->rgn_mid3 = mid;
338 }
339
fc_enable_mpe(enum rgn_mpe_t mpe)340 void fc_enable_mpe(enum rgn_mpe_t mpe)
341 {
342 struct _firewall_pe_rwe_reg_map_t *ptr =
343 (struct _firewall_pe_rwe_reg_map_t *)fw_data.rwe_ptr;
344 ptr->rgn_ctrl1 |= (mpe & RGN_CTRL1_MPE_EN_MASK);
345 while (!(ptr->rgn_st & mpe))
346 ;
347 }
348
fc_disable_mpe(enum rgn_mpe_t mpe)349 void fc_disable_mpe(enum rgn_mpe_t mpe)
350 {
351 struct _firewall_pe_rwe_reg_map_t *ptr =
352 (struct _firewall_pe_rwe_reg_map_t *)fw_data.rwe_ptr;
353 mpe &= RGN_CTRL1_MPE_EN_MASK;
354 ptr->rgn_ctrl1 &= ~mpe;
355 while ((ptr->rgn_st & mpe))
356 ;
357 }
358
fc_rgn_lock(void)359 void fc_rgn_lock(void)
360 {
361 struct _firewall_pe_rwe_reg_map_t *ptr =
362 (struct _firewall_pe_rwe_reg_map_t *)fw_data.rwe_ptr;
363 ptr->rgn_lctrl |= RGN_LCTRL_LOCK_MASK;
364 }
365
fc_rgn_unlock(void)366 void fc_rgn_unlock(void)
367 {
368 struct _firewall_pe_rwe_reg_map_t *ptr =
369 (struct _firewall_pe_rwe_reg_map_t *)fw_data.rwe_ptr;
370 ptr->rgn_lctrl &= ~RGN_LCTRL_LOCK_MASK;
371 }
372
fw_get_lockdown_status(void)373 enum fw_lockdown_status_t fw_get_lockdown_status(void)
374 {
375 struct _firewall_lde_reg_map_t *ptr = (struct _firewall_lde_reg_map_t *)
376 LDE_REG_ADDR(fw_data.base_addr);
377 if (ptr->ld_ctrl & LD_CTRL_LDI_ST_MASK)
378 return FW_LOCKED;
379 else
380 return FW_UNLOCKED;
381 }
382
fw_lockdown(enum fw_lockdown_state_t lockdown_state)383 void fw_lockdown(enum fw_lockdown_state_t lockdown_state)
384 {
385 struct _firewall_lde_reg_map_t *ptr = (struct _firewall_lde_reg_map_t *)
386 LDE_REG_ADDR(fw_data.base_addr);
387 ptr->ld_ctrl |= lockdown_state;
388 }
389