TF-M Reference Manual  1.2.0
TrustedFirmware-M
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
tfm_core_mem_check.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017-2020, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include <arm_cmse.h>
9 #include <stdbool.h>
10 #include "region_defs.h"
11 #include "tfm_arch.h"
12 #include "tfm_spm_hal.h"
13 #include "tfm_api.h"
14 #include "spm_func.h"
15 
32 static enum tfm_status_e has_access_to_region(const void *p, size_t s,
33  int flags)
34 {
35  int32_t range_access_allowed_by_mpu;
36 
37  /* Use the TT instruction to check access to the partition's regions*/
38  range_access_allowed_by_mpu =
39  cmse_check_address_range((void *)p, s, flags) != NULL;
40 
41 #if !defined(__SAUREGION_PRESENT) || (__SAUREGION_PRESENT == 0)
42  if (!range_access_allowed_by_mpu) {
43  /*
44  * Verification failure may be due to address range crossing
45  * one or multiple IDAU boundaries. In this case request a
46  * platform-specific check for access permissions.
47  */
48  cmse_address_info_t addr_info_base = cmse_TT((void *)p);
49  cmse_address_info_t addr_info_last = cmse_TT((void *)((uint32_t)p + s - 1));
50 
51  if ((addr_info_base.flags.idau_region_valid != 0) &&
52  (addr_info_last.flags.idau_region_valid != 0) &&
53  (addr_info_base.flags.idau_region != addr_info_last.flags.idau_region)) {
54  range_access_allowed_by_mpu =
55  tfm_spm_hal_has_access_to_region(p, s, flags);
56  }
57  }
58 #endif
59 
60  if (range_access_allowed_by_mpu) {
61  return TFM_SUCCESS;
62  }
63 
64  return TFM_ERROR_GENERIC;
65 }
66 
67 enum tfm_status_e tfm_core_has_read_access_to_region(const void *p, size_t s,
68  bool ns_caller,
69  uint32_t privileged)
70 {
71  int flags = CMSE_MPU_READ;
72 
73  /* In case of NS caller, only force unprivileged check, if the non secure
74  * Thread mode is unprivileged
75  */
76  if (ns_caller) {
77  CONTROL_Type ctrl;
78 
79  ctrl.w = __TZ_get_CONTROL_NS();
80  if (ctrl.b.nPRIV == 1) {
82  } else {
83  privileged = TFM_PARTITION_PRIVILEGED_MODE;
84  }
85  }
86 
87  if (privileged == TFM_PARTITION_UNPRIVILEGED_MODE) {
88  flags |= CMSE_MPU_UNPRIV;
89  }
90 
91  if (ns_caller) {
92  flags |= CMSE_NONSECURE;
93  }
94 
95  return has_access_to_region(p, s, flags);
96 }
97 
99  bool ns_caller,
100  uint32_t privileged)
101 {
102  int flags = CMSE_MPU_READWRITE;
103 
104  /* In case of NS caller, only force unprivileged check, if the non secure
105  * Thread mode is unprivileged
106  */
107  if (ns_caller) {
108  CONTROL_Type ctrl;
109 
110  ctrl.w = __TZ_get_CONTROL_NS();
111  if (ctrl.b.nPRIV == 1) {
112  privileged = TFM_PARTITION_UNPRIVILEGED_MODE;
113  } else {
114  privileged = TFM_PARTITION_PRIVILEGED_MODE;
115  }
116  }
117 
118  if (privileged == TFM_PARTITION_UNPRIVILEGED_MODE) {
119  flags |= CMSE_MPU_UNPRIV;
120  }
121 
122  if (ns_caller) {
123  flags |= CMSE_NONSECURE;
124  }
125 
126  return has_access_to_region(p, s, flags);
127 }
#define TFM_PARTITION_UNPRIVILEGED_MODE
Definition: spm_func.h:32
tfm_status_e
Definition: tfm_api.h:45
enum tfm_status_e tfm_core_has_read_access_to_region(const void *p, size_t s, bool ns_caller, uint32_t privileged)
Check whether the current partition has read access to a memory range.
enum tfm_status_e tfm_core_has_write_access_to_region(const void *p, size_t s, bool ns_caller, uint32_t privileged)
Check whether the current partition has write access to a memory range.
#define TFM_PARTITION_PRIVILEGED_MODE
Definition: spm_func.h:33