blob: 8003f2140a7136a1f282383dbc863c2b9e509f1e [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"
24#else
25#include "spm_func.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},
Sherry Zhang07b42412021-01-07 14:19:41 +080072 {TFM_SP_FWU, TLV_MAJOR_FWU},
Tamas Ban6bd5b812019-09-25 09:34:11 +010073};
74
75/*!
76 * \brief Verify the access right of the active secure partition to the
77 * specified data type in the shared data area.
78 *
79 * \param[in] major_type Data type identifier.
80 *
81 * \return Returns 0 in case of success, otherwise -1.
82 */
83static int32_t tfm_core_check_boot_data_access_policy(uint8_t major_type)
84{
85 uint32_t partition_id;
86 uint32_t i;
87 int32_t rc = -1;
Xinyu Zhangade2e0a2021-03-18 16:20:54 +080088 const uint32_t array_size = ARRAY_SIZE(access_policy_table);
Tamas Ban6bd5b812019-09-25 09:34:11 +010089
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 Sunae70d8d2020-06-30 15:56:05 +0800152 struct partition_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 =
Mingyang Sun56c59692020-07-20 17:02:19 +0800176 tfm_spm_partition_get_privileged_mode(partition->p_static->flags);
Edison Ai2e413a62019-05-16 13:46:00 +0800177
178 if (tfm_memory_check(buf_start, buf_size, false, TFM_MEMORY_ACCESS_RW,
Ken Liubcae38b2021-01-20 15:47:44 +0800179 privileged) != SPM_SUCCESS) {
Edison Ai2e413a62019-05-16 13:46:00 +0800180 /* Not in accessible range, return error */
Hugues de Valon99578562019-06-18 16:08:51 +0100181 args[0] = (uint32_t)TFM_ERROR_INVALID_PARAMETER;
Edison Ai2e413a62019-05-16 13:46:00 +0800182 return;
183 }
184#endif
Tamas Ban9ff535b2018-09-18 08:15:18 +0100185
Tamas Ban9ff535b2018-09-18 08:15:18 +0100186 if (is_boot_data_valid != BOOT_DATA_VALID) {
Hugues de Valon99578562019-06-18 16:08:51 +0100187 args[0] = (uint32_t)TFM_ERROR_INVALID_PARAMETER;
Tamas Ban9ff535b2018-09-18 08:15:18 +0100188 return;
189 }
190
Tamas Ban6bd5b812019-09-25 09:34:11 +0100191 /* 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
David Vinczee13a48b2020-01-08 17:42:30 +0100197#ifdef BOOT_DATA_AVAILABLE
Tamas Ban9ff535b2018-09-18 08:15:18 +0100198 /* Get the boundaries of TLV section */
Tamas Bana24ce042019-02-20 11:50:22 +0000199 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;
Tamas Ban9ff535b2018-09-18 08:15:18 +0100201 offset = BOOT_TFM_SHARED_DATA_BASE + SHARED_DATA_HEADER_SIZE;
David Vinczee13a48b2020-01-08 17:42:30 +0100202#endif /* BOOT_DATA_AVAILABLE */
Tamas Ban9ff535b2018-09-18 08:15:18 +0100203
204 /* Add header to output buffer as well */
205 if (buf_size < SHARED_DATA_HEADER_SIZE) {
Hugues de Valon99578562019-06-18 16:08:51 +0100206 args[0] = (uint32_t)TFM_ERROR_INVALID_PARAMETER;
Tamas Ban9ff535b2018-09-18 08:15:18 +0100207 return;
208 } else {
Tamas Bana24ce042019-02-20 11:50:22 +0000209 boot_data = (struct tfm_boot_data *)buf_start;
210 boot_data->header.tlv_magic = SHARED_DATA_TLV_INFO_MAGIC;
211 boot_data->header.tlv_tot_len = SHARED_DATA_HEADER_SIZE;
Tamas Ban9ff535b2018-09-18 08:15:18 +0100212 }
213
David Vinczee13a48b2020-01-08 17:42:30 +0100214#ifdef BOOT_DATA_AVAILABLE
TTornblomfaf74f52020-03-04 17:56:27 +0100215 ptr = boot_data->data;
Tamas Ban9ff535b2018-09-18 08:15:18 +0100216 /* Iterates over the TLV section and copy TLVs with requested major
217 * type to the provided buffer.
218 */
David Vincze53998032020-06-10 15:54:31 +0200219 for (; offset < tlv_end; offset += next_tlv_offset) {
Tamas Banc43181d2019-02-18 14:21:35 +0000220 /* Create local copy to avoid unaligned access */
Summer Qinf24dbb52020-07-23 14:53:54 +0800221 (void)spm_memcpy(&tlv_entry, (const void *)offset,
222 SHARED_DATA_ENTRY_HEADER_SIZE);
Balint Matyie5cadb22020-07-06 14:43:37 +0100223
David Vincze53998032020-06-10 15:54:31 +0200224 next_tlv_offset = SHARED_DATA_ENTRY_HEADER_SIZE + tlv_entry.tlv_len;
Balint Matyie5cadb22020-07-06 14:43:37 +0100225
Tamas Banc43181d2019-02-18 14:21:35 +0000226 if (GET_MAJOR(tlv_entry.tlv_type) == tlv_major) {
Tamas Ban9ff535b2018-09-18 08:15:18 +0100227 /* Check buffer overflow */
David Vincze53998032020-06-10 15:54:31 +0200228 if (((ptr - buf_start) + next_tlv_offset) > buf_size) {
Hugues de Valon99578562019-06-18 16:08:51 +0100229 args[0] = (uint32_t)TFM_ERROR_INVALID_PARAMETER;
Tamas Ban9ff535b2018-09-18 08:15:18 +0100230 return;
231 }
232
Summer Qinf24dbb52020-07-23 14:53:54 +0800233 (void)spm_memcpy(ptr, (const void *)offset, next_tlv_offset);
David Vincze53998032020-06-10 15:54:31 +0200234 ptr += next_tlv_offset;
235 boot_data->header.tlv_tot_len += next_tlv_offset;
Tamas Ban9ff535b2018-09-18 08:15:18 +0100236 }
237 }
David Vinczee13a48b2020-01-08 17:42:30 +0100238#endif /* BOOT_DATA_AVAILABLE */
239
Hugues de Valon99578562019-06-18 16:08:51 +0100240 args[0] = (uint32_t)TFM_SUCCESS;
Tamas Ban9ff535b2018-09-18 08:15:18 +0100241 return;
242}