blob: 0dc312446b040fd8bb331babf5b303b46f1c0513 [file] [log] [blame]
Tamas Ban9ff535b2018-09-18 08:15:18 +01001/*
David Vinczee13a48b2020-01-08 17:42:30 +01002 * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
Tamas Ban9ff535b2018-09-18 08:15:18 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8#include <stdint.h>
Mingyang Sun67a1c0e2020-06-04 17:18:16 +08009#include "tfm_boot_status.h"
David Hu1cb73db2019-09-06 13:29:22 +080010#include "region_defs.h"
Tamas Ban8bd24b72019-02-19 12:13:13 +000011#include "tfm_memory_utils.h"
Tamas Ban9ff535b2018-09-18 08:15:18 +010012#include "tfm_internal.h"
13#include "tfm_api.h"
Mingyang Sun94b1b412019-09-20 15:11:14 +080014#include "tfm_core_utils.h"
Mingyang Sunc3123ec2020-06-11 17:43:58 +080015#include "spm_api.h"
16#include "spm_partition_defs.h"
Edison Ai2e413a62019-05-16 13:46:00 +080017#ifdef TFM_PSA_API
18#include "tfm_internal_defines.h"
19#include "tfm_utils.h"
Jamie Foxcc31d402019-01-28 17:13:52 +000020#include "psa/service.h"
Edison Ai2e413a62019-05-16 13:46:00 +080021#include "tfm_thread.h"
22#include "tfm_wait.h"
23#include "tfm_message_queue.h"
Mingyang Sun5e13aa72019-07-10 10:30:16 +080024#include "tfm_spm_hal.h"
Mingyang Sunc3123ec2020-06-11 17:43:58 +080025#include "spm_db.h"
Edison Ai2e413a62019-05-16 13:46:00 +080026#endif
Tamas Ban9ff535b2018-09-18 08:15:18 +010027
28/*!
29 * \def BOOT_DATA_VALID
30 *
31 * \brief Indicates that shared data between bootloader and runtime firmware was
32 * passed the sanity check with success.
33 */
34#define BOOT_DATA_VALID (1u)
35
36/*!
37 * \def BOOT_DATA_INVALID
38 *
39 * \brief Indicates that shared data between bootloader and runtime firmware was
40 * failed on sanity check.
41 */
42#define BOOT_DATA_INVALID (0u)
43
44/*!
45 * \var is_boot_data_valid
46 *
47 * \brief Indicates the status of shared data between bootloader and runtime
48 * firmware
49 */
50static uint32_t is_boot_data_valid = BOOT_DATA_INVALID;
51
Tamas Ban6bd5b812019-09-25 09:34:11 +010052/*!
53 * \struct boot_data_access_policy
54 *
55 * \brief Defines the access policy of secure partitions to data items in shared
56 * data area (between bootloader and runtime firmware).
57 */
58struct boot_data_access_policy {
59 uint32_t partition_id;
60 uint32_t major_type;
61};
62
63/*!
64 * \var access_policy_table
65 *
66 * \brief Contains the partition_id and major_type assignments. This describes
67 * which secure partition is allowed to access which data item
68 * (identified by major_type).
69 */
70static const struct boot_data_access_policy access_policy_table[] = {
Edison Aib2134e62019-10-11 18:24:47 +080071 {TFM_SP_INITIAL_ATTESTATION, TLV_MAJOR_IAS},
Tamas Ban6bd5b812019-09-25 09:34:11 +010072};
73
74/*!
75 * \brief Verify the access right of the active secure partition to the
76 * specified data type in the shared data area.
77 *
78 * \param[in] major_type Data type identifier.
79 *
80 * \return Returns 0 in case of success, otherwise -1.
81 */
82static int32_t tfm_core_check_boot_data_access_policy(uint8_t major_type)
83{
84 uint32_t partition_id;
85 uint32_t i;
86 int32_t rc = -1;
87 const uint32_t array_size =
88 sizeof(access_policy_table) / sizeof(access_policy_table[0]);
89
90#ifndef TFM_PSA_API
91 uint32_t partition_idx = tfm_spm_partition_get_running_partition_idx();
92
93 partition_id = tfm_spm_partition_get_partition_id(partition_idx);
94#else
95 partition_id = tfm_spm_partition_get_running_partition_id();
96#endif
97
98 for (i = 0; i < array_size; ++i) {
99 if (partition_id == access_policy_table[i].partition_id) {
100 if (major_type == access_policy_table[i].major_type) {
101 rc = 0;
102 break;
103 }
104 }
105 }
106
107 return rc;
108}
109
Tamas Ban6d2e4302019-10-03 12:37:09 +0100110/* Compile time check to verify that shared data region is not overlapping with
111 * non-secure data area.
112 */
113#if ((BOOT_TFM_SHARED_DATA_BASE >= NS_DATA_START && \
114 BOOT_TFM_SHARED_DATA_BASE <= NS_DATA_LIMIT) || \
115 (BOOT_TFM_SHARED_DATA_LIMIT >= NS_DATA_START && \
116 BOOT_TFM_SHARED_DATA_LIMIT <= NS_DATA_LIMIT))
117#error "Shared data area and non-secure data area is overlapping"
118#endif
119
Tamas Ban9ff535b2018-09-18 08:15:18 +0100120void tfm_core_validate_boot_data(void)
121{
David Vinczee13a48b2020-01-08 17:42:30 +0100122#ifdef BOOT_DATA_AVAILABLE
Tamas Bana24ce042019-02-20 11:50:22 +0000123 struct tfm_boot_data *boot_data;
Tamas Ban9ff535b2018-09-18 08:15:18 +0100124
Tamas Bana24ce042019-02-20 11:50:22 +0000125 boot_data = (struct tfm_boot_data *)BOOT_TFM_SHARED_DATA_BASE;
Tamas Ban9ff535b2018-09-18 08:15:18 +0100126
Tamas Bana24ce042019-02-20 11:50:22 +0000127 if (boot_data->header.tlv_magic == SHARED_DATA_TLV_INFO_MAGIC) {
Tamas Ban9ff535b2018-09-18 08:15:18 +0100128 is_boot_data_valid = BOOT_DATA_VALID;
129 }
David Vinczee13a48b2020-01-08 17:42:30 +0100130#else
131 is_boot_data_valid = BOOT_DATA_VALID;
132#endif /* BOOT_DATA_AVAILABLE */
Tamas Ban9ff535b2018-09-18 08:15:18 +0100133}
134
135void tfm_core_get_boot_data_handler(uint32_t args[])
136{
137 uint8_t tlv_major = (uint8_t)args[0];
Tamas Banc43181d2019-02-18 14:21:35 +0000138 uint8_t *buf_start = (uint8_t *)args[1];
Tamas Ban9ff535b2018-09-18 08:15:18 +0100139 uint16_t buf_size = (uint16_t)args[2];
Tamas Bana24ce042019-02-20 11:50:22 +0000140 struct tfm_boot_data *boot_data;
David Vinczee13a48b2020-01-08 17:42:30 +0100141#ifdef BOOT_DATA_AVAILABLE
TTornblomfaf74f52020-03-04 17:56:27 +0100142 uint8_t *ptr;
Tamas Banc43181d2019-02-18 14:21:35 +0000143 struct shared_data_tlv_entry tlv_entry;
Tamas Ban9ff535b2018-09-18 08:15:18 +0100144 uintptr_t tlv_end, offset;
David Vincze53998032020-06-10 15:54:31 +0200145 size_t next_tlv_offset;
David Vinczee13a48b2020-01-08 17:42:30 +0100146#endif /* BOOT_DATA_AVAILABLE */
Edison Ai2e413a62019-05-16 13:46:00 +0800147#ifndef TFM_PSA_API
148 uint32_t running_partition_idx =
149 tfm_spm_partition_get_running_partition_idx();
Tamas Ban9ff535b2018-09-18 08:15:18 +0100150 uint32_t res;
Edison Ai2e413a62019-05-16 13:46:00 +0800151#else
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800152 struct spm_partition_desc_t *partition = NULL;
Edison Ai2e413a62019-05-16 13:46:00 +0800153 uint32_t privileged;
154#endif
Tamas Ban9ff535b2018-09-18 08:15:18 +0100155
Edison Ai2e413a62019-05-16 13:46:00 +0800156#ifndef TFM_PSA_API
Mingyang Sunabb1aab2020-02-18 13:49:08 +0800157 /*
158 * Make sure that the output pointer points to a memory area that is owned
159 * by the partition. And check 4 bytes alignment.
Tamas Ban9ff535b2018-09-18 08:15:18 +0100160 */
Mingyang Sunabb1aab2020-02-18 13:49:08 +0800161 res = tfm_spm_check_buffer_access(running_partition_idx,
162 (void *)buf_start,
163 buf_size,
164 2);
Tamas Ban9ff535b2018-09-18 08:15:18 +0100165 if (!res) {
166 /* Not in accessible range, return error */
Hugues de Valon99578562019-06-18 16:08:51 +0100167 args[0] = (uint32_t)TFM_ERROR_INVALID_PARAMETER;
Tamas Ban9ff535b2018-09-18 08:15:18 +0100168 return;
169 }
Edison Ai2e413a62019-05-16 13:46:00 +0800170#else
171 partition = tfm_spm_get_running_partition();
172 if (!partition) {
Edison Ai9059ea02019-11-28 13:46:14 +0800173 tfm_core_panic();
Edison Ai2e413a62019-05-16 13:46:00 +0800174 }
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800175 privileged =
Summer Qin75f0d752019-08-27 14:38:20 +0800176 tfm_spm_partition_get_privileged_mode(partition->static_data->
177 partition_flags);
Edison Ai2e413a62019-05-16 13:46:00 +0800178
179 if (tfm_memory_check(buf_start, buf_size, false, TFM_MEMORY_ACCESS_RW,
180 privileged) != IPC_SUCCESS) {
181 /* Not in accessible range, return error */
Hugues de Valon99578562019-06-18 16:08:51 +0100182 args[0] = (uint32_t)TFM_ERROR_INVALID_PARAMETER;
Edison Ai2e413a62019-05-16 13:46:00 +0800183 return;
184 }
185#endif
Tamas Ban9ff535b2018-09-18 08:15:18 +0100186
Tamas Ban9ff535b2018-09-18 08:15:18 +0100187 if (is_boot_data_valid != BOOT_DATA_VALID) {
Hugues de Valon99578562019-06-18 16:08:51 +0100188 args[0] = (uint32_t)TFM_ERROR_INVALID_PARAMETER;
Tamas Ban9ff535b2018-09-18 08:15:18 +0100189 return;
190 }
191
Tamas Ban6bd5b812019-09-25 09:34:11 +0100192 /* Check whether caller has access right to given tlv_major_type */
193 if (tfm_core_check_boot_data_access_policy(tlv_major)) {
194 args[0] = (uint32_t)TFM_ERROR_INVALID_PARAMETER;
195 return;
196 }
197
David Vinczee13a48b2020-01-08 17:42:30 +0100198#ifdef BOOT_DATA_AVAILABLE
Tamas Ban9ff535b2018-09-18 08:15:18 +0100199 /* Get the boundaries of TLV section */
Tamas Bana24ce042019-02-20 11:50:22 +0000200 boot_data = (struct tfm_boot_data *)BOOT_TFM_SHARED_DATA_BASE;
201 tlv_end = BOOT_TFM_SHARED_DATA_BASE + boot_data->header.tlv_tot_len;
Tamas Ban9ff535b2018-09-18 08:15:18 +0100202 offset = BOOT_TFM_SHARED_DATA_BASE + SHARED_DATA_HEADER_SIZE;
David Vinczee13a48b2020-01-08 17:42:30 +0100203#endif /* BOOT_DATA_AVAILABLE */
Tamas Ban9ff535b2018-09-18 08:15:18 +0100204
205 /* Add header to output buffer as well */
206 if (buf_size < SHARED_DATA_HEADER_SIZE) {
Hugues de Valon99578562019-06-18 16:08:51 +0100207 args[0] = (uint32_t)TFM_ERROR_INVALID_PARAMETER;
Tamas Ban9ff535b2018-09-18 08:15:18 +0100208 return;
209 } else {
Tamas Bana24ce042019-02-20 11:50:22 +0000210 boot_data = (struct tfm_boot_data *)buf_start;
211 boot_data->header.tlv_magic = SHARED_DATA_TLV_INFO_MAGIC;
212 boot_data->header.tlv_tot_len = SHARED_DATA_HEADER_SIZE;
Tamas Ban9ff535b2018-09-18 08:15:18 +0100213 }
214
David Vinczee13a48b2020-01-08 17:42:30 +0100215#ifdef BOOT_DATA_AVAILABLE
TTornblomfaf74f52020-03-04 17:56:27 +0100216 ptr = boot_data->data;
Tamas Ban9ff535b2018-09-18 08:15:18 +0100217 /* Iterates over the TLV section and copy TLVs with requested major
218 * type to the provided buffer.
219 */
David Vincze53998032020-06-10 15:54:31 +0200220 for (; offset < tlv_end; offset += next_tlv_offset) {
Tamas Banc43181d2019-02-18 14:21:35 +0000221 /* Create local copy to avoid unaligned access */
Mingyang Sun94b1b412019-09-20 15:11:14 +0800222 (void)tfm_core_util_memcpy(&tlv_entry,
223 (const void *)offset,
224 SHARED_DATA_ENTRY_HEADER_SIZE);
David Vincze53998032020-06-10 15:54:31 +0200225#ifdef LEGACY_TFM_TLV_HEADER
226 next_tlv_offset = tlv_entry.tlv_len;
227#else
228 next_tlv_offset = SHARED_DATA_ENTRY_HEADER_SIZE + tlv_entry.tlv_len;
229#endif
Tamas Banc43181d2019-02-18 14:21:35 +0000230 if (GET_MAJOR(tlv_entry.tlv_type) == tlv_major) {
Tamas Ban9ff535b2018-09-18 08:15:18 +0100231 /* Check buffer overflow */
David Vincze53998032020-06-10 15:54:31 +0200232 if (((ptr - buf_start) + next_tlv_offset) > buf_size) {
Hugues de Valon99578562019-06-18 16:08:51 +0100233 args[0] = (uint32_t)TFM_ERROR_INVALID_PARAMETER;
Tamas Ban9ff535b2018-09-18 08:15:18 +0100234 return;
235 }
236
Mingyang Sun94b1b412019-09-20 15:11:14 +0800237 (void)tfm_core_util_memcpy(ptr, (const void *)offset,
David Vincze53998032020-06-10 15:54:31 +0200238 next_tlv_offset);
239 ptr += next_tlv_offset;
240 boot_data->header.tlv_tot_len += next_tlv_offset;
Tamas Ban9ff535b2018-09-18 08:15:18 +0100241 }
242 }
David Vinczee13a48b2020-01-08 17:42:30 +0100243#endif /* BOOT_DATA_AVAILABLE */
244
Hugues de Valon99578562019-06-18 16:08:51 +0100245 args[0] = (uint32_t)TFM_SUCCESS;
Tamas Ban9ff535b2018-09-18 08:15:18 +0100246 return;
247}