1 /*
2  * Copyright (c) 2020-2022, Arm Limited. All rights reserved.
3  * Copyright (c) 2022 Cypress Semiconductor Corporation (an Infineon
4  * company) or an affiliate of Cypress Semiconductor Corporation. All rights
5  * reserved.
6  *
7  * SPDX-License-Identifier: BSD-3-Clause
8  *
9  */
10 
11 #include <arm_cmse.h>
12 #include <stddef.h>
13 #include <stdint.h>
14 #include <string.h>
15 #include "array.h"
16 #include "cmsis.h"
17 #include "Driver_Common.h"
18 #include "mmio_defs.h"
19 #include "mpu_armv8m_drv.h"
20 #include "region.h"
21 #include "target_cfg.h"
22 #include "tfm_hal_defs.h"
23 #include "tfm_hal_isolation.h"
24 #include "tfm_plat_defs.h"
25 #include "region_defs.h"
26 #include "tfm_peripherals_def.h"
27 #include "load/partition_defs.h"
28 #include "load/asset_defs.h"
29 #include "load/spm_load_api.h"
30 
31 #ifdef FLOW_CONTROL
32 #include "target_flowcontrol.h"
33 #else
34 /* dummy definitions */
35 extern volatile uint32_t uFlowStage;
36 #define FLOW_CONTROL_STEP(C,B,A) ((void)0)
37 #define FLOW_CONTROL_CHECK(B,A) ((void)0)
38 #define FLOW_STAGE_CFG          (0x0)
39 #define FLOW_STAGE_CHK          (0x1)
40 #endif
41 
42 /* It can be retrieved from the MPU_TYPE register. */
43 #define MPU_REGION_NUM                  8
44 #define PROT_BOUNDARY_VAL \
45     ((1U << HANDLE_ATTR_PRIV_POS) & HANDLE_ATTR_PRIV_MASK)
46 
47 #ifdef CONFIG_TFM_ENABLE_MEMORY_PROTECT
48 static uint32_t n_configured_regions = 0;
49 
50 struct mpu_armv8m_dev_t dev_mpu_s = { MPU_BASE };
51 REGION_DECLARE(Image$$, TFM_UNPRIV_CODE, $$RO$$Base);
52 REGION_DECLARE(Image$$, TFM_UNPRIV_CODE, $$RO$$Limit);
53 REGION_DECLARE(Image$$, TFM_UNPRIV_DATA, $$RW$$Base);
54 REGION_DECLARE(Image$$, TFM_UNPRIV_DATA, $$ZI$$Limit);
55 
56 REGION_DECLARE(Image$$, TFM_APP_RW_STACK_START, $$Base);
57 REGION_DECLARE(Image$$, TFM_APP_RW_STACK_END, $$Base);
58 
59 REGION_DECLARE(Image$$, ER_VENEER, $$Limit);
60 
61 const struct mpu_armv8m_region_cfg_t region_cfg[] = {
62     /* TFM Core unprivileged code region */
63     {
64         0, /* will be updated before using */
65         (uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_CODE, $$RO$$Base),
66         FLASH_BASE_S + FLASH_AREA_0_OFFSET + FLASH_AREA_0_SIZE - 32,
67         MPU_ARMV8M_MAIR_ATTR_CODE_IDX,
68         MPU_ARMV8M_XN_EXEC_OK,
69         MPU_ARMV8M_AP_RO_PRIV_UNPRIV,
70         MPU_ARMV8M_SH_NONE,
71 #ifdef FLOW_CONTROL
72         FLOW_STEP_MPU_S_EN_R0,
73         FLOW_CTRL_MPU_S_EN_R0,
74         FLOW_STEP_MPU_S_CH_R0,
75         FLOW_CTRL_MPU_S_CH_R0,
76 #endif /* FLOW_CONTROL */
77     },
78     /* TFM_Core privileged code region   */
79     {
80         0, /* will be updated before using */
81         S_CODE_START,
82         (uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_CODE, $$RO$$Base),
83         MPU_ARMV8M_MAIR_ATTR_CODE_IDX,
84         MPU_ARMV8M_XN_EXEC_OK,
85         MPU_ARMV8M_AP_RO_PRIV_ONLY,
86         MPU_ARMV8M_SH_NONE,
87 #ifdef FLOW_CONTROL
88         FLOW_STEP_MPU_S_EN_R2,
89         FLOW_CTRL_MPU_S_EN_R2,
90         FLOW_STEP_MPU_S_CH_R2,
91         FLOW_CTRL_MPU_S_CH_R2,
92 #endif /* FLOW_CONTROL */
93     },
94     {
95       0, /* will be updated before using */
96         (uint32_t)&REGION_NAME(Image$$, TFM_APP_RW_STACK_START, $$Base),
97         (uint32_t)&REGION_NAME(Image$$, TFM_APP_RW_STACK_END, $$Base),
98         MPU_ARMV8M_MAIR_ATTR_DATA_IDX,
99         MPU_ARMV8M_XN_EXEC_NEVER,
100         MPU_ARMV8M_AP_RW_PRIV_UNPRIV,
101         MPU_ARMV8M_SH_NONE,
102 #ifdef FLOW_CONTROL
103         FLOW_STEP_MPU_S_EN_R1,
104         FLOW_CTRL_MPU_S_EN_R1,
105         FLOW_STEP_MPU_S_CH_R1,
106         FLOW_CTRL_MPU_S_CH_R1,
107 #endif /* FLOW_CONTROL */
108     },
109     /* TFM_Core privileged data region   */
110     {
111         0, /* will be updated before using */
112         (uint32_t)&REGION_NAME(Image$$, TFM_APP_RW_STACK_END, $$Base),
113         S_DATA_LIMIT + 1,
114         MPU_ARMV8M_MAIR_ATTR_DATA_IDX,
115         MPU_ARMV8M_XN_EXEC_NEVER,
116         MPU_ARMV8M_AP_RW_PRIV_ONLY,
117         MPU_ARMV8M_SH_NONE,
118 #ifdef FLOW_CONTROL
119         FLOW_STEP_MPU_S_EN_R3,
120         FLOW_CTRL_MPU_S_EN_R3,
121         FLOW_STEP_MPU_S_CH_R3,
122         FLOW_CTRL_MPU_S_CH_R3,
123 #endif /* FLOW_CONTROL */
124     },
125     /* peripheral for AppROT partition */
126     {
127         0, /* will be updated before using */
128         PERIPH_BASE_S,
129         PERIPH_BASE_S+0x10000000,
130         MPU_ARMV8M_MAIR_ATTR_DATANOCACHE_IDX,
131         MPU_ARMV8M_XN_EXEC_NEVER,
132         MPU_ARMV8M_AP_RW_PRIV_UNPRIV,
133         MPU_ARMV8M_SH_NONE,
134 #ifdef FLOW_CONTROL
135         FLOW_STEP_MPU_S_EN_R4,
136         FLOW_CTRL_MPU_S_EN_R4,
137         FLOW_STEP_MPU_S_CH_R4,
138         FLOW_CTRL_MPU_S_CH_R4,
139 #endif /* FLOW_CONTROL */
140     },
141     /* TFM Non volatile data region (OTP/NVM/SST/ITS) */
142     /* OTP is write protected (Option Byte protection) */
143     {
144         0, /* will be updated before using */
145         TFM_NV_DATA_START,
146         TFM_NV_DATA_LIMIT + 1,
147         MPU_ARMV8M_MAIR_ATTR_DATANOCACHE_IDX,
148         MPU_ARMV8M_XN_EXEC_NEVER,
149         MPU_ARMV8M_AP_RW_PRIV_ONLY,
150         MPU_ARMV8M_SH_NONE,
151 #ifdef FLOW_CONTROL
152         FLOW_STEP_MPU_S_EN_R5,
153         FLOW_CTRL_MPU_S_EN_R5,
154         FLOW_STEP_MPU_S_CH_R5,
155         FLOW_CTRL_MPU_S_CH_R5,
156 #endif /* FLOW_CONTROL */
157     },
158     /* RAM Non Secure Alias Not Executable */
159     {
160         0, /* will be updated before using */
161         SRAM1_BASE_NS,
162         SRAM4_BASE_NS + SRAM4_SIZE,
163         MPU_ARMV8M_MAIR_ATTR_DATA_IDX,
164         MPU_ARMV8M_XN_EXEC_NEVER,
165         MPU_ARMV8M_AP_RW_PRIV_ONLY,
166         MPU_ARMV8M_SH_NONE,
167 #ifdef FLOW_CONTROL
168         FLOW_STEP_MPU_S_EN_R6,
169         FLOW_CTRL_MPU_S_EN_R6,
170         FLOW_STEP_MPU_S_CH_R6,
171         FLOW_CTRL_MPU_S_CH_R6,
172 #endif /* FLOW_CONTROL */
173     },
174     /* FLASH Non Secure Alias Not Executable, read only */
175     {
176         0, /* will be updated before using */
177         FLASH_BASE_NS,
178         FLASH_BASE_NS + FLASH_AREA_1_OFFSET + FLASH_AREA_1_SIZE - 32,
179         MPU_ARMV8M_MAIR_ATTR_DATANOCACHE_IDX,
180         MPU_ARMV8M_XN_EXEC_NEVER,
181         MPU_ARMV8M_AP_RO_PRIV_ONLY,
182         MPU_ARMV8M_SH_NONE,
183 #ifdef FLOW_CONTROL
184         FLOW_STEP_MPU_S_EN_R7,
185         FLOW_CTRL_MPU_S_EN_R7,
186         FLOW_STEP_MPU_S_CH_R7,
187         FLOW_CTRL_MPU_S_CH_R7,
188 #endif /* FLOW_CONTROL */
189     },
190 };
191 
mpu_init(void)192 static enum tfm_hal_status_t mpu_init(void)
193 {
194     uint32_t i;
195     struct mpu_armv8m_region_cfg_t localcfg;
196 
197     /* configuration stage */
198     if (uFlowStage == FLOW_STAGE_CFG)
199     {
200         mpu_armv8m_clean(&dev_mpu_s);
201 
202         /* configure secure MPU regions */
203         for (i = 0; i < ARRAY_SIZE(region_cfg); i++)
204         {
205             memcpy(&localcfg, &region_cfg[i], sizeof(localcfg));
206             localcfg.region_nr = i;
207 
208             if (mpu_armv8m_region_enable(&dev_mpu_s,
209                         &localcfg) != MPU_ARMV8M_OK)
210             {
211                 return TFM_HAL_ERROR_GENERIC;
212             }
213             else
214             {
215                 /* Execution stopped if flow control failed */
216                 FLOW_CONTROL_STEP(uFlowProtectValue, localcfg.flow_step_enable,
217                         region_cfg[i].flow_ctrl_enable);
218             }
219         }
220         n_configured_regions = i;
221 
222         /* enable secure MPU */
223         mpu_armv8m_enable(&dev_mpu_s, PRIVILEGED_DEFAULT_ENABLE, HARDFAULT_NMI_ENABLE);
224         FLOW_CONTROL_STEP(uFlowProtectValue, FLOW_STEP_MPU_S_EN, FLOW_CTRL_MPU_S_EN);
225     }
226     /* verification stage */
227     else
228     {
229         /* check secure MPU regions */
230         for (i = 0; i < ARRAY_SIZE(region_cfg); i++)
231         {
232             memcpy(&localcfg, &region_cfg[i], sizeof(localcfg));
233             localcfg.region_nr = i;
234 
235             if (mpu_armv8m_region_enable_check(&dev_mpu_s,
236                         &localcfg) != MPU_ARMV8M_OK)
237             {
238                 Error_Handler();
239             }
240             else
241             {
242                 /* Execution stopped if flow control failed */
243                 FLOW_CONTROL_STEP(uFlowProtectValue, localcfg.flow_step_check,
244                         region_cfg[i].flow_ctrl_check);
245             }
246         }
247 
248         /* check secure MPU */
249         if (mpu_armv8m_check(&dev_mpu_s, PRIVILEGED_DEFAULT_ENABLE,
250                     HARDFAULT_NMI_ENABLE) != MPU_ARMV8M_OK)
251         {
252             Error_Handler();
253         }
254         else
255         {
256             /* Execution stopped if flow control failed */
257             FLOW_CONTROL_STEP(uFlowProtectValue, FLOW_STEP_MPU_S_CH, FLOW_CTRL_MPU_S_CH);
258         }
259 
260         /* Lock MPU config */
261         __HAL_RCC_SYSCFG_CLK_ENABLE();
262         /* in TFM_DEV_MODE MPU is not locked, this allows to see MPU configuration */
263 #ifndef TFM_DEV_MODE
264         SYSCFG->CSLCKR |= SYSCFG_CSLCKR_LOCKSMPU;
265 #endif
266         FLOW_CONTROL_STEP(uFlowProtectValue, FLOW_STEP_MPU_S_LCK, FLOW_CTRL_MPU_S_LCK);
267 #ifndef TFM_DEV_MODE
268         if (!(SYSCFG->CSLCKR & SYSCFG_CSLCKR_LOCKSMPU))
269             Error_Handler();
270 #endif
271         FLOW_CONTROL_STEP(uFlowProtectValue, FLOW_STEP_MPU_S_LCK_CH, FLOW_CTRL_MPU_S_LCK_CH);
272     }
273 
274     return TFM_HAL_SUCCESS;
275 }
276 #endif /* CONFIG_TFM_ENABLE_MEMORY_PROTECT */
277 
tfm_hal_set_up_static_boundaries(uintptr_t * p_spm_boundary)278 FIH_RET_TYPE(enum tfm_hal_status_t) tfm_hal_set_up_static_boundaries(
279                                             uintptr_t *p_spm_boundary)
280 {
281     /* Set up isolation boundaries between SPE and NSPE */
282     /* Configures non-secure memory spaces in the target */
283     uFlowStage = FLOW_STAGE_CFG;
284     gtzc_init_cfg();
285     sau_and_idau_cfg();
286     pinmux_init_cfg();
287 
288     /* Check configurations with Flow control to resist to basic HW attacks */
289     uFlowStage = FLOW_STAGE_CHK;
290     gtzc_init_cfg();
291     sau_and_idau_cfg();
292 
293     /* Start HW randomization */
294     if (RNG_Init()){
295         Error_Handler();
296     };
297 
298 #ifdef CONFIG_TFM_ENABLE_MEMORY_PROTECT
299     uFlowStage = FLOW_STAGE_CFG;
300     mpu_init();
301     uFlowStage = FLOW_STAGE_CHK;
302     mpu_init();
303 #endif /* CONFIG_TFM_ENABLE_MEMORY_PROTECT */
304 
305     *p_spm_boundary = (uintptr_t)PROT_BOUNDARY_VAL;
306 
307     FIH_RET(fih_int_encode(TFM_HAL_SUCCESS));
308 }
309 
310 #ifdef TFM_FIH_PROFILE_ON
tfm_hal_verify_static_boundaries(void)311 fih_int tfm_hal_verify_static_boundaries(void)
312 {
313     FIH_RET(fih_int_encode(TFM_HAL_SUCCESS));
314 }
315 #endif
316 
317 /*
318  * Implementation of tfm_hal_bind_boundary() on STM:
319  *
320  * The API encodes some attributes into a handle and returns it to SPM.
321  * The attributes include isolation boundaries, privilege, and MMIO information.
322  * When scheduler switches running partitions, SPM compares the handle between
323  * partitions to know if boundary update is necessary. If update is required,
324  * SPM passes the handle to platform to do platform settings and update
325  * isolation boundaries.
326  *
327  * The handle should be unique under isolation level 3. The implementation
328  * encodes an index at the highest 8 bits to assure handle uniqueness. While
329  * under isolation level 1/2, handles may not be unique.
330  *
331  * The encoding format assignment:
332  * - For isolation level 3
333  *      BIT | 31        24 | 23         20 | ... | 7           4 | 3       0 |
334  *          | Unique Index | Region Attr 5 | ... | Region Attr 1 | Base Attr |
335  *
336  *      In which the "Region Attr i" is:
337  *      BIT |       3      | 2        0 |
338  *          | 1: RW, 0: RO | MMIO Index |
339  *
340  *      In which the "Base Attr" is:
341  *      BIT |               1                |                           0                     |
342  *          | 1: privileged, 0: unprivileged | 1: Trustzone-specific NSPE, 0: Secure partition |
343  *
344  * - For isolation level 1/2
345  *      BIT | 31     2 |              1                |                           0                     |
346  *          | Reserved |1: privileged, 0: unprivileged | 1: Trustzone-specific NSPE, 0: Secure partition |
347  *
348  * This is a reference implementation on STM, and may have some limitations.
349  * 1. The maximum number of allowed MMIO regions is 5.
350  * 2. Highest 8 bits are for index. It supports 256 unique handles at most.
351  */
352 
tfm_hal_bind_boundary(const struct partition_load_info_t * p_ldinf,uintptr_t * p_boundary)353 FIH_RET_TYPE(enum tfm_hal_status_t) tfm_hal_bind_boundary(
354                                     const struct partition_load_info_t *p_ldinf,
355                                     uintptr_t *p_boundary)
356 {
357     uint32_t i, j;
358     bool privileged;
359     bool ns_agent;
360     uint32_t partition_attrs = 0;
361     const struct asset_desc_t *p_asset;
362     struct platform_data_t *plat_data_ptr;
363 #if TFM_LVL == 2
364     struct mpu_armv8m_region_cfg_t localcfg;
365 #endif
366 
367     if (!p_ldinf || !p_boundary) {
368         FIH_RET(fih_int_encode(TFM_HAL_ERROR_GENERIC));
369     }
370 
371 #if TFM_LVL == 1
372     privileged = true;
373 #else
374     privileged = IS_PSA_ROT(p_ldinf);
375 #endif
376 
377     ns_agent = IS_NS_AGENT(p_ldinf);
378     p_asset = LOAD_INFO_ASSET(p_ldinf);
379 
380     /*
381      * Validate if the named MMIO of partition is allowed by the platform.
382      * Otherwise, skip validation.
383      *
384      * NOTE: Need to add validation of numbered MMIO if platform requires.
385      */
386     for (i = 0; i < p_ldinf->nassets; i++) {
387         if (!(p_asset[i].attr & ASSET_ATTR_NAMED_MMIO)) {
388             continue;
389         }
390         for (j = 0; j < ARRAY_SIZE(partition_named_mmio_list); j++) {
391             if (p_asset[i].dev.dev_ref == partition_named_mmio_list[j]) {
392                 break;
393             }
394         }
395 
396         if (j == ARRAY_SIZE(partition_named_mmio_list)) {
397             /* The MMIO asset is not in the allowed list of platform. */
398             FIH_RET(fih_int_encode(TFM_HAL_ERROR_GENERIC));
399         }
400 #if TFM_LVL == 2
401         plat_data_ptr = REFERENCE_TO_PTR(p_asset[i].dev.dev_ref,
402                                          struct platform_data_t *);
403         /*
404          * Static boundaries are set. Set up MPU region for MMIO.
405          * Setup regions for unprivileged assets only.
406          */
407         if (!privileged) {
408             localcfg.region_base = plat_data_ptr->periph_start;
409             localcfg.region_limit = plat_data_ptr->periph_limit;
410             localcfg.region_attridx = MPU_ARMV8M_MAIR_ATTR_DEVICE_IDX;
411             localcfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV;
412             localcfg.attr_sh = MPU_ARMV8M_SH_NONE;
413             localcfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;
414             localcfg.region_nr = n_configured_regions++;
415 
416             if (mpu_armv8m_region_enable(&dev_mpu_s, &localcfg)
417                 != MPU_ARMV8M_OK) {
418                 FIH_RET(fih_int_encode(TFM_HAL_ERROR_GENERIC));
419             }
420         }
421 #endif
422     }
423     partition_attrs = ((uint32_t)privileged << HANDLE_ATTR_PRIV_POS) &
424                         HANDLE_ATTR_PRIV_MASK;
425     partition_attrs |= ((uint32_t)ns_agent << HANDLE_ATTR_NS_POS) &
426                         HANDLE_ATTR_NS_MASK;
427     *p_boundary = (uintptr_t)partition_attrs;
428 
429     FIH_RET(fih_int_encode(TFM_HAL_SUCCESS));
430 }
431 
tfm_hal_activate_boundary(const struct partition_load_info_t * p_ldinf,uintptr_t boundary)432 FIH_RET_TYPE(enum tfm_hal_status_t) tfm_hal_activate_boundary(
433                              const struct partition_load_info_t *p_ldinf,
434                              uintptr_t boundary)
435 {
436     CONTROL_Type ctrl;
437     uint32_t local_handle = (uint32_t)boundary;
438     bool privileged = !!(local_handle & HANDLE_ATTR_PRIV_MASK);
439 
440     /* Privileged level is required to be set always */
441     ctrl.w = __get_CONTROL();
442     ctrl.b.nPRIV = privileged ? 0 : 1;
443     __set_CONTROL(ctrl.w);
444 
445     FIH_RET(fih_int_encode(TFM_HAL_SUCCESS));
446 }
447 
tfm_hal_memory_check(uintptr_t boundary,uintptr_t base,size_t size,uint32_t access_type)448 FIH_RET_TYPE(enum tfm_hal_status_t) tfm_hal_memory_check(uintptr_t boundary, uintptr_t base,
449                                            size_t size, uint32_t access_type)
450 {
451     int flags = 0;
452 
453     /* If size is zero, this indicates an empty buffer and base is ignored */
454     if (size == 0) {
455         FIH_RET(fih_int_encode(TFM_HAL_SUCCESS));
456     }
457 
458     if (!base) {
459         FIH_RET(fih_int_encode(TFM_HAL_ERROR_INVALID_INPUT));
460     }
461 
462     if ((access_type & TFM_HAL_ACCESS_READWRITE) == TFM_HAL_ACCESS_READWRITE) {
463         flags |= CMSE_MPU_READWRITE;
464     } else if (access_type & TFM_HAL_ACCESS_READABLE) {
465         flags |= CMSE_MPU_READ;
466     } else {
467         FIH_RET(fih_int_encode(TFM_HAL_ERROR_INVALID_INPUT));
468     }
469 
470     if (!((uint32_t)boundary & HANDLE_ATTR_PRIV_MASK)) {
471         flags |= CMSE_MPU_UNPRIV;
472     }
473 
474     if ((uint32_t)boundary & HANDLE_ATTR_NS_MASK) {
475         CONTROL_Type ctrl;
476         ctrl.w = __TZ_get_CONTROL_NS();
477         if (ctrl.b.nPRIV == 1) {
478             flags |= CMSE_MPU_UNPRIV;
479         } else {
480             flags &= ~CMSE_MPU_UNPRIV;
481         }
482         flags |= CMSE_NONSECURE;
483     }
484 
485     if (cmse_check_address_range((void *)base, size, flags) != NULL) {
486         FIH_RET(fih_int_encode(TFM_HAL_SUCCESS));
487     } else {
488         FIH_RET(fih_int_encode(TFM_HAL_ERROR_MEM_FAULT));
489     }
490 }
491 
tfm_hal_boundary_need_switch(uintptr_t boundary_from,uintptr_t boundary_to)492 bool tfm_hal_boundary_need_switch(uintptr_t boundary_from,
493                                   uintptr_t boundary_to)
494 {
495     if (boundary_from == boundary_to) {
496         return false;
497     }
498 
499     if (((uint32_t)boundary_from & HANDLE_ATTR_PRIV_MASK) &&
500         ((uint32_t)boundary_to & HANDLE_ATTR_PRIV_MASK)) {
501         return false;
502     }
503     return true;
504 }
505