TF-M Reference Manual  1.2.0
TrustedFirmware-M
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
tfm_boot_data.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include <stdint.h>
9 #include "tfm_boot_status.h"
10 #include "region_defs.h"
11 #include "tfm_memory_utils.h"
12 #include "tfm_api.h"
13 #include "tfm_core_utils.h"
14 #include "spm_partition_defs.h"
15 #ifdef TFM_PSA_API
16 #include "tfm_internal_defines.h"
17 #include "utilities.h"
18 #include "psa/service.h"
19 #include "tfm_thread.h"
20 #include "tfm_wait.h"
21 #include "tfm_spm_hal.h"
22 #include "spm_ipc.h"
23 #else
24 #include "spm_func.h"
25 #endif
26 
33 #define BOOT_DATA_VALID (1u)
34 
41 #define BOOT_DATA_INVALID (0u)
42 
49 static uint32_t is_boot_data_valid = BOOT_DATA_INVALID;
50 
58  uint32_t partition_id;
59  uint32_t major_type;
60 };
61 
69 static const struct boot_data_access_policy access_policy_table[] = {
71 };
72 
81 static int32_t tfm_core_check_boot_data_access_policy(uint8_t major_type)
82 {
83  uint32_t partition_id;
84  uint32_t i;
85  int32_t rc = -1;
86  const uint32_t array_size =
87  sizeof(access_policy_table) / sizeof(access_policy_table[0]);
88 
89 #ifndef TFM_PSA_API
90  uint32_t partition_idx = tfm_spm_partition_get_running_partition_idx();
91 
92  partition_id = tfm_spm_partition_get_partition_id(partition_idx);
93 #else
95 #endif
96 
97  for (i = 0; i < array_size; ++i) {
98  if (partition_id == access_policy_table[i].partition_id) {
99  if (major_type == access_policy_table[i].major_type) {
100  rc = 0;
101  break;
102  }
103  }
104  }
105 
106  return rc;
107 }
108 
109 /* Compile time check to verify that shared data region is not overlapping with
110  * non-secure data area.
111  */
112 #if ((BOOT_TFM_SHARED_DATA_BASE >= NS_DATA_START && \
113  BOOT_TFM_SHARED_DATA_BASE <= NS_DATA_LIMIT) || \
114  (BOOT_TFM_SHARED_DATA_LIMIT >= NS_DATA_START && \
115  BOOT_TFM_SHARED_DATA_LIMIT <= NS_DATA_LIMIT))
116 #error "Shared data area and non-secure data area is overlapping"
117 #endif
118 
120 {
121 #ifdef BOOT_DATA_AVAILABLE
122  struct tfm_boot_data *boot_data;
123 
124  boot_data = (struct tfm_boot_data *)BOOT_TFM_SHARED_DATA_BASE;
125 
126  if (boot_data->header.tlv_magic == SHARED_DATA_TLV_INFO_MAGIC) {
127  is_boot_data_valid = BOOT_DATA_VALID;
128  }
129 #else
130  is_boot_data_valid = BOOT_DATA_VALID;
131 #endif /* BOOT_DATA_AVAILABLE */
132 }
133 
134 void tfm_core_get_boot_data_handler(uint32_t args[])
135 {
136  uint8_t tlv_major = (uint8_t)args[0];
137  uint8_t *buf_start = (uint8_t *)args[1];
138  uint16_t buf_size = (uint16_t)args[2];
139  struct tfm_boot_data *boot_data;
140 #ifdef BOOT_DATA_AVAILABLE
141  uint8_t *ptr;
142  struct shared_data_tlv_entry tlv_entry;
143  uintptr_t tlv_end, offset;
144  size_t next_tlv_offset;
145 #endif /* BOOT_DATA_AVAILABLE */
146 #ifndef TFM_PSA_API
147  uint32_t running_partition_idx =
149  uint32_t res;
150 #else
151  struct partition_t *partition = NULL;
152  uint32_t privileged;
153 #endif
154 
155 #ifndef TFM_PSA_API
156  /*
157  * Make sure that the output pointer points to a memory area that is owned
158  * by the partition. And check 4 bytes alignment.
159  */
160  res = tfm_spm_check_buffer_access(running_partition_idx,
161  (void *)buf_start,
162  buf_size,
163  2);
164  if (!res) {
165  /* Not in accessible range, return error */
166  args[0] = (uint32_t)TFM_ERROR_INVALID_PARAMETER;
167  return;
168  }
169 #else
170  partition = tfm_spm_get_running_partition();
171  if (!partition) {
172  tfm_core_panic();
173  }
174  privileged =
176  partition_flags);
177 
178  if (tfm_memory_check(buf_start, buf_size, false, TFM_MEMORY_ACCESS_RW,
179  privileged) != IPC_SUCCESS) {
180  /* Not in accessible range, return error */
181  args[0] = (uint32_t)TFM_ERROR_INVALID_PARAMETER;
182  return;
183  }
184 #endif
185 
186  if (is_boot_data_valid != BOOT_DATA_VALID) {
187  args[0] = (uint32_t)TFM_ERROR_INVALID_PARAMETER;
188  return;
189  }
190 
191  /* Check whether caller has access right to given tlv_major_type */
192  if (tfm_core_check_boot_data_access_policy(tlv_major)) {
193  args[0] = (uint32_t)TFM_ERROR_INVALID_PARAMETER;
194  return;
195  }
196 
197 #ifdef BOOT_DATA_AVAILABLE
198  /* Get the boundaries of TLV section */
199  boot_data = (struct tfm_boot_data *)BOOT_TFM_SHARED_DATA_BASE;
200  tlv_end = BOOT_TFM_SHARED_DATA_BASE + boot_data->header.tlv_tot_len;
201  offset = BOOT_TFM_SHARED_DATA_BASE + SHARED_DATA_HEADER_SIZE;
202 #endif /* BOOT_DATA_AVAILABLE */
203 
204  /* Add header to output buffer as well */
205  if (buf_size < SHARED_DATA_HEADER_SIZE) {
206  args[0] = (uint32_t)TFM_ERROR_INVALID_PARAMETER;
207  return;
208  } else {
209  boot_data = (struct tfm_boot_data *)buf_start;
212  }
213 
214 #ifdef BOOT_DATA_AVAILABLE
215  ptr = boot_data->data;
216  /* Iterates over the TLV section and copy TLVs with requested major
217  * type to the provided buffer.
218  */
219  for (; offset < tlv_end; offset += next_tlv_offset) {
220  /* Create local copy to avoid unaligned access */
221  (void)spm_memcpy(&tlv_entry, (const void *)offset,
223 
224  next_tlv_offset = SHARED_DATA_ENTRY_HEADER_SIZE + tlv_entry.tlv_len;
225 
226  if (GET_MAJOR(tlv_entry.tlv_type) == tlv_major) {
227  /* Check buffer overflow */
228  if (((ptr - buf_start) + next_tlv_offset) > buf_size) {
229  args[0] = (uint32_t)TFM_ERROR_INVALID_PARAMETER;
230  return;
231  }
232 
233  (void)spm_memcpy(ptr, (const void *)offset, next_tlv_offset);
234  ptr += next_tlv_offset;
235  boot_data->header.tlv_tot_len += next_tlv_offset;
236  }
237  }
238 #endif /* BOOT_DATA_AVAILABLE */
239 
240  args[0] = (uint32_t)TFM_SUCCESS;
241  return;
242 }
#define GET_MAJOR(tlv_type)
#define TLV_MAJOR_IAS
void tfm_core_validate_boot_data(void)
Validate the content of shared memory area, which stores the shared data between bootloader and runti...
uint32_t tfm_spm_partition_get_privileged_mode(uint32_t partition_flags)
Get the current partition mode.
Definition: spm_func.c:713
void tfm_core_get_boot_data_handler(uint32_t args[])
Retrieve secure partition related data from shared memory area, which stores shared data between boot...
uint16_t tlv_len
#define SHARED_DATA_ENTRY_HEADER_SIZE
#define SHARED_DATA_HEADER_SIZE
#define SHARED_DATA_TLV_INFO_MAGIC
#define TFM_SP_INITIAL_ATTESTATION
Definition: pid.h:22
void tfm_core_panic(void)
Definition: utilities.c:11
int32_t tfm_memory_check(const void *buffer, size_t len, bool ns_caller, enum tfm_memory_access_e access, uint32_t privileged)
Check the memory reference is valid.
Definition: spm_ipc.c:596
uint16_t tlv_type
int32_t tfm_spm_check_buffer_access(uint32_t partition_idx, void *start_addr, size_t len, uint32_t alignment)
Check whether a buffer is ok for writing to by the privileged API function.
Definition: spm_func.c:818
struct partition_t * tfm_spm_get_running_partition(void)
Get current running partition context.
Definition: spm_ipc.c:384
Defines the access policy of secure partitions to data items in shared data area (between bootloader ...
Definition: tfm_boot_data.c:57
Store the data for the runtime SW.
#define BOOT_DATA_INVALID
Indicates that shared data between bootloader and runtime firmware was failed on sanity check...
Definition: tfm_boot_data.c:41
void * spm_memcpy(void *dest, const void *src, size_t n)
Memory copy function for TF-M core.
struct shared_data_tlv_header header
#define BOOT_DATA_VALID
Indicates that shared data between bootloader and runtime firmware was passed the sanity check with s...
Definition: tfm_boot_data.c:33
#define IPC_SUCCESS
const struct partition_static_t * static_data
Definition: spm_ipc.h:104
uint32_t tfm_spm_partition_get_partition_id(uint32_t partition_idx)
Get the id of the partition for its index from the db.
Definition: spm_func.c:707
uint32_t tfm_spm_partition_get_running_partition_idx(void)
Returns the index of the partition that has running state.
Definition: spm_func.c:1357
uint32_t tfm_spm_partition_get_running_partition_id(void)
Get the running partition ID.
Definition: spm_ipc.c:584