1 /*
2 * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <string.h>
8 #include "sdkconfig.h"
9 #include "soc/periph_defs.h"
10 #include "esp_intr_alloc.h"
11 #include "hal/memprot_ll.h"
12 #include "riscv/interrupt.h"
13 #include "esp32c3/rom/ets_sys.h"
14 #include "esp_cpu.h"
15 #include "esp_fault.h"
16 #include "esp_attr.h"
17 #include "hal/memprot_types.h"
18 #include "esp_private/esp_memprot_internal.h"
19 #include "esp_memprot.h"
20
21 extern int _iram_text_end;
22 extern int _rtc_text_end;
23
esp_memprot_iram0_get_def_split_addr(void)24 static void *esp_memprot_iram0_get_def_split_addr(void)
25 {
26 return &_iram_text_end;
27 }
28
esp_memprot_dram0_get_def_split_addr(void)29 static void *esp_memprot_dram0_get_def_split_addr(void)
30 {
31 return MAP_IRAM_TO_DRAM(&_iram_text_end);
32 }
33
esp_memprot_rtcfast_get_min_split_addr(void)34 static void *esp_memprot_rtcfast_get_min_split_addr(void)
35 {
36 return &_rtc_text_end;
37 }
38
esp_mprot_set_split_addr(const esp_mprot_mem_t mem_type,const esp_mprot_split_addr_t line_type,const void * line_addr)39 esp_err_t esp_mprot_set_split_addr(const esp_mprot_mem_t mem_type, const esp_mprot_split_addr_t line_type, const void *line_addr)
40 {
41 switch (mem_type) {
42 case MEMPROT_TYPE_IRAM0_SRAM:
43 switch (line_type) {
44 case MEMPROT_SPLIT_ADDR_IRAM0_DRAM0:
45 return esp_mprot_ll_err_to_esp_err(memprot_ll_set_iram0_split_line_main_I_D(line_addr));
46 case MEMPROT_SPLIT_ADDR_IRAM0_LINE_0:
47 return esp_mprot_ll_err_to_esp_err(memprot_ll_set_iram0_split_line_I_0(line_addr));
48 case MEMPROT_SPLIT_ADDR_IRAM0_LINE_1:
49 return esp_mprot_ll_err_to_esp_err(memprot_ll_set_iram0_split_line_I_1(line_addr));
50 default:
51 return ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID;
52 } break;
53 case MEMPROT_TYPE_DRAM0_SRAM:
54 switch (line_type) {
55 case MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_0:
56 return esp_mprot_ll_err_to_esp_err(memprot_ll_set_dram0_split_line_D_0(line_addr));
57 case MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_1:
58 return esp_mprot_ll_err_to_esp_err(memprot_ll_set_dram0_split_line_D_1(line_addr));
59 default:
60 return ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID;
61 } break;
62 case MEMPROT_TYPE_IRAM0_RTCFAST:
63 if (line_type == MEMPROT_SPLIT_ADDR_MAIN) {
64 /* so far only WORLD_0 is supported */
65 return esp_mprot_ll_err_to_esp_err(memprot_ll_set_rtcfast_split_line(line_addr, MEMP_LL_WORLD_0));
66 } else {
67 return ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID;
68 }
69 break;
70 default:
71 return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
72 }
73 }
74
esp_mprot_get_split_addr(const esp_mprot_mem_t mem_type,const esp_mprot_split_addr_t line_type,void ** line_addr)75 esp_err_t esp_mprot_get_split_addr(const esp_mprot_mem_t mem_type, const esp_mprot_split_addr_t line_type, void **line_addr)
76 {
77 if (line_addr == NULL) {
78 return ESP_ERR_INVALID_ARG;
79 }
80
81 switch (mem_type) {
82 case MEMPROT_TYPE_IRAM0_SRAM:
83 switch (line_type) {
84 case MEMPROT_SPLIT_ADDR_IRAM0_DRAM0:
85 *line_addr = memprot_ll_get_iram0_split_line_main_I_D();
86 break;
87 case MEMPROT_SPLIT_ADDR_IRAM0_LINE_0:
88 *line_addr = memprot_ll_get_iram0_split_line_I_0();
89 break;
90 case MEMPROT_SPLIT_ADDR_IRAM0_LINE_1:
91 *line_addr = memprot_ll_get_iram0_split_line_I_1();
92 break;
93 default:
94 return ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID;
95 } break;
96 case MEMPROT_TYPE_DRAM0_SRAM:
97 switch (line_type) {
98 case MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_0:
99 *line_addr = memprot_ll_get_dram0_split_line_D_0();
100 break;
101 case MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_1:
102 *line_addr = memprot_ll_get_dram0_split_line_D_1();
103 break;
104 default:
105 return ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID;
106 } break;
107 case MEMPROT_TYPE_IRAM0_RTCFAST:
108 if (line_type == MEMPROT_SPLIT_ADDR_MAIN) {
109 /* so far only WORLD_0 is supported */
110 return esp_mprot_ll_err_to_esp_err(memprot_ll_get_rtcfast_split_line(MEMP_LL_WORLD_0, line_addr));
111 } else {
112 return ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID;
113 }
114 break;
115 default:
116 return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
117 }
118
119 return ESP_OK;
120 }
121
esp_mprot_get_default_main_split_addr(const esp_mprot_mem_t mem_type,void ** def_split_addr)122 esp_err_t esp_mprot_get_default_main_split_addr(const esp_mprot_mem_t mem_type, void **def_split_addr)
123 {
124 if (def_split_addr == NULL) {
125 return ESP_ERR_INVALID_ARG;
126 }
127
128 switch (mem_type) {
129 case MEMPROT_TYPE_IRAM0_SRAM:
130 *def_split_addr = esp_memprot_iram0_get_def_split_addr();
131 break;
132 case MEMPROT_TYPE_DRAM0_SRAM:
133 *def_split_addr = esp_memprot_dram0_get_def_split_addr();
134 break;
135 case MEMPROT_TYPE_IRAM0_RTCFAST:
136 *def_split_addr = esp_memprot_rtcfast_get_min_split_addr();
137 break;
138 default:
139 return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
140 }
141
142 return ESP_OK;
143 }
144
esp_mprot_set_split_addr_lock(const esp_mprot_mem_t mem_type)145 esp_err_t esp_mprot_set_split_addr_lock(const esp_mprot_mem_t mem_type)
146 {
147 switch (mem_type) {
148 case MEMPROT_TYPE_IRAM0_SRAM:
149 case MEMPROT_TYPE_DRAM0_SRAM:
150 memprot_ll_set_iram0_dram0_split_line_lock();
151 break;
152 case MEMPROT_TYPE_IRAM0_RTCFAST:
153 //caution: RTCFAST shares the lock with other PIF PMS constraints!
154 memprot_ll_set_pif_constraint_lock();
155 break;
156 default:
157 return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
158 }
159
160 return ESP_OK;
161 }
162
esp_mprot_get_split_addr_lock(const esp_mprot_mem_t mem_type,bool * locked)163 esp_err_t esp_mprot_get_split_addr_lock(const esp_mprot_mem_t mem_type, bool *locked)
164 {
165 if (locked == NULL) {
166 return ESP_ERR_INVALID_ARG;
167 }
168
169 switch (mem_type) {
170 case MEMPROT_TYPE_IRAM0_SRAM:
171 case MEMPROT_TYPE_DRAM0_SRAM:
172 *locked = memprot_ll_get_iram0_dram0_split_line_lock();
173 break;
174 case MEMPROT_TYPE_IRAM0_RTCFAST:
175 *locked = memprot_ll_get_pif_constraint_lock();
176 break;
177 default:
178 return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
179 }
180
181 return ESP_OK;
182 }
183
esp_mprot_set_pms_lock(const esp_mprot_mem_t mem_type)184 esp_err_t esp_mprot_set_pms_lock(const esp_mprot_mem_t mem_type)
185 {
186 switch (mem_type) {
187 case MEMPROT_TYPE_IRAM0_SRAM:
188 memprot_ll_iram0_set_pms_lock();
189 break;
190 case MEMPROT_TYPE_DRAM0_SRAM:
191 memprot_ll_dram0_set_pms_lock();
192 break;
193 case MEMPROT_TYPE_IRAM0_RTCFAST:
194 //caution: RTCFAST shares the lock with other PIF PMS constraints!
195 memprot_ll_set_pif_constraint_lock();
196 break;
197 default:
198 return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
199 }
200
201 return ESP_OK;
202 }
203
esp_mprot_get_pms_lock(const esp_mprot_mem_t mem_type,bool * locked)204 esp_err_t esp_mprot_get_pms_lock(const esp_mprot_mem_t mem_type, bool *locked)
205 {
206 if (locked == NULL) {
207 return ESP_ERR_INVALID_ARG;
208 }
209
210 switch (mem_type) {
211 case MEMPROT_TYPE_IRAM0_SRAM:
212 *locked = memprot_ll_iram0_get_pms_lock();
213 break;
214 case MEMPROT_TYPE_DRAM0_SRAM:
215 *locked = memprot_ll_dram0_get_pms_lock();
216 break;
217 case MEMPROT_TYPE_IRAM0_RTCFAST:
218 *locked = memprot_ll_get_pif_constraint_lock();
219 break;
220 default:
221 return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
222 }
223
224 return ESP_OK;
225 }
226
esp_mprot_set_pms_area(const esp_mprot_pms_area_t area_type,const uint32_t flags)227 esp_err_t esp_mprot_set_pms_area(const esp_mprot_pms_area_t area_type, const uint32_t flags)
228 {
229 bool r = flags & MEMPROT_OP_READ;
230 bool w = flags & MEMPROT_OP_WRITE;
231 bool x = flags & MEMPROT_OP_EXEC;
232
233 switch (area_type) {
234 case MEMPROT_PMS_AREA_IRAM0_0:
235 memprot_ll_iram0_set_pms_area_0(r, w, x);
236 break;
237 case MEMPROT_PMS_AREA_IRAM0_1:
238 memprot_ll_iram0_set_pms_area_1(r, w, x);
239 break;
240 case MEMPROT_PMS_AREA_IRAM0_2:
241 memprot_ll_iram0_set_pms_area_2(r, w, x);
242 break;
243 case MEMPROT_PMS_AREA_IRAM0_3:
244 memprot_ll_iram0_set_pms_area_3(r, w, x);
245 break;
246 case MEMPROT_PMS_AREA_DRAM0_0:
247 memprot_ll_dram0_set_pms_area_0(r, w);
248 break;
249 case MEMPROT_PMS_AREA_DRAM0_1:
250 memprot_ll_dram0_set_pms_area_1(r, w);
251 break;
252 case MEMPROT_PMS_AREA_DRAM0_2:
253 memprot_ll_dram0_set_pms_area_2(r, w);
254 break;
255 case MEMPROT_PMS_AREA_DRAM0_3:
256 memprot_ll_dram0_set_pms_area_3(r, w);
257 break;
258 case MEMPROT_PMS_AREA_IRAM0_RTCFAST_LO:
259 memprot_ll_rtcfast_set_pms_area(r, w, x, MEMP_LL_WORLD_0, MEMP_LL_AREA_LOW);
260 break;
261 case MEMPROT_PMS_AREA_IRAM0_RTCFAST_HI:
262 memprot_ll_rtcfast_set_pms_area(r, w, x, MEMP_LL_WORLD_0, MEMP_LL_AREA_HIGH);
263 break;
264 default:
265 return ESP_ERR_NOT_SUPPORTED;
266 }
267
268 return ESP_OK;
269 }
270
esp_mprot_get_pms_area(const esp_mprot_pms_area_t area_type,uint32_t * flags)271 esp_err_t esp_mprot_get_pms_area(const esp_mprot_pms_area_t area_type, uint32_t *flags)
272 {
273 if (flags == NULL) {
274 return ESP_ERR_INVALID_ARG;
275 }
276
277 bool r = false;
278 bool w = false;
279 bool x = false;
280
281 switch (area_type) {
282 case MEMPROT_PMS_AREA_IRAM0_0:
283 memprot_ll_iram0_get_pms_area_0(&r, &w, &x);
284 break;
285 case MEMPROT_PMS_AREA_IRAM0_1:
286 memprot_ll_iram0_get_pms_area_1(&r, &w, &x);
287 break;
288 case MEMPROT_PMS_AREA_IRAM0_2:
289 memprot_ll_iram0_get_pms_area_2(&r, &w, &x);
290 break;
291 case MEMPROT_PMS_AREA_IRAM0_3:
292 memprot_ll_iram0_get_pms_area_3(&r, &w, &x);
293 break;
294 case MEMPROT_PMS_AREA_DRAM0_0:
295 memprot_ll_dram0_get_pms_area_0(&r, &w);
296 break;
297 case MEMPROT_PMS_AREA_DRAM0_1:
298 memprot_ll_dram0_get_pms_area_1(&r, &w);
299 break;
300 case MEMPROT_PMS_AREA_DRAM0_2:
301 memprot_ll_dram0_get_pms_area_2(&r, &w);
302 break;
303 case MEMPROT_PMS_AREA_DRAM0_3:
304 memprot_ll_dram0_get_pms_area_3(&r, &w);
305 break;
306 case MEMPROT_PMS_AREA_IRAM0_RTCFAST_LO:
307 memprot_ll_rtcfast_get_pms_area(&r, &w, &x, MEMP_LL_WORLD_0, MEMP_LL_AREA_LOW);
308 break;
309 case MEMPROT_PMS_AREA_IRAM0_RTCFAST_HI:
310 memprot_ll_rtcfast_get_pms_area(&r, &w, &x, MEMP_LL_WORLD_0, MEMP_LL_AREA_HIGH);
311 break;
312 default:
313 return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
314 }
315
316 *flags = 0;
317 if (r) {
318 *flags |= MEMPROT_OP_READ;
319 }
320 if (w) {
321 *flags |= MEMPROT_OP_WRITE;
322 }
323 if (x) {
324 *flags |= MEMPROT_OP_EXEC;
325 }
326
327 return ESP_OK;
328 }
329
esp_mprot_set_monitor_lock(const esp_mprot_mem_t mem_type)330 esp_err_t esp_mprot_set_monitor_lock(const esp_mprot_mem_t mem_type)
331 {
332 switch (mem_type) {
333 case MEMPROT_TYPE_IRAM0_SRAM:
334 memprot_ll_iram0_set_monitor_lock();
335 break;
336 case MEMPROT_TYPE_DRAM0_SRAM:
337 memprot_ll_dram0_set_monitor_lock();
338 break;
339 case MEMPROT_TYPE_IRAM0_RTCFAST:
340 memprot_ll_rtcfast_set_monitor_lock();
341 break;
342 default:
343 return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
344 }
345
346 return ESP_OK;
347 }
348
esp_mprot_get_monitor_lock(const esp_mprot_mem_t mem_type,bool * locked)349 esp_err_t esp_mprot_get_monitor_lock(const esp_mprot_mem_t mem_type, bool *locked)
350 {
351 if (locked == NULL) {
352 return ESP_ERR_INVALID_ARG;
353 }
354
355 switch (mem_type) {
356 case MEMPROT_TYPE_IRAM0_SRAM:
357 *locked = memprot_ll_iram0_get_monitor_lock();
358 break;
359 case MEMPROT_TYPE_DRAM0_SRAM:
360 *locked = memprot_ll_dram0_get_monitor_lock();
361 break;
362 case MEMPROT_TYPE_IRAM0_RTCFAST:
363 *locked = memprot_ll_rtcfast_get_monitor_lock();
364 break;
365 default:
366 return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
367 }
368
369 return ESP_OK;
370 }
371
esp_mprot_set_monitor_en(const esp_mprot_mem_t mem_type,const bool enable)372 esp_err_t esp_mprot_set_monitor_en(const esp_mprot_mem_t mem_type, const bool enable)
373 {
374 switch (mem_type) {
375 case MEMPROT_TYPE_IRAM0_SRAM:
376 memprot_ll_iram0_set_monitor_en(enable);
377 break;
378 case MEMPROT_TYPE_DRAM0_SRAM:
379 memprot_ll_dram0_set_monitor_en(enable);
380 break;
381 case MEMPROT_TYPE_IRAM0_RTCFAST:
382 memprot_ll_rtcfast_set_monitor_en(enable);
383 break;
384 default:
385 return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
386 }
387
388 return ESP_OK;
389 }
390
esp_mprot_get_monitor_en(const esp_mprot_mem_t mem_type,bool * enabled)391 esp_err_t esp_mprot_get_monitor_en(const esp_mprot_mem_t mem_type, bool *enabled)
392 {
393 if (enabled == NULL) {
394 return ESP_ERR_INVALID_ARG;
395 }
396
397 switch (mem_type) {
398 case MEMPROT_TYPE_IRAM0_SRAM:
399 *enabled = memprot_ll_iram0_get_monitor_en();
400 break;
401 case MEMPROT_TYPE_DRAM0_SRAM:
402 *enabled = memprot_ll_dram0_get_monitor_en();
403 break;
404 case MEMPROT_TYPE_IRAM0_RTCFAST:
405 *enabled = memprot_ll_rtcfast_get_monitor_en();
406 break;
407 default:
408 return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
409 }
410
411 return ESP_OK;
412 }
413
esp_mprot_monitor_clear_intr(const esp_mprot_mem_t mem_type,int const * const core)414 esp_err_t IRAM_ATTR esp_mprot_monitor_clear_intr(const esp_mprot_mem_t mem_type, int const *const core __attribute__((unused)))
415 {
416 switch (mem_type) {
417 case MEMPROT_TYPE_IRAM0_SRAM:
418 memprot_ll_iram0_set_monitor_intrclr();
419 memprot_ll_iram0_reset_monitor_intrclr();
420 break;
421 case MEMPROT_TYPE_DRAM0_SRAM:
422 memprot_ll_dram0_set_monitor_intrclr();
423 memprot_ll_dram0_reset_monitor_intrclr();
424 break;
425 case MEMPROT_TYPE_IRAM0_RTCFAST:
426 memprot_ll_rtcfast_set_monitor_intrclr();
427 memprot_ll_rtcfast_reset_monitor_intrclr();
428 break;
429 default:
430 return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
431 }
432
433 return ESP_OK;
434 }
435
esp_mprot_get_active_intr(esp_memp_intr_source_t * active_memp_intr)436 esp_err_t IRAM_ATTR esp_mprot_get_active_intr(esp_memp_intr_source_t *active_memp_intr)
437 {
438 if (active_memp_intr == NULL) {
439 return ESP_ERR_INVALID_ARG;
440 }
441
442 active_memp_intr->core = PRO_CPU_NUM;
443
444 if (memprot_ll_iram0_get_monitor_status_intr() > 0) {
445 active_memp_intr->mem_type = MEMPROT_TYPE_IRAM0_SRAM;
446 } else if (memprot_ll_dram0_get_monitor_status_intr() > 0) {
447 active_memp_intr->mem_type = MEMPROT_TYPE_DRAM0_SRAM;
448 } else if (memprot_ll_rtcfast_get_monitor_status_intr() > 0) {
449 active_memp_intr->mem_type = MEMPROT_TYPE_IRAM0_RTCFAST;
450 } else {
451 active_memp_intr->mem_type = MEMPROT_TYPE_NONE;
452 }
453
454 return ESP_OK;
455 }
456
esp_mprot_is_conf_locked_any(bool * locked)457 esp_err_t IRAM_ATTR esp_mprot_is_conf_locked_any(bool *locked)
458 {
459 if (locked == NULL) {
460 return ESP_ERR_INVALID_ARG;
461 }
462
463 bool lock_on = false;
464 esp_err_t res;
465
466 ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_split_addr_lock(MEMPROT_TYPE_IRAM0_SRAM, &lock_on))
467 *locked |= lock_on;
468 ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_split_addr_lock(MEMPROT_TYPE_DRAM0_SRAM, &lock_on))
469 *locked |= lock_on;
470 ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_pms_lock(MEMPROT_TYPE_IRAM0_SRAM, &lock_on))
471 *locked |= lock_on;
472 ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_pms_lock(MEMPROT_TYPE_DRAM0_SRAM, &lock_on))
473 *locked |= lock_on;
474 ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_monitor_lock(MEMPROT_TYPE_IRAM0_SRAM, &lock_on))
475 *locked |= lock_on;
476 ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_monitor_lock(MEMPROT_TYPE_DRAM0_SRAM, &lock_on));
477 *locked |= lock_on;
478 ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_monitor_lock(MEMPROT_TYPE_IRAM0_RTCFAST, &lock_on));
479 *locked |= lock_on;
480
481 return ESP_OK;
482 }
483
esp_mprot_is_intr_ena_any(bool * enabled)484 esp_err_t IRAM_ATTR esp_mprot_is_intr_ena_any(bool *enabled)
485 {
486 if (enabled == NULL) {
487 return ESP_ERR_INVALID_ARG;
488 }
489
490 bool ena_on = false;
491 esp_err_t res;
492
493 ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_monitor_en(MEMPROT_TYPE_IRAM0_SRAM, &ena_on))
494 *enabled |= ena_on;
495 ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_monitor_en(MEMPROT_TYPE_DRAM0_SRAM, &ena_on))
496 *enabled |= ena_on;
497 ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_monitor_en(MEMPROT_TYPE_IRAM0_RTCFAST, &ena_on))
498 *enabled |= ena_on;
499
500 return ESP_OK;
501 }
502
esp_mprot_get_violate_addr(const esp_mprot_mem_t mem_type,void ** fault_addr,int const * const core)503 esp_err_t IRAM_ATTR esp_mprot_get_violate_addr(const esp_mprot_mem_t mem_type, void **fault_addr, int const *const core __attribute__((unused)))
504 {
505 if (fault_addr == NULL) {
506 return ESP_ERR_INVALID_ARG;
507 }
508
509 switch (mem_type) {
510 case MEMPROT_TYPE_IRAM0_SRAM:
511 *fault_addr = (void *)memprot_ll_iram0_get_monitor_status_fault_addr();
512 break;
513 case MEMPROT_TYPE_DRAM0_SRAM:
514 *fault_addr = (void *)memprot_ll_dram0_get_monitor_status_fault_addr();
515 break;
516 case MEMPROT_TYPE_IRAM0_RTCFAST:
517 *fault_addr = (void *)memprot_ll_rtcfast_get_monitor_status_fault_addr();
518 break;
519 default:
520 return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
521 }
522
523 return ESP_OK;
524 }
525
esp_mprot_get_violate_world(const esp_mprot_mem_t mem_type,esp_mprot_pms_world_t * world,int const * const core)526 esp_err_t IRAM_ATTR esp_mprot_get_violate_world(const esp_mprot_mem_t mem_type, esp_mprot_pms_world_t *world, int const *const core __attribute__((unused)))
527 {
528 if (world == NULL) {
529 return ESP_ERR_INVALID_ARG;
530 }
531
532 esp_mprot_pms_world_t res;
533 switch (mem_type) {
534 case MEMPROT_TYPE_IRAM0_SRAM:
535 res = esp_mprot_ll_world_to_hl_world(memprot_ll_iram0_get_monitor_status_fault_world());
536 break;
537 case MEMPROT_TYPE_DRAM0_SRAM:
538 res = esp_mprot_ll_world_to_hl_world(memprot_ll_dram0_get_monitor_status_fault_world());
539 break;
540 case MEMPROT_TYPE_IRAM0_RTCFAST:
541 res = esp_mprot_ll_world_to_hl_world(memprot_ll_rtcfast_get_monitor_status_fault_world());
542 break;
543 default:
544 return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
545 }
546
547 if (res == MEMPROT_PMS_WORLD_INVALID) {
548 return ESP_ERR_MEMPROT_WORLD_INVALID;
549 }
550
551 *world = res;
552
553 return ESP_OK;
554 }
555
esp_mprot_get_violate_operation(const esp_mprot_mem_t mem_type,uint32_t * oper,int const * const core)556 esp_err_t IRAM_ATTR esp_mprot_get_violate_operation(const esp_mprot_mem_t mem_type, uint32_t *oper, int const *const core __attribute__((unused)))
557 {
558 if (oper == NULL) {
559 return ESP_ERR_INVALID_ARG;
560 }
561
562 uint32_t operation = MEMPROT_OP_NONE;
563
564 if ((mem_type == MEMPROT_TYPE_IRAM0_SRAM && memprot_ll_iram0_get_monitor_status_fault_loadstore() == 0) ||
565 (mem_type == MEMPROT_TYPE_IRAM0_RTCFAST && memprot_ll_rtcfast_get_monitor_status_fault_loadstore() == 0)) {
566 operation = MEMPROT_OP_EXEC;
567 }
568
569 if (operation == MEMPROT_OP_NONE) {
570 switch (mem_type) {
571 case MEMPROT_TYPE_IRAM0_SRAM:
572 operation = memprot_ll_iram0_get_monitor_status_fault_wr() == 1 ? MEMPROT_OP_WRITE : MEMPROT_OP_READ;
573 break;
574 case MEMPROT_TYPE_DRAM0_SRAM:
575 operation = memprot_ll_dram0_get_monitor_status_fault_wr() == 1 ? MEMPROT_OP_WRITE : MEMPROT_OP_READ;
576 break;
577 case MEMPROT_TYPE_IRAM0_RTCFAST:
578 operation = memprot_ll_rtcfast_get_monitor_status_fault_wr() == 1 ? MEMPROT_OP_WRITE : MEMPROT_OP_READ;
579 break;
580 default:
581 return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
582 }
583 }
584
585 *oper = operation;
586
587 return ESP_OK;
588 }
589
esp_mprot_has_byte_enables(const esp_mprot_mem_t mem_type)590 bool IRAM_ATTR esp_mprot_has_byte_enables(const esp_mprot_mem_t mem_type)
591 {
592 return mem_type == MEMPROT_TYPE_DRAM0_SRAM;
593 }
594
esp_mprot_get_violate_byte_enables(const esp_mprot_mem_t mem_type,uint32_t * byte_en,int const * const core)595 esp_err_t IRAM_ATTR esp_mprot_get_violate_byte_enables(const esp_mprot_mem_t mem_type, uint32_t *byte_en, int const *const core __attribute__((unused)))
596 {
597 if (byte_en == NULL) {
598 return ESP_ERR_INVALID_ARG;
599 }
600
601 switch (mem_type) {
602 case MEMPROT_TYPE_DRAM0_SRAM:
603 *byte_en = memprot_ll_dram0_get_monitor_status_fault_byte_en();
604 break;
605 default:
606 return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
607 }
608
609 return ESP_OK;
610 }
611
612 /* internal */
esp_mprot_set_intr_matrix(const esp_mprot_mem_t mem_type)613 static esp_err_t esp_mprot_set_intr_matrix(const esp_mprot_mem_t mem_type)
614 {
615 ESP_INTR_DISABLE(ETS_MEMPROT_ERR_INUM);
616
617 switch (mem_type) {
618 case MEMPROT_TYPE_IRAM0_SRAM:
619 intr_matrix_set(PRO_CPU_NUM, memprot_ll_iram0_get_intr_source_num(), ETS_MEMPROT_ERR_INUM);
620 break;
621 case MEMPROT_TYPE_DRAM0_SRAM:
622 intr_matrix_set(PRO_CPU_NUM, memprot_ll_dram0_get_intr_source_num(), ETS_MEMPROT_ERR_INUM);
623 break;
624 case MEMPROT_TYPE_IRAM0_RTCFAST:
625 intr_matrix_set(PRO_CPU_NUM, memprot_ll_rtcfast_get_intr_source_num(), ETS_MEMPROT_ERR_INUM);
626 break;
627 default:
628 return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
629 }
630
631 /* Set the type and priority to cache error interrupts. */
632 esprv_intc_int_set_type(BIT(ETS_MEMPROT_ERR_INUM), INTR_TYPE_LEVEL);
633 esprv_intc_int_set_priority(ETS_MEMPROT_ERR_INUM, SOC_INTERRUPT_LEVEL_MEDIUM);
634
635 ESP_INTR_ENABLE(ETS_MEMPROT_ERR_INUM);
636
637 return ESP_OK;
638 }
639
esp_mprot_set_prot(const esp_memp_config_t * memp_config)640 esp_err_t esp_mprot_set_prot(const esp_memp_config_t *memp_config)
641 {
642 if (memp_config == NULL) {
643 return ESP_ERR_INVALID_ARG;
644 }
645 if (memp_config->mem_type_mask == MEMPROT_TYPE_NONE) {
646 return ESP_ERR_NO_MEM;
647 }
648
649 //debugger connected:
650 // 1.check the signal repeatedly to avoid possible glitching attempt
651 // 2.leave the Memprot unset to allow debug operations
652 if (esp_cpu_in_ocd_debug_mode()) {
653 ESP_FAULT_ASSERT(esp_cpu_in_ocd_debug_mode());
654 return ESP_OK;
655 }
656
657 bool use_iram0 = memp_config->mem_type_mask & MEMPROT_TYPE_IRAM0_SRAM;
658 bool use_dram0 = memp_config->mem_type_mask & MEMPROT_TYPE_DRAM0_SRAM;
659 bool use_rtcfast = memp_config->mem_type_mask & MEMPROT_TYPE_IRAM0_RTCFAST;
660 esp_err_t ret = ESP_OK;
661
662 //disable protection (must be unlocked)
663 if (use_iram0) {
664 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_IRAM0_SRAM, false))
665 }
666 if (use_dram0) {
667 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_DRAM0_SRAM, false))
668 }
669 if (use_rtcfast) {
670 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_IRAM0_RTCFAST, false))
671 }
672
673 //panic handling
674 if (memp_config->invoke_panic_handler) {
675 if (use_iram0) {
676 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_intr_matrix(MEMPROT_TYPE_IRAM0_SRAM))
677 }
678 if (use_dram0) {
679 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_intr_matrix(MEMPROT_TYPE_DRAM0_SRAM))
680 }
681 if (use_rtcfast) {
682 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_intr_matrix(MEMPROT_TYPE_IRAM0_RTCFAST))
683 }
684 }
685
686 //set split lines (must-have for all mem_types). This version sets only the main I/D which is then shared for all PMS regions
687 void *line_addr = memp_config->split_addr;
688 if (line_addr == NULL) {
689 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_get_default_main_split_addr(MEMPROT_TYPE_IRAM0_SRAM, &line_addr))
690 }
691
692 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr(MEMPROT_TYPE_IRAM0_SRAM, MEMPROT_SPLIT_ADDR_IRAM0_LINE_1, line_addr))
693 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr(MEMPROT_TYPE_IRAM0_SRAM, MEMPROT_SPLIT_ADDR_IRAM0_LINE_0, line_addr))
694 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr(MEMPROT_TYPE_IRAM0_SRAM, MEMPROT_SPLIT_ADDR_IRAM0_DRAM0, line_addr))
695 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr(MEMPROT_TYPE_DRAM0_SRAM, MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_0, (void *)(MAP_IRAM_TO_DRAM((uint32_t)line_addr))))
696 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr(MEMPROT_TYPE_DRAM0_SRAM, MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_1, (void *)(MAP_IRAM_TO_DRAM((uint32_t)line_addr))))
697
698 //set permissions
699 if (use_iram0) {
700 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_0, MEMPROT_OP_READ | MEMPROT_OP_EXEC))
701 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_1, MEMPROT_OP_READ | MEMPROT_OP_EXEC))
702 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_2, MEMPROT_OP_READ | MEMPROT_OP_EXEC))
703 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_3, MEMPROT_OP_NONE))
704 }
705 if (use_dram0) {
706 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_0, MEMPROT_OP_NONE ))
707 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_1, MEMPROT_OP_READ | MEMPROT_OP_WRITE))
708 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_2, MEMPROT_OP_READ | MEMPROT_OP_WRITE))
709 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_3, MEMPROT_OP_READ | MEMPROT_OP_WRITE))
710 }
711 if (use_rtcfast) {
712 //RTCFAST split-line cannot be set manually - always use default
713 void *rtc_fast_line;
714 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_get_default_main_split_addr(MEMPROT_TYPE_IRAM0_RTCFAST, &rtc_fast_line));
715 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr(MEMPROT_TYPE_IRAM0_RTCFAST, MEMPROT_SPLIT_ADDR_MAIN, rtc_fast_line))
716 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_RTCFAST_LO, MEMPROT_OP_READ | MEMPROT_OP_EXEC))
717 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_RTCFAST_HI, MEMPROT_OP_READ | MEMPROT_OP_WRITE))
718 }
719
720 //reenable the protection
721 if (use_iram0) {
722 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_monitor_clear_intr(MEMPROT_TYPE_IRAM0_SRAM, NULL))
723 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_IRAM0_SRAM, true))
724 }
725 if (use_dram0) {
726 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_monitor_clear_intr(MEMPROT_TYPE_DRAM0_SRAM, NULL))
727 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_DRAM0_SRAM, true))
728 }
729 if (use_rtcfast) {
730 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_monitor_clear_intr(MEMPROT_TYPE_IRAM0_RTCFAST, NULL))
731 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_IRAM0_RTCFAST, true))
732 }
733
734 //lock if required
735 if (memp_config->lock_feature) {
736 if (use_iram0) {
737 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr_lock(MEMPROT_TYPE_IRAM0_SRAM))
738 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_lock(MEMPROT_TYPE_IRAM0_SRAM))
739 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_lock(MEMPROT_TYPE_IRAM0_SRAM))
740 }
741 if (use_dram0) {
742 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr_lock(MEMPROT_TYPE_DRAM0_SRAM))
743 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_lock(MEMPROT_TYPE_DRAM0_SRAM))
744 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_lock(MEMPROT_TYPE_DRAM0_SRAM))
745 }
746 if (use_rtcfast) {
747 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr_lock(MEMPROT_TYPE_IRAM0_RTCFAST))
748 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_lock(MEMPROT_TYPE_IRAM0_RTCFAST))
749 ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_lock(MEMPROT_TYPE_IRAM0_RTCFAST))
750 }
751 }
752
753 return ret;
754 }
755
esp_mprot_dump_configuration(char ** dump_info_string)756 esp_err_t esp_mprot_dump_configuration(char **dump_info_string)
757 {
758 if (dump_info_string == NULL) {
759 return ESP_ERR_INVALID_ARG;;
760 }
761
762 *dump_info_string = calloc(1024, 1);
763
764 if (*dump_info_string == NULL) {
765 return ESP_ERR_NO_MEM;
766 }
767
768 bool line_lock = memprot_ll_get_iram0_dram0_split_line_lock();
769 uint32_t line_ID = (uint32_t)memprot_ll_get_iram0_split_line_main_I_D();
770 uint32_t line_I0 = (uint32_t)memprot_ll_get_iram0_split_line_I_0();
771 uint32_t line_I1 = (uint32_t)memprot_ll_get_iram0_split_line_I_1();
772 uint32_t line_D0 = (uint32_t)memprot_ll_get_dram0_split_line_D_0();
773 uint32_t line_D1 = (uint32_t)memprot_ll_get_dram0_split_line_D_1();
774 uint32_t line_ID_cat = (uint32_t)memprot_ll_get_iram0_split_line_main_I_D_cat();
775 uint32_t line_I0_cat = (uint32_t)memprot_ll_get_iram0_split_line_I_0_cat();
776 uint32_t line_I1_cat = (uint32_t)memprot_ll_get_iram0_split_line_I_1_cat();
777 uint32_t line_D0_cat = (uint32_t)memprot_ll_get_dram0_split_line_D_0_cat();
778 uint32_t line_D1_cat = (uint32_t)memprot_ll_get_dram0_split_line_D_1_cat();
779
780 sprintf(*dump_info_string,
781 "Split line settings (lock=%u):\n"
782 " IRAM0:\n line ID (main): 0x%08X (cat=0x%08X)\n line I0: 0x%08X (cat=0x%08X)\n line I1: 0x%08X (cat=0x%08X)\n"
783 " DRAM0:\n line D0: 0x%08X (cat=0x%08X)\n line D1: 0x%08X (cat=0x%08X)\n",
784 line_lock, line_ID, line_ID_cat, line_I0, line_I0_cat, line_I1, line_I1_cat, line_D0, line_D0_cat, line_D1, line_D1_cat);
785
786 uint32_t offset = strlen(*dump_info_string);
787
788 void *line_RTC = NULL;
789 esp_err_t err = esp_mprot_ll_err_to_esp_err(memprot_ll_get_rtcfast_split_line(MEMP_LL_WORLD_0, &line_RTC));
790 if (err != ESP_OK) {
791 sprintf((*dump_info_string + offset), " RTCFAST:\n line main: N/A (world=0) - %s\n", esp_err_to_name(err));
792 } else {
793 sprintf((*dump_info_string + offset), " RTCFAST:\n line main: 0x%08X (world=0)\n", (uint32_t)line_RTC);
794 }
795
796 offset = strlen(*dump_info_string);
797
798 bool ar0i, ar1i, ar2i, ar3i;
799 bool aw0i, aw1i, aw2i, aw3i;
800 bool ax0i, ax1i, ax2i, ax3i;
801 bool ar0d, ar1d, ar2d, ar3d;
802 bool aw0d, aw1d, aw2d, aw3d;
803
804 bool pms_lock_i = memprot_ll_iram0_get_pms_lock();
805 memprot_ll_iram0_get_pms_area_0(&ar0i, &aw0i, &ax0i);
806 memprot_ll_iram0_get_pms_area_1(&ar1i, &aw1i, &ax1i);
807 memprot_ll_iram0_get_pms_area_2(&ar2i, &aw2i, &ax2i);
808 memprot_ll_iram0_get_pms_area_3(&ar3i, &aw3i, &ax3i);
809
810 bool pms_lock_d = memprot_ll_dram0_get_pms_lock();
811 memprot_ll_dram0_get_pms_area_0(&ar0d, &aw0d);
812 memprot_ll_dram0_get_pms_area_1(&ar1d, &aw1d);
813 memprot_ll_dram0_get_pms_area_2(&ar2d, &aw2d);
814 memprot_ll_dram0_get_pms_area_3(&ar3d, &aw3d);
815
816 bool rtc_line_lock = memprot_ll_get_pif_constraint_lock();
817
818 sprintf((*dump_info_string + offset),
819 "PMS area settings:\n"
820 " IRAM0 (lock=%u):\n area 0: r=%u,w=%u,x=%u\n area 1: r=%u,w=%u,x=%u\n area 2: r=%u,w=%u,x=%u\n area 3: r=%u,w=%u,x=%u\n"
821 " DRAM0 (lock=%u):\n area 0: r=%u,w=%u\n area 1: r=%u,w=%u\n area 2: r=%u,w=%u\n area 3: r=%u,w=%u\n"
822 " RTCFAST (lock=%u):\n",
823 pms_lock_i, ar0i, aw0i, ax0i, ar1i, aw1i, ax1i, ar2i, aw2i, ax2i, ar3i, aw3i, ax3i,
824 pms_lock_d, ar0d, aw0d, ar1d, aw1d, ar2d, aw2d, ar3d, aw3d, rtc_line_lock);
825
826 offset = strlen(*dump_info_string);
827
828 bool arl0rtc, awl0rtc, axl0rtc;
829 bool arh0rtc, awh0rtc, axh0rtc;
830
831 err = esp_mprot_ll_err_to_esp_err(memprot_ll_rtcfast_get_pms_area(&arl0rtc, &awl0rtc, &axl0rtc, MEMP_LL_WORLD_0, MEMP_LL_AREA_LOW));
832 if (err != ESP_OK) {
833 sprintf((*dump_info_string + offset), " area low: N/A - %s\n", esp_err_to_name(err));
834 } else {
835 sprintf((*dump_info_string + offset), " area low: r=%u,w=%u,x=%u\n", arl0rtc, awl0rtc, axl0rtc);
836 }
837
838 offset = strlen(*dump_info_string);
839
840 err = esp_mprot_ll_err_to_esp_err(memprot_ll_rtcfast_get_pms_area(&arh0rtc, &awh0rtc, &axh0rtc, MEMP_LL_WORLD_0, MEMP_LL_AREA_HIGH));
841 if (err != ESP_OK) {
842 sprintf((*dump_info_string + offset), " area high: N/A - %s\n", esp_err_to_name(err));
843 } else {
844 sprintf((*dump_info_string + offset), " area high: r=%u,w=%u,x=%u\n", arh0rtc, awh0rtc, axh0rtc);
845 }
846
847 offset = strlen(*dump_info_string);
848
849 bool monitor_lock_i = memprot_ll_iram0_get_monitor_lock();
850 bool monitor_en_i = memprot_ll_iram0_get_monitor_en();
851 bool monitor_clr_i = memprot_ll_iram0_get_monitor_intrclr();
852 bool monitor_lock_d = memprot_ll_dram0_get_monitor_lock();
853 bool monitor_en_d = memprot_ll_dram0_get_monitor_en();
854 bool monitor_clr_d = memprot_ll_dram0_get_monitor_intrclr();
855 bool monitor_lock_rtc = memprot_ll_rtcfast_get_monitor_lock();
856 bool monitor_en_rtc = memprot_ll_rtcfast_get_monitor_en();
857 bool monitor_clr_rtc = memprot_ll_rtcfast_get_monitor_intrclr();
858
859 sprintf((*dump_info_string + offset),
860 "Monitor settings:\n"
861 " IRAM0 (lock=%u):\n enabled=%u\n intr_clr=%u\n"
862 " DRAM0 (lock=%u):\n enabled=%u\n intr_clr=%u\n"
863 " RTCFAST (lock=%u):\n enabled=%u\n intr_clr=%u\n",
864 monitor_lock_i, monitor_en_i, monitor_clr_i,
865 monitor_lock_d, monitor_en_d, monitor_clr_d,
866 monitor_lock_rtc, monitor_en_rtc, monitor_clr_rtc);
867
868 return ESP_OK;
869 }
870