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