blob: 1b9ed64e040545439218272586b9731e45247d5f [file] [log] [blame]
Tamas Ban9ff535b2018-09-18 08:15:18 +01001/*
Sherry Zhang07b42412021-01-07 14:19:41 +08002 * Copyright (c) 2018-2021, 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>
Xinyu Zhangade2e0a2021-03-18 16:20:54 +08009#include "array.h"
Mingyang Sun67a1c0e2020-06-04 17:18:16 +080010#include "tfm_boot_status.h"
David Hu1cb73db2019-09-06 13:29:22 +080011#include "region_defs.h"
Tamas Ban8bd24b72019-02-19 12:13:13 +000012#include "tfm_memory_utils.h"
Tamas Ban9ff535b2018-09-18 08:15:18 +010013#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_partition_defs.h"
Edison Ai2e413a62019-05-16 13:46:00 +080016#ifdef TFM_PSA_API
Ken Liubcae38b2021-01-20 15:47:44 +080017#include "internal_errors.h"
Summer Qin5fdcf632020-06-22 16:49:24 +080018#include "utilities.h"
Jamie Foxcc31d402019-01-28 17:13:52 +000019#include "psa/service.h"
Edison Ai2e413a62019-05-16 13:46:00 +080020#include "tfm_thread.h"
21#include "tfm_wait.h"
Mingyang Sun5e13aa72019-07-10 10:30:16 +080022#include "tfm_spm_hal.h"
Mingyang Sun7397b4f2020-06-17 15:07:45 +080023#include "spm_ipc.h"
Mingyang Sun2b352662021-04-21 11:35:43 +080024#include "load/partition_defs.h"
Mingyang Sun7397b4f2020-06-17 15:07:45 +080025#else
26#include "spm_func.h"
Edison Ai2e413a62019-05-16 13:46:00 +080027#endif
Tamas Ban9ff535b2018-09-18 08:15:18 +010028
29/*!
30 * \def BOOT_DATA_VALID
31 *
32 * \brief Indicates that shared data between bootloader and runtime firmware was
33 * passed the sanity check with success.
34 */
35#define BOOT_DATA_VALID (1u)
36
37/*!
38 * \def BOOT_DATA_INVALID
39 *
40 * \brief Indicates that shared data between bootloader and runtime firmware was
41 * failed on sanity check.
42 */
43#define BOOT_DATA_INVALID (0u)
44
45/*!
46 * \var is_boot_data_valid
47 *
48 * \brief Indicates the status of shared data between bootloader and runtime
49 * firmware
50 */
51static uint32_t is_boot_data_valid = BOOT_DATA_INVALID;
52
Tamas Ban6bd5b812019-09-25 09:34:11 +010053/*!
54 * \struct boot_data_access_policy
55 *
56 * \brief Defines the access policy of secure partitions to data items in shared
57 * data area (between bootloader and runtime firmware).
58 */
59struct boot_data_access_policy {
60 uint32_t partition_id;
61 uint32_t major_type;
62};
63
64/*!
65 * \var access_policy_table
66 *
67 * \brief Contains the partition_id and major_type assignments. This describes
68 * which secure partition is allowed to access which data item
69 * (identified by major_type).
70 */
71static const struct boot_data_access_policy access_policy_table[] = {
Edison Aib2134e62019-10-11 18:24:47 +080072 {TFM_SP_INITIAL_ATTESTATION, TLV_MAJOR_IAS},
Sherry Zhang07b42412021-01-07 14:19:41 +080073 {TFM_SP_FWU, TLV_MAJOR_FWU},
Tamas Ban6bd5b812019-09-25 09:34:11 +010074};
75
76/*!
77 * \brief Verify the access right of the active secure partition to the
78 * specified data type in the shared data area.
79 *
80 * \param[in] major_type Data type identifier.
81 *
82 * \return Returns 0 in case of success, otherwise -1.
83 */
84static int32_t tfm_core_check_boot_data_access_policy(uint8_t major_type)
85{
86 uint32_t partition_id;
87 uint32_t i;
88 int32_t rc = -1;
Xinyu Zhangade2e0a2021-03-18 16:20:54 +080089 const uint32_t array_size = ARRAY_SIZE(access_policy_table);
Tamas Ban6bd5b812019-09-25 09:34:11 +010090
91#ifndef TFM_PSA_API
92 uint32_t partition_idx = tfm_spm_partition_get_running_partition_idx();
93
94 partition_id = tfm_spm_partition_get_partition_id(partition_idx);
95#else
96 partition_id = tfm_spm_partition_get_running_partition_id();
97#endif
98
99 for (i = 0; i < array_size; ++i) {
100 if (partition_id == access_policy_table[i].partition_id) {
101 if (major_type == access_policy_table[i].major_type) {
102 rc = 0;
103 break;
104 }
105 }
106 }
107
108 return rc;
109}
110
Tamas Ban6d2e4302019-10-03 12:37:09 +0100111/* Compile time check to verify that shared data region is not overlapping with
112 * non-secure data area.
113 */
114#if ((BOOT_TFM_SHARED_DATA_BASE >= NS_DATA_START && \
115 BOOT_TFM_SHARED_DATA_BASE <= NS_DATA_LIMIT) || \
116 (BOOT_TFM_SHARED_DATA_LIMIT >= NS_DATA_START && \
117 BOOT_TFM_SHARED_DATA_LIMIT <= NS_DATA_LIMIT))
118#error "Shared data area and non-secure data area is overlapping"
119#endif
120
Tamas Ban9ff535b2018-09-18 08:15:18 +0100121void tfm_core_validate_boot_data(void)
122{
David Vinczee13a48b2020-01-08 17:42:30 +0100123#ifdef BOOT_DATA_AVAILABLE
Tamas Bana24ce042019-02-20 11:50:22 +0000124 struct tfm_boot_data *boot_data;
Tamas Ban9ff535b2018-09-18 08:15:18 +0100125
Tamas Bana24ce042019-02-20 11:50:22 +0000126 boot_data = (struct tfm_boot_data *)BOOT_TFM_SHARED_DATA_BASE;
Tamas Ban9ff535b2018-09-18 08:15:18 +0100127
Tamas Bana24ce042019-02-20 11:50:22 +0000128 if (boot_data->header.tlv_magic == SHARED_DATA_TLV_INFO_MAGIC) {
Tamas Ban9ff535b2018-09-18 08:15:18 +0100129 is_boot_data_valid = BOOT_DATA_VALID;
130 }
David Vinczee13a48b2020-01-08 17:42:30 +0100131#else
132 is_boot_data_valid = BOOT_DATA_VALID;
133#endif /* BOOT_DATA_AVAILABLE */
Tamas Ban9ff535b2018-09-18 08:15:18 +0100134}
135
136void tfm_core_get_boot_data_handler(uint32_t args[])
137{
138 uint8_t tlv_major = (uint8_t)args[0];
Tamas Banc43181d2019-02-18 14:21:35 +0000139 uint8_t *buf_start = (uint8_t *)args[1];
Tamas Ban9ff535b2018-09-18 08:15:18 +0100140 uint16_t buf_size = (uint16_t)args[2];
Tamas Bana24ce042019-02-20 11:50:22 +0000141 struct tfm_boot_data *boot_data;
David Vinczee13a48b2020-01-08 17:42:30 +0100142#ifdef BOOT_DATA_AVAILABLE
TTornblomfaf74f52020-03-04 17:56:27 +0100143 uint8_t *ptr;
Tamas Banc43181d2019-02-18 14:21:35 +0000144 struct shared_data_tlv_entry tlv_entry;
Tamas Ban9ff535b2018-09-18 08:15:18 +0100145 uintptr_t tlv_end, offset;
David Vincze53998032020-06-10 15:54:31 +0200146 size_t next_tlv_offset;
David Vinczee13a48b2020-01-08 17:42:30 +0100147#endif /* BOOT_DATA_AVAILABLE */
Edison Ai2e413a62019-05-16 13:46:00 +0800148#ifndef TFM_PSA_API
149 uint32_t running_partition_idx =
150 tfm_spm_partition_get_running_partition_idx();
Tamas Ban9ff535b2018-09-18 08:15:18 +0100151 uint32_t res;
Edison Ai2e413a62019-05-16 13:46:00 +0800152#else
Mingyang Sunae70d8d2020-06-30 15:56:05 +0800153 struct partition_t *partition = NULL;
Edison Ai2e413a62019-05-16 13:46:00 +0800154 uint32_t privileged;
155#endif
Tamas Ban9ff535b2018-09-18 08:15:18 +0100156
Edison Ai2e413a62019-05-16 13:46:00 +0800157#ifndef TFM_PSA_API
Mingyang Sunabb1aab2020-02-18 13:49:08 +0800158 /*
159 * Make sure that the output pointer points to a memory area that is owned
160 * by the partition. And check 4 bytes alignment.
Tamas Ban9ff535b2018-09-18 08:15:18 +0100161 */
Mingyang Sunabb1aab2020-02-18 13:49:08 +0800162 res = tfm_spm_check_buffer_access(running_partition_idx,
163 (void *)buf_start,
164 buf_size,
165 2);
Tamas Ban9ff535b2018-09-18 08:15:18 +0100166 if (!res) {
167 /* Not in accessible range, return error */
Hugues de Valon99578562019-06-18 16:08:51 +0100168 args[0] = (uint32_t)TFM_ERROR_INVALID_PARAMETER;
Tamas Ban9ff535b2018-09-18 08:15:18 +0100169 return;
170 }
Edison Ai2e413a62019-05-16 13:46:00 +0800171#else
172 partition = tfm_spm_get_running_partition();
173 if (!partition) {
Edison Ai9059ea02019-11-28 13:46:14 +0800174 tfm_core_panic();
Edison Ai2e413a62019-05-16 13:46:00 +0800175 }
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800176 privileged =
Ken Liuacd2a572021-05-12 16:19:04 +0800177 tfm_spm_partition_get_privileged_mode(partition->p_ldinf->flags);
Edison Ai2e413a62019-05-16 13:46:00 +0800178
179 if (tfm_memory_check(buf_start, buf_size, false, TFM_MEMORY_ACCESS_RW,
Ken Liubcae38b2021-01-20 15:47:44 +0800180 privileged) != SPM_SUCCESS) {
Edison Ai2e413a62019-05-16 13:46:00 +0800181 /* 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 */
Summer Qinf24dbb52020-07-23 14:53:54 +0800222 (void)spm_memcpy(&tlv_entry, (const void *)offset,
223 SHARED_DATA_ENTRY_HEADER_SIZE);
Balint Matyie5cadb22020-07-06 14:43:37 +0100224
David Vincze53998032020-06-10 15:54:31 +0200225 next_tlv_offset = SHARED_DATA_ENTRY_HEADER_SIZE + tlv_entry.tlv_len;
Balint Matyie5cadb22020-07-06 14:43:37 +0100226
Tamas Banc43181d2019-02-18 14:21:35 +0000227 if (GET_MAJOR(tlv_entry.tlv_type) == tlv_major) {
Tamas Ban9ff535b2018-09-18 08:15:18 +0100228 /* Check buffer overflow */
David Vincze53998032020-06-10 15:54:31 +0200229 if (((ptr - buf_start) + next_tlv_offset) > buf_size) {
Hugues de Valon99578562019-06-18 16:08:51 +0100230 args[0] = (uint32_t)TFM_ERROR_INVALID_PARAMETER;
Tamas Ban9ff535b2018-09-18 08:15:18 +0100231 return;
232 }
233
Summer Qinf24dbb52020-07-23 14:53:54 +0800234 (void)spm_memcpy(ptr, (const void *)offset, next_tlv_offset);
David Vincze53998032020-06-10 15:54:31 +0200235 ptr += next_tlv_offset;
236 boot_data->header.tlv_tot_len += next_tlv_offset;
Tamas Ban9ff535b2018-09-18 08:15:18 +0100237 }
238 }
David Vinczee13a48b2020-01-08 17:42:30 +0100239#endif /* BOOT_DATA_AVAILABLE */
240
Hugues de Valon99578562019-06-18 16:08:51 +0100241 args[0] = (uint32_t)TFM_SUCCESS;
Tamas Ban9ff535b2018-09-18 08:15:18 +0100242 return;
243}