1 /*
2 * Copyright (c) 2020-2024, 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 "array.h"
15 #include "tfm_hal_device_header.h"
16 #include "Driver_Common.h"
17 #include "mmio_defs.h"
18 #include "mpu_armv8m_drv.h"
19 #include "region.h"
20 #include "target_cfg.h"
21 #include "tfm_hal_defs.h"
22 #include "tfm_hal_isolation.h"
23 #include "tfm_peripherals_def.h"
24 #include "load/partition_defs.h"
25 #include "load/asset_defs.h"
26 #include "load/spm_load_api.h"
27
28 /* It can be retrieved from the MPU_TYPE register. */
29 #define MPU_REGION_NUM 8
30
31 #if TFM_ISOLATION_LEVEL == 3
32 #define PROT_BOUNDARY_VAL \
33 (((1U << HANDLE_ATTR_PRIV_POS) & HANDLE_ATTR_PRIV_MASK) | \
34 ((1U << HANDLE_ATTR_SPM_POS) & HANDLE_ATTR_SPM_MASK))
35 #else
36 #define PROT_BOUNDARY_VAL \
37 ((1U << HANDLE_ATTR_PRIV_POS) & HANDLE_ATTR_PRIV_MASK)
38 #endif
39
40 #ifdef CONFIG_TFM_ENABLE_MEMORY_PROTECT
41 static uint32_t n_configured_regions = 0;
42 struct mpu_armv8m_dev_t dev_mpu_s = { MPU_BASE };
43
44 #ifdef CONFIG_TFM_PARTITION_META
45 REGION_DECLARE(Image$$, TFM_SP_META_PTR, $$ZI$$Base);
46 REGION_DECLARE(Image$$, TFM_SP_META_PTR_END, $$ZI$$Limit);
47 #endif
48
49 #if TFM_ISOLATION_LEVEL == 3
50 static uint32_t idx_boundary_handle = 0;
51 REGION_DECLARE(Image$$, PT_RO_START, $$Base);
52 REGION_DECLARE(Image$$, PT_RO_END, $$Base);
53 REGION_DECLARE(Image$$, PT_PRIV_RWZI_START, $$Base);
54 REGION_DECLARE(Image$$, PT_PRIV_RWZI_END, $$Base);
55
56 static struct mpu_armv8m_region_cfg_t isolation_regions[] = {
57 {
58 0, /* will be updated before using */
59 (uint32_t)®ION_NAME(Image$$, PT_RO_START, $$Base),
60 (uint32_t)®ION_NAME(Image$$, PT_RO_END, $$Base) - 1,
61 MPU_ARMV8M_MAIR_ATTR_CODE_IDX,
62 MPU_ARMV8M_XN_EXEC_OK,
63 MPU_ARMV8M_AP_RO_PRIV_UNPRIV,
64 MPU_ARMV8M_SH_NONE,
65 },
66 /* For isolation Level 3, set up static isolation for privileged data.
67 * Unprivileged data is dynamically set during Partition scheduling.
68 */
69 {
70 0, /* will be updated before using */
71 (uint32_t)®ION_NAME(Image$$, PT_PRIV_RWZI_START, $$Base),
72 (uint32_t)®ION_NAME(Image$$, PT_PRIV_RWZI_END, $$Base) - 1,
73 MPU_ARMV8M_MAIR_ATTR_DATA_IDX,
74 MPU_ARMV8M_XN_EXEC_NEVER,
75 MPU_ARMV8M_AP_RW_PRIV_ONLY,
76 MPU_ARMV8M_SH_NONE,
77 },
78 #ifdef CONFIG_TFM_PARTITION_META
79 {
80 0, /* will be updated before using */
81 (uint32_t)®ION_NAME(Image$$, TFM_SP_META_PTR, $$ZI$$Base),
82 (uint32_t)®ION_NAME(Image$$, TFM_SP_META_PTR_END, $$ZI$$Limit) - 1,
83 MPU_ARMV8M_MAIR_ATTR_DATA_IDX,
84 MPU_ARMV8M_XN_EXEC_NEVER,
85 MPU_ARMV8M_AP_RW_PRIV_UNPRIV,
86 MPU_ARMV8M_SH_NONE,
87 }
88 #endif
89 };
90 #else /* TFM_ISOLATION_LEVEL == 3 */
91
92 REGION_DECLARE(Image$$, ER_VENEER, $$Base);
93 REGION_DECLARE(Image$$, VENEER_ALIGN, $$Limit);
94 REGION_DECLARE(Image$$, TFM_UNPRIV_CODE_START, $$RO$$Base);
95 REGION_DECLARE(Image$$, TFM_UNPRIV_CODE_END, $$RO$$Limit);
96 REGION_DECLARE(Image$$, TFM_APP_CODE_START, $$Base);
97 REGION_DECLARE(Image$$, TFM_APP_CODE_END, $$Base);
98 REGION_DECLARE(Image$$, TFM_APP_RW_STACK_START, $$Base);
99 REGION_DECLARE(Image$$, TFM_APP_RW_STACK_END, $$Base);
100
101 #endif /* TFM_ISOLATION_LEVEL == 3 */
102 #endif /* CONFIG_TFM_ENABLE_MEMORY_PROTECT */
103
tfm_hal_set_up_static_boundaries(uintptr_t * p_spm_boundary)104 enum tfm_hal_status_t tfm_hal_set_up_static_boundaries(
105 uintptr_t *p_spm_boundary)
106 {
107 /* Set up isolation boundaries between SPE and NSPE */
108 sau_and_idau_cfg();
109
110 if (mpc_init_cfg() != ARM_DRIVER_OK) {
111 return TFM_HAL_ERROR_GENERIC;
112 }
113
114 if (ppc_init_cfg() != ARM_DRIVER_OK) {
115 return TFM_HAL_ERROR_GENERIC;
116 }
117
118 /* Set up static isolation boundaries inside SPE */
119 #ifdef CONFIG_TFM_ENABLE_MEMORY_PROTECT
120
121 mpu_armv8m_clean(&dev_mpu_s);
122 #if TFM_ISOLATION_LEVEL == 3
123 int32_t i;
124
125 /*
126 * Update MPU region numbers. The numbers start from 0 and are continuous.
127 * Under isolation level3, at lease one MPU region is reserved for private
128 * data asset.
129 */
130 if (ARRAY_SIZE(isolation_regions) >= MPU_REGION_NUM) {
131 return TFM_HAL_ERROR_GENERIC;
132 }
133 for (i = 0; i < ARRAY_SIZE(isolation_regions); i++) {
134 /* Update region number */
135 isolation_regions[i].region_nr = i;
136 /* Enable regions */
137 if (mpu_armv8m_region_enable(&dev_mpu_s, &isolation_regions[i])
138 != MPU_ARMV8M_OK) {
139 return TFM_HAL_ERROR_GENERIC;
140 }
141 }
142 n_configured_regions = i;
143 #else /* TFM_ISOLATION_LEVEL == 3 */
144 struct mpu_armv8m_region_cfg_t region_cfg;
145
146 /* Veneer region */
147 region_cfg.region_nr = n_configured_regions;
148 region_cfg.region_base = (uint32_t)®ION_NAME(Image$$, ER_VENEER, $$Base);
149 region_cfg.region_limit =
150 (uint32_t)®ION_NAME(Image$$, VENEER_ALIGN, $$Limit) - 1;
151 region_cfg.region_attridx = MPU_ARMV8M_MAIR_ATTR_CODE_IDX;
152 region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV;
153 region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;
154 region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_OK;
155 if (mpu_armv8m_region_enable(&dev_mpu_s, ®ion_cfg) != MPU_ARMV8M_OK) {
156 return TFM_HAL_ERROR_GENERIC;
157 }
158 n_configured_regions++;
159
160 /* TFM Core unprivileged code region */
161 region_cfg.region_nr = n_configured_regions;
162 region_cfg.region_base =
163 (uint32_t)®ION_NAME(Image$$, TFM_UNPRIV_CODE_START, $$RO$$Base);
164 region_cfg.region_limit =
165 (uint32_t)®ION_NAME(Image$$, TFM_UNPRIV_CODE_END, $$RO$$Limit) - 1;
166 region_cfg.region_attridx = MPU_ARMV8M_MAIR_ATTR_CODE_IDX;
167 region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV;
168 region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;
169 region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_OK;
170 if (mpu_armv8m_region_enable(&dev_mpu_s, ®ion_cfg) != MPU_ARMV8M_OK) {
171 return TFM_HAL_ERROR_GENERIC;
172 }
173 n_configured_regions++;
174
175 /* RO region */
176 region_cfg.region_nr = n_configured_regions;
177 region_cfg.region_base =
178 (uint32_t)®ION_NAME(Image$$, TFM_APP_CODE_START, $$Base);
179 region_cfg.region_limit =
180 (uint32_t)®ION_NAME(Image$$, TFM_APP_CODE_END, $$Base) - 1;
181 region_cfg.region_attridx = MPU_ARMV8M_MAIR_ATTR_CODE_IDX;
182 region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV;
183 region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;
184 region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_OK;
185 if (mpu_armv8m_region_enable(&dev_mpu_s, ®ion_cfg) != MPU_ARMV8M_OK) {
186 return TFM_HAL_ERROR_GENERIC;
187 }
188 n_configured_regions++;
189
190 /* RW, ZI and stack as one region */
191 region_cfg.region_nr = n_configured_regions;
192 region_cfg.region_base =
193 (uint32_t)®ION_NAME(Image$$, TFM_APP_RW_STACK_START, $$Base);
194 region_cfg.region_limit =
195 (uint32_t)®ION_NAME(Image$$, TFM_APP_RW_STACK_END, $$Base) - 1;
196 region_cfg.region_attridx = MPU_ARMV8M_MAIR_ATTR_DATA_IDX;
197 region_cfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV;
198 region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;
199 region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;
200 if (mpu_armv8m_region_enable(&dev_mpu_s, ®ion_cfg) != MPU_ARMV8M_OK) {
201 return TFM_HAL_ERROR_GENERIC;
202 }
203 n_configured_regions++;
204
205 #ifdef CONFIG_TFM_PARTITION_META
206 /* TFM partition metadata pointer region */
207 region_cfg.region_nr = n_configured_regions;
208 region_cfg.region_base =
209 (uint32_t)®ION_NAME(Image$$, TFM_SP_META_PTR, $$ZI$$Base);
210 region_cfg.region_limit =
211 (uint32_t)®ION_NAME(Image$$, TFM_SP_META_PTR_END, $$ZI$$Limit) - 1;
212 region_cfg.region_attridx = MPU_ARMV8M_MAIR_ATTR_DATA_IDX;
213 region_cfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV;
214 region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;
215 region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;
216 if (mpu_armv8m_region_enable(&dev_mpu_s, ®ion_cfg) != MPU_ARMV8M_OK) {
217 return TFM_HAL_ERROR_GENERIC;
218 }
219 n_configured_regions++;
220 #endif /* CONFIG_TFM_PARTITION_META */
221 #endif /* TFM_ISOLATION_LEVEL == 3 */
222
223 /* Enable MPU */
224 if (mpu_armv8m_enable(&dev_mpu_s,
225 PRIVILEGED_DEFAULT_ENABLE,
226 HARDFAULT_NMI_ENABLE) != MPU_ARMV8M_OK) {
227 return TFM_HAL_ERROR_GENERIC;
228 }
229 #endif
230
231 *p_spm_boundary = (uintptr_t)PROT_BOUNDARY_VAL;
232
233 return TFM_HAL_SUCCESS;
234 }
235
236 /*
237 * Implementation of tfm_hal_bind_boundary() on MUSCA_B1:
238 *
239 * The API encodes some attributes into a handle and returns it to SPM.
240 * The attributes include isolation boundaries, privilege, and MMIO information.
241 * When scheduler switches running partitions, SPM compares the handle between
242 * partitions to know if boundary update is necessary. If update is required,
243 * SPM passes the handle to platform to do platform settings and update
244 * isolation boundaries.
245 *
246 * The handle should be unique under isolation level 3. The implementation
247 * encodes an index at the highest 8 bits to assure handle uniqueness. While
248 * under isolation level 1/2, handles may not be unique.
249 *
250 * The encoding format assignment:
251 * - For isolation level 3
252 * BIT | 31 24 | 23 20 | ... | 7 4 | 3 0 |
253 * | Unique Index | Region Attr 5 | ... | Region Attr 1 | Base Attr |
254 *
255 * In which the "Region Attr i" is:
256 * BIT | 3 | 2 0 |
257 * | 1: RW, 0: RO | MMIO Index |
258 *
259 * In which the "Base Attr" is:
260 * BIT | 1 | 0 |
261 * | 1: privileged, 0: unprivileged | 1: Trustzone-specific NSPE, 0: Secure partition |
262 *
263 * - For isolation level 1/2
264 * BIT | 31 2 | 1 | 0 |
265 * | Reserved |1: privileged, 0: unprivileged | 1: Trustzone-specific NSPE, 0: Secure partition |
266 *
267 * This is a reference implementation on MUSCA_B1, and may have some
268 * limitations.
269 * 1. The maximum number of allowed MMIO regions is 5.
270 * 2. Highest 8 bits are for index. It supports 256 unique handles at most.
271 */
tfm_hal_bind_boundary(const struct partition_load_info_t * p_ldinf,uintptr_t * p_boundary)272 enum tfm_hal_status_t tfm_hal_bind_boundary(
273 const struct partition_load_info_t *p_ldinf,
274 uintptr_t *p_boundary)
275 {
276 uint32_t i, j;
277 bool privileged;
278 bool ns_agent;
279 uint32_t partition_attrs = 0;
280 const struct asset_desc_t *p_asset;
281 struct platform_data_t *plat_data_ptr;
282 #if TFM_ISOLATION_LEVEL == 2
283 struct mpu_armv8m_region_cfg_t localcfg;
284 #endif
285
286 if (!p_ldinf || !p_boundary) {
287 return TFM_HAL_ERROR_GENERIC;
288 }
289
290 #if TFM_ISOLATION_LEVEL == 1
291 privileged = true;
292 #else
293 privileged = IS_PSA_ROT(p_ldinf);
294 #endif
295
296 ns_agent = IS_NS_AGENT(p_ldinf);
297 p_asset = LOAD_INFO_ASSET(p_ldinf);
298
299 /*
300 * Validate if the named MMIO of partition is allowed by the platform.
301 * Otherwise, skip validation.
302 *
303 * NOTE: Need to add validation of numbered MMIO if platform requires.
304 */
305 for (i = 0; i < p_ldinf->nassets; i++) {
306 if (!(p_asset[i].attr & ASSET_ATTR_NAMED_MMIO)) {
307 continue;
308 }
309 for (j = 0; j < ARRAY_SIZE(partition_named_mmio_list); j++) {
310 if (p_asset[i].dev.dev_ref == partition_named_mmio_list[j]) {
311 break;
312 }
313 }
314
315 if (j == ARRAY_SIZE(partition_named_mmio_list)) {
316 /* The MMIO asset is not in the allowed list of platform. */
317 return TFM_HAL_ERROR_GENERIC;
318 }
319 /* Assume PPC & MPC settings are required even under level 1 */
320 plat_data_ptr = REFERENCE_TO_PTR(p_asset[i].dev.dev_ref,
321 struct platform_data_t *);
322
323 if (plat_data_ptr->periph_ppc_bank != PPC_SP_DO_NOT_CONFIGURE) {
324 ppc_configure_to_secure(plat_data_ptr->periph_ppc_bank,
325 plat_data_ptr->periph_ppc_loc);
326 if (privileged) {
327 ppc_clr_secure_unpriv(plat_data_ptr->periph_ppc_bank,
328 plat_data_ptr->periph_ppc_loc);
329 } else {
330 ppc_en_secure_unpriv(plat_data_ptr->periph_ppc_bank,
331 plat_data_ptr->periph_ppc_loc);
332 }
333 }
334
335 #if TFM_ISOLATION_LEVEL == 2
336 /*
337 * Static boundaries are set. Set up MPU region for MMIO.
338 * Setup regions for unprivileged assets only.
339 */
340 if (!privileged) {
341 localcfg.region_base = plat_data_ptr->periph_start;
342 localcfg.region_limit = plat_data_ptr->periph_limit;
343 localcfg.region_attridx = MPU_ARMV8M_MAIR_ATTR_DEVICE_IDX;
344 localcfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV;
345 localcfg.attr_sh = MPU_ARMV8M_SH_NONE;
346 localcfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;
347 localcfg.region_nr = n_configured_regions++;
348
349 if (mpu_armv8m_region_enable(&dev_mpu_s, &localcfg)
350 != MPU_ARMV8M_OK) {
351 return TFM_HAL_ERROR_GENERIC;
352 }
353 }
354 #elif TFM_ISOLATION_LEVEL == 3
355 /* Encode MMIO attributes into the "partition_attrs". */
356 partition_attrs <<= HANDLE_PER_ATTR_BITS;
357 partition_attrs |= ((j + 1) & HANDLE_ATTR_INDEX_MASK);
358 if (p_asset[i].attr & ASSET_ATTR_READ_WRITE) {
359 partition_attrs |= HANDLE_ATTR_RW_POS;
360 }
361 #endif
362 }
363
364 #if TFM_ISOLATION_LEVEL == 3
365 partition_attrs <<= HANDLE_PER_ATTR_BITS;
366 /*
367 * Highest 8 bits are reserved for index, if they are non-zero, MMIO numbers
368 * must have exceeded the limit of 5.
369 */
370 if (partition_attrs & HANDLE_INDEX_MASK) {
371 return TFM_HAL_ERROR_GENERIC;
372 }
373 HANDLE_ENCODE_INDEX(partition_attrs, idx_boundary_handle);
374 #endif
375
376 partition_attrs |= ((uint32_t)privileged << HANDLE_ATTR_PRIV_POS) &
377 HANDLE_ATTR_PRIV_MASK;
378 partition_attrs |= ((uint32_t)ns_agent << HANDLE_ATTR_NS_POS) &
379 HANDLE_ATTR_NS_MASK;
380 *p_boundary = (uintptr_t)partition_attrs;
381
382 return TFM_HAL_SUCCESS;
383 }
384
tfm_hal_activate_boundary(const struct partition_load_info_t * p_ldinf,uintptr_t boundary)385 enum tfm_hal_status_t tfm_hal_activate_boundary(
386 const struct partition_load_info_t *p_ldinf,
387 uintptr_t boundary)
388 {
389 CONTROL_Type ctrl;
390 uint32_t local_handle = (uint32_t)boundary;
391 bool privileged = !!(local_handle & HANDLE_ATTR_PRIV_MASK);
392 #if TFM_ISOLATION_LEVEL == 3
393 bool is_spm = !!(local_handle & HANDLE_ATTR_SPM_MASK);
394 struct mpu_armv8m_region_cfg_t localcfg;
395 uint32_t i, mmio_index;
396 struct platform_data_t *plat_data_ptr;
397 const struct asset_desc_t *rt_mem;
398 #endif
399
400 /* Privileged level is required to be set always */
401 ctrl.w = __get_CONTROL();
402 ctrl.b.nPRIV = privileged ? 0 : 1;
403 __set_CONTROL(ctrl.w);
404
405 #if TFM_ISOLATION_LEVEL == 3
406 if (is_spm) {
407 FIH_RET(fih_int_encode(TFM_HAL_SUCCESS));
408 }
409
410 if (!p_ldinf) {
411 return TFM_HAL_ERROR_GENERIC;
412 }
413
414 /* Update regions, for unprivileged partitions only */
415 if (privileged) {
416 return TFM_HAL_SUCCESS;
417 }
418
419 /* Setup runtime memory first */
420 localcfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;
421 localcfg.attr_sh = MPU_ARMV8M_SH_NONE;
422 localcfg.region_attridx = MPU_ARMV8M_MAIR_ATTR_DATA_IDX;
423 localcfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV;
424 rt_mem = LOAD_INFO_ASSET(p_ldinf);
425 /*
426 * MUSCA_B1 shortcut: The first item is the only runtime memory asset.
427 * Platforms with many memory assets please check this part.
428 */
429 for (i = 0;
430 i < p_ldinf->nassets && !(rt_mem[i].attr & ASSET_ATTR_MMIO);
431 i++) {
432 localcfg.region_nr = n_configured_regions + i;
433 localcfg.region_base = rt_mem[i].mem.start;
434 localcfg.region_limit = rt_mem[i].mem.limit - 1;
435
436 if (mpu_armv8m_region_enable(&dev_mpu_s, &localcfg) != MPU_ARMV8M_OK) {
437 return TFM_HAL_ERROR_GENERIC;
438 }
439 }
440
441 /* Named MMIO part */
442 local_handle = local_handle & (~HANDLE_INDEX_MASK);
443 local_handle >>= HANDLE_PER_ATTR_BITS;
444 mmio_index = local_handle & HANDLE_ATTR_INDEX_MASK;
445
446 localcfg.region_attridx = MPU_ARMV8M_MAIR_ATTR_DEVICE_IDX;
447
448 i = n_configured_regions + i;
449 while (mmio_index && i < MPU_REGION_NUM) {
450 plat_data_ptr =
451 (struct platform_data_t *)partition_named_mmio_list[mmio_index - 1];
452 localcfg.region_nr = i++;
453 localcfg.attr_access = (local_handle & HANDLE_ATTR_RW_POS)?
454 MPU_ARMV8M_AP_RW_PRIV_UNPRIV :
455 MPU_ARMV8M_AP_RO_PRIV_UNPRIV;
456 localcfg.region_base = plat_data_ptr->periph_start;
457 localcfg.region_limit = plat_data_ptr->periph_limit;
458
459 if (mpu_armv8m_region_enable(&dev_mpu_s, &localcfg) != MPU_ARMV8M_OK) {
460 return TFM_HAL_ERROR_GENERIC;
461 }
462
463 local_handle >>= HANDLE_PER_ATTR_BITS;
464 mmio_index = local_handle & HANDLE_ATTR_INDEX_MASK;
465 }
466
467 /* Disable unused regions */
468 while (i < MPU_REGION_NUM) {
469 if (mpu_armv8m_region_disable(&dev_mpu_s, i++)!= MPU_ARMV8M_OK) {
470 return TFM_HAL_ERROR_GENERIC;
471 }
472 }
473 #endif
474 return TFM_HAL_SUCCESS;
475 }
476
tfm_hal_memory_check(uintptr_t boundary,uintptr_t base,size_t size,uint32_t access_type)477 enum tfm_hal_status_t tfm_hal_memory_check(uintptr_t boundary, uintptr_t base,
478 size_t size, uint32_t access_type)
479 {
480 int flags = 0;
481
482 /* If size is zero, this indicates an empty buffer and base is ignored */
483 if (size == 0) {
484 return TFM_HAL_SUCCESS;
485 }
486
487 if (!base) {
488 return TFM_HAL_ERROR_INVALID_INPUT;
489 }
490
491 if ((access_type & TFM_HAL_ACCESS_READWRITE) == TFM_HAL_ACCESS_READWRITE) {
492 flags |= CMSE_MPU_READWRITE;
493 } else if (access_type & TFM_HAL_ACCESS_READABLE) {
494 flags |= CMSE_MPU_READ;
495 } else {
496 return TFM_HAL_ERROR_INVALID_INPUT;
497 }
498
499 if (!((uint32_t)boundary & HANDLE_ATTR_PRIV_MASK)) {
500 flags |= CMSE_MPU_UNPRIV;
501 }
502
503 if ((uint32_t)boundary & HANDLE_ATTR_NS_MASK) {
504 CONTROL_Type ctrl;
505 ctrl.w = __TZ_get_CONTROL_NS();
506 if (ctrl.b.nPRIV == 1) {
507 flags |= CMSE_MPU_UNPRIV;
508 } else {
509 flags &= ~CMSE_MPU_UNPRIV;
510 }
511 flags |= CMSE_NONSECURE;
512 }
513
514 if (cmse_check_address_range((void *)base, size, flags) != NULL) {
515 return TFM_HAL_SUCCESS;
516 } else {
517 return TFM_HAL_ERROR_MEM_FAULT;
518 }
519 }
520
tfm_hal_boundary_need_switch(uintptr_t boundary_from,uintptr_t boundary_to)521 bool tfm_hal_boundary_need_switch(uintptr_t boundary_from,
522 uintptr_t boundary_to)
523 {
524 if (boundary_from == boundary_to) {
525 return false;
526 }
527
528 if (((uint32_t)boundary_from & HANDLE_ATTR_PRIV_MASK) &&
529 ((uint32_t)boundary_to & HANDLE_ATTR_PRIV_MASK)) {
530 return false;
531 }
532 return true;
533 }
534