blob: b2115f5e62cc41c1ad40d7a92c26ab4da02c0b96 [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>
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
Ken Liubcae38b2021-01-20 15:47:44 +080016#include "internal_errors.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},
Sherry Zhang07b42412021-01-07 14:19:41 +080071 {TFM_SP_FWU, TLV_MAJOR_FWU},
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 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}