blob: fe77002fc79444ac9a277af38c05569c1310245c [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_api.h"
Mingyang Sun94b1b412019-09-20 15:11:14 +080013#include "tfm_core_utils.h"
Mingyang Sunc3123ec2020-06-11 17:43:58 +080014#include "spm_partition_defs.h"
Edison Ai2e413a62019-05-16 13:46:00 +080015#ifdef TFM_PSA_API
16#include "tfm_internal_defines.h"
Summer Qin5fdcf632020-06-22 16:49:24 +080017#include "utilities.h"
Jamie Foxcc31d402019-01-28 17:13:52 +000018#include "psa/service.h"
Edison Ai2e413a62019-05-16 13:46:00 +080019#include "tfm_thread.h"
20#include "tfm_wait.h"
Mingyang Sun5e13aa72019-07-10 10:30:16 +080021#include "tfm_spm_hal.h"
Mingyang Sun7397b4f2020-06-17 15:07:45 +080022#include "spm_ipc.h"
23#else
24#include "spm_func.h"
Edison Ai2e413a62019-05-16 13:46:00 +080025#endif
Tamas Ban9ff535b2018-09-18 08:15:18 +010026
27/*!
28 * \def BOOT_DATA_VALID
29 *
30 * \brief Indicates that shared data between bootloader and runtime firmware was
31 * passed the sanity check with success.
32 */
33#define BOOT_DATA_VALID (1u)
34
35/*!
36 * \def BOOT_DATA_INVALID
37 *
38 * \brief Indicates that shared data between bootloader and runtime firmware was
39 * failed on sanity check.
40 */
41#define BOOT_DATA_INVALID (0u)
42
43/*!
44 * \var is_boot_data_valid
45 *
46 * \brief Indicates the status of shared data between bootloader and runtime
47 * firmware
48 */
49static uint32_t is_boot_data_valid = BOOT_DATA_INVALID;
50
Tamas Ban6bd5b812019-09-25 09:34:11 +010051/*!
52 * \struct boot_data_access_policy
53 *
54 * \brief Defines the access policy of secure partitions to data items in shared
55 * data area (between bootloader and runtime firmware).
56 */
57struct boot_data_access_policy {
58 uint32_t partition_id;
59 uint32_t major_type;
60};
61
62/*!
63 * \var access_policy_table
64 *
65 * \brief Contains the partition_id and major_type assignments. This describes
66 * which secure partition is allowed to access which data item
67 * (identified by major_type).
68 */
69static const struct boot_data_access_policy access_policy_table[] = {
Edison Aib2134e62019-10-11 18:24:47 +080070 {TFM_SP_INITIAL_ATTESTATION, TLV_MAJOR_IAS},
Tamas Ban6bd5b812019-09-25 09:34:11 +010071};
72
73/*!
74 * \brief Verify the access right of the active secure partition to the
75 * specified data type in the shared data area.
76 *
77 * \param[in] major_type Data type identifier.
78 *
79 * \return Returns 0 in case of success, otherwise -1.
80 */
81static 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
94 partition_id = tfm_spm_partition_get_running_partition_id();
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
Tamas Ban6d2e4302019-10-03 12:37:09 +0100109/* 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
Tamas Ban9ff535b2018-09-18 08:15:18 +0100119void tfm_core_validate_boot_data(void)
120{
David Vinczee13a48b2020-01-08 17:42:30 +0100121#ifdef BOOT_DATA_AVAILABLE
Tamas Bana24ce042019-02-20 11:50:22 +0000122 struct tfm_boot_data *boot_data;
Tamas Ban9ff535b2018-09-18 08:15:18 +0100123
Tamas Bana24ce042019-02-20 11:50:22 +0000124 boot_data = (struct tfm_boot_data *)BOOT_TFM_SHARED_DATA_BASE;
Tamas Ban9ff535b2018-09-18 08:15:18 +0100125
Tamas Bana24ce042019-02-20 11:50:22 +0000126 if (boot_data->header.tlv_magic == SHARED_DATA_TLV_INFO_MAGIC) {
Tamas Ban9ff535b2018-09-18 08:15:18 +0100127 is_boot_data_valid = BOOT_DATA_VALID;
128 }
David Vinczee13a48b2020-01-08 17:42:30 +0100129#else
130 is_boot_data_valid = BOOT_DATA_VALID;
131#endif /* BOOT_DATA_AVAILABLE */
Tamas Ban9ff535b2018-09-18 08:15:18 +0100132}
133
134void tfm_core_get_boot_data_handler(uint32_t args[])
135{
136 uint8_t tlv_major = (uint8_t)args[0];
Tamas Banc43181d2019-02-18 14:21:35 +0000137 uint8_t *buf_start = (uint8_t *)args[1];
Tamas Ban9ff535b2018-09-18 08:15:18 +0100138 uint16_t buf_size = (uint16_t)args[2];
Tamas Bana24ce042019-02-20 11:50:22 +0000139 struct tfm_boot_data *boot_data;
David Vinczee13a48b2020-01-08 17:42:30 +0100140#ifdef BOOT_DATA_AVAILABLE
TTornblomfaf74f52020-03-04 17:56:27 +0100141 uint8_t *ptr;
Tamas Banc43181d2019-02-18 14:21:35 +0000142 struct shared_data_tlv_entry tlv_entry;
Tamas Ban9ff535b2018-09-18 08:15:18 +0100143 uintptr_t tlv_end, offset;
David Vincze53998032020-06-10 15:54:31 +0200144 size_t next_tlv_offset;
David Vinczee13a48b2020-01-08 17:42:30 +0100145#endif /* BOOT_DATA_AVAILABLE */
Edison Ai2e413a62019-05-16 13:46:00 +0800146#ifndef TFM_PSA_API
147 uint32_t running_partition_idx =
148 tfm_spm_partition_get_running_partition_idx();
Tamas Ban9ff535b2018-09-18 08:15:18 +0100149 uint32_t res;
Edison Ai2e413a62019-05-16 13:46:00 +0800150#else
Mingyang Sunae70d8d2020-06-30 15:56:05 +0800151 struct partition_t *partition = NULL;
Edison Ai2e413a62019-05-16 13:46:00 +0800152 uint32_t privileged;
153#endif
Tamas Ban9ff535b2018-09-18 08:15:18 +0100154
Edison Ai2e413a62019-05-16 13:46:00 +0800155#ifndef TFM_PSA_API
Mingyang Sunabb1aab2020-02-18 13:49:08 +0800156 /*
157 * Make sure that the output pointer points to a memory area that is owned
158 * by the partition. And check 4 bytes alignment.
Tamas Ban9ff535b2018-09-18 08:15:18 +0100159 */
Mingyang Sunabb1aab2020-02-18 13:49:08 +0800160 res = tfm_spm_check_buffer_access(running_partition_idx,
161 (void *)buf_start,
162 buf_size,
163 2);
Tamas Ban9ff535b2018-09-18 08:15:18 +0100164 if (!res) {
165 /* Not in accessible range, return error */
Hugues de Valon99578562019-06-18 16:08:51 +0100166 args[0] = (uint32_t)TFM_ERROR_INVALID_PARAMETER;
Tamas Ban9ff535b2018-09-18 08:15:18 +0100167 return;
168 }
Edison Ai2e413a62019-05-16 13:46:00 +0800169#else
170 partition = tfm_spm_get_running_partition();
171 if (!partition) {
Edison Ai9059ea02019-11-28 13:46:14 +0800172 tfm_core_panic();
Edison Ai2e413a62019-05-16 13:46:00 +0800173 }
Mingyang Sun5e13aa72019-07-10 10:30:16 +0800174 privileged =
Summer Qin75f0d752019-08-27 14:38:20 +0800175 tfm_spm_partition_get_privileged_mode(partition->static_data->
176 partition_flags);
Edison Ai2e413a62019-05-16 13:46:00 +0800177
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 */
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}