mbed-os5 only for TYBLE16
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/tfm_svcalls.c@1:9db0e321a9f4, 2019-12-31 (annotated)
- Committer:
- kenjiArai
- Date:
- Tue Dec 31 06:02:27 2019 +0000
- Revision:
- 1:9db0e321a9f4
- Parent:
- 0:5b88d5760320
updated based on mbed-os5.15.0
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
kenjiArai | 0:5b88d5760320 | 1 | /* |
kenjiArai | 0:5b88d5760320 | 2 | * Copyright (c) 2018-2019, Arm Limited. All rights reserved. |
kenjiArai | 0:5b88d5760320 | 3 | * |
kenjiArai | 0:5b88d5760320 | 4 | * SPDX-License-Identifier: BSD-3-Clause |
kenjiArai | 0:5b88d5760320 | 5 | * |
kenjiArai | 0:5b88d5760320 | 6 | */ |
kenjiArai | 0:5b88d5760320 | 7 | #include <inttypes.h> |
kenjiArai | 0:5b88d5760320 | 8 | #include <stdbool.h> |
kenjiArai | 0:5b88d5760320 | 9 | #include <stdio.h> |
kenjiArai | 0:5b88d5760320 | 10 | #include <stdlib.h> |
kenjiArai | 0:5b88d5760320 | 11 | #include "psa_client.h" |
kenjiArai | 0:5b88d5760320 | 12 | #include "psa_service.h" |
kenjiArai | 0:5b88d5760320 | 13 | #include "tfm_svc.h" |
kenjiArai | 0:5b88d5760320 | 14 | #include "tfm_svcalls.h" |
kenjiArai | 0:5b88d5760320 | 15 | #include "tfm_thread.h" |
kenjiArai | 0:5b88d5760320 | 16 | #include "tfm_wait.h" |
kenjiArai | 0:5b88d5760320 | 17 | #include "tfm_utils.h" |
kenjiArai | 0:5b88d5760320 | 18 | #include "tfm_internal_defines.h" |
kenjiArai | 0:5b88d5760320 | 19 | #include "tfm_message_queue.h" |
kenjiArai | 0:5b88d5760320 | 20 | #include "tfm_spm.h" |
kenjiArai | 0:5b88d5760320 | 21 | #include "tfm_api.h" |
kenjiArai | 0:5b88d5760320 | 22 | #include "tfm_secure_api.h" |
kenjiArai | 0:5b88d5760320 | 23 | #include "tfm_memory_utils.h" |
kenjiArai | 0:5b88d5760320 | 24 | #include "spm_api.h" |
kenjiArai | 0:5b88d5760320 | 25 | |
kenjiArai | 0:5b88d5760320 | 26 | #define PSA_TIMEOUT_MASK PSA_BLOCK |
kenjiArai | 0:5b88d5760320 | 27 | |
kenjiArai | 0:5b88d5760320 | 28 | /************************* SVC handler for PSA Client APIs *******************/ |
kenjiArai | 0:5b88d5760320 | 29 | |
kenjiArai | 0:5b88d5760320 | 30 | uint32_t tfm_svcall_psa_framework_version(void) |
kenjiArai | 0:5b88d5760320 | 31 | { |
kenjiArai | 0:5b88d5760320 | 32 | return PSA_FRAMEWORK_VERSION; |
kenjiArai | 0:5b88d5760320 | 33 | } |
kenjiArai | 0:5b88d5760320 | 34 | |
kenjiArai | 0:5b88d5760320 | 35 | uint32_t tfm_svcall_psa_version(uint32_t *args, int32_t ns_caller) |
kenjiArai | 0:5b88d5760320 | 36 | { |
kenjiArai | 0:5b88d5760320 | 37 | uint32_t sid; |
kenjiArai | 0:5b88d5760320 | 38 | struct tfm_spm_service_t *service; |
kenjiArai | 0:5b88d5760320 | 39 | |
kenjiArai | 0:5b88d5760320 | 40 | TFM_ASSERT(args != NULL); |
kenjiArai | 0:5b88d5760320 | 41 | sid = (uint32_t)args[0]; |
kenjiArai | 0:5b88d5760320 | 42 | /* |
kenjiArai | 0:5b88d5760320 | 43 | * It should return PSA_VERSION_NONE if the RoT Service is not |
kenjiArai | 0:5b88d5760320 | 44 | * implemented. |
kenjiArai | 0:5b88d5760320 | 45 | */ |
kenjiArai | 0:5b88d5760320 | 46 | service = tfm_spm_get_service_by_sid(sid); |
kenjiArai | 0:5b88d5760320 | 47 | if (!service) { |
kenjiArai | 0:5b88d5760320 | 48 | return PSA_VERSION_NONE; |
kenjiArai | 0:5b88d5760320 | 49 | } |
kenjiArai | 0:5b88d5760320 | 50 | |
kenjiArai | 0:5b88d5760320 | 51 | /* |
kenjiArai | 0:5b88d5760320 | 52 | * It should return PSA_VERSION_NONE if the caller is not authorized |
kenjiArai | 0:5b88d5760320 | 53 | * to access the RoT Service. |
kenjiArai | 0:5b88d5760320 | 54 | */ |
kenjiArai | 0:5b88d5760320 | 55 | if (ns_caller && !service->service_db->non_secure_client) { |
kenjiArai | 0:5b88d5760320 | 56 | return PSA_VERSION_NONE; |
kenjiArai | 0:5b88d5760320 | 57 | } |
kenjiArai | 0:5b88d5760320 | 58 | |
kenjiArai | 0:5b88d5760320 | 59 | return service->service_db->minor_version; |
kenjiArai | 0:5b88d5760320 | 60 | } |
kenjiArai | 0:5b88d5760320 | 61 | |
kenjiArai | 0:5b88d5760320 | 62 | psa_handle_t tfm_svcall_psa_connect(uint32_t *args, int32_t ns_caller) |
kenjiArai | 0:5b88d5760320 | 63 | { |
kenjiArai | 0:5b88d5760320 | 64 | uint32_t sid; |
kenjiArai | 0:5b88d5760320 | 65 | uint32_t minor_version; |
kenjiArai | 0:5b88d5760320 | 66 | struct tfm_spm_service_t *service; |
kenjiArai | 0:5b88d5760320 | 67 | struct tfm_msg_body_t *msg; |
kenjiArai | 0:5b88d5760320 | 68 | |
kenjiArai | 0:5b88d5760320 | 69 | TFM_ASSERT(args != NULL); |
kenjiArai | 0:5b88d5760320 | 70 | sid = (uint32_t)args[0]; |
kenjiArai | 0:5b88d5760320 | 71 | minor_version = (uint32_t)args[1]; |
kenjiArai | 0:5b88d5760320 | 72 | |
kenjiArai | 0:5b88d5760320 | 73 | /* It is a fatal error if the RoT Service does not exist on the platform */ |
kenjiArai | 0:5b88d5760320 | 74 | service = tfm_spm_get_service_by_sid(sid); |
kenjiArai | 0:5b88d5760320 | 75 | if (!service) { |
kenjiArai | 0:5b88d5760320 | 76 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 77 | } |
kenjiArai | 0:5b88d5760320 | 78 | |
kenjiArai | 0:5b88d5760320 | 79 | /* |
kenjiArai | 0:5b88d5760320 | 80 | * It is a fatal error if the caller is not authorized to access the RoT |
kenjiArai | 0:5b88d5760320 | 81 | * Service. |
kenjiArai | 0:5b88d5760320 | 82 | */ |
kenjiArai | 0:5b88d5760320 | 83 | if (ns_caller && !service->service_db->non_secure_client) { |
kenjiArai | 0:5b88d5760320 | 84 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 85 | } |
kenjiArai | 0:5b88d5760320 | 86 | |
kenjiArai | 0:5b88d5760320 | 87 | /* |
kenjiArai | 0:5b88d5760320 | 88 | * It is a fatal error if the version of the RoT Service requested is not |
kenjiArai | 0:5b88d5760320 | 89 | * supported on the platform. |
kenjiArai | 0:5b88d5760320 | 90 | */ |
kenjiArai | 0:5b88d5760320 | 91 | if (tfm_spm_check_client_version(service, minor_version) != IPC_SUCCESS) { |
kenjiArai | 0:5b88d5760320 | 92 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 93 | } |
kenjiArai | 0:5b88d5760320 | 94 | |
kenjiArai | 0:5b88d5760320 | 95 | /* No input or output needed for connect message */ |
kenjiArai | 0:5b88d5760320 | 96 | msg = tfm_spm_create_msg(service, PSA_NULL_HANDLE, PSA_IPC_CONNECT, |
kenjiArai | 0:5b88d5760320 | 97 | ns_caller, NULL, 0, NULL, 0, NULL); |
kenjiArai | 0:5b88d5760320 | 98 | if (!msg) { |
kenjiArai | 0:5b88d5760320 | 99 | return PSA_NULL_HANDLE; |
kenjiArai | 0:5b88d5760320 | 100 | } |
kenjiArai | 0:5b88d5760320 | 101 | |
kenjiArai | 0:5b88d5760320 | 102 | /* |
kenjiArai | 0:5b88d5760320 | 103 | * Send message and wake up the SP who is waiting on message queue, |
kenjiArai | 0:5b88d5760320 | 104 | * and scheduler triggered |
kenjiArai | 0:5b88d5760320 | 105 | */ |
kenjiArai | 0:5b88d5760320 | 106 | tfm_spm_send_event(service, msg); |
kenjiArai | 0:5b88d5760320 | 107 | |
kenjiArai | 0:5b88d5760320 | 108 | return PSA_NULL_HANDLE; |
kenjiArai | 0:5b88d5760320 | 109 | } |
kenjiArai | 0:5b88d5760320 | 110 | |
kenjiArai | 0:5b88d5760320 | 111 | psa_status_t tfm_svcall_psa_call(uint32_t *args, int32_t ns_caller, uint32_t lr) |
kenjiArai | 0:5b88d5760320 | 112 | { |
kenjiArai | 0:5b88d5760320 | 113 | psa_handle_t handle; |
kenjiArai | 0:5b88d5760320 | 114 | psa_invec *inptr, invecs[PSA_MAX_IOVEC]; |
kenjiArai | 0:5b88d5760320 | 115 | psa_outvec *outptr, outvecs[PSA_MAX_IOVEC]; |
kenjiArai | 0:5b88d5760320 | 116 | size_t in_num, out_num; |
kenjiArai | 0:5b88d5760320 | 117 | struct tfm_spm_service_t *service; |
kenjiArai | 0:5b88d5760320 | 118 | struct tfm_msg_body_t *msg; |
kenjiArai | 0:5b88d5760320 | 119 | int i; |
kenjiArai | 0:5b88d5760320 | 120 | struct tfm_spm_ipc_partition_t *partition = NULL; |
kenjiArai | 0:5b88d5760320 | 121 | uint32_t privileged; |
kenjiArai | 0:5b88d5760320 | 122 | |
kenjiArai | 0:5b88d5760320 | 123 | TFM_ASSERT(args != NULL); |
kenjiArai | 0:5b88d5760320 | 124 | handle = (psa_handle_t)args[0]; |
kenjiArai | 0:5b88d5760320 | 125 | |
kenjiArai | 0:5b88d5760320 | 126 | partition = tfm_spm_get_running_partition(); |
kenjiArai | 0:5b88d5760320 | 127 | if (!partition) { |
kenjiArai | 0:5b88d5760320 | 128 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 129 | } |
kenjiArai | 0:5b88d5760320 | 130 | privileged = tfm_spm_partition_get_privileged_mode(partition->index); |
kenjiArai | 0:5b88d5760320 | 131 | |
kenjiArai | 0:5b88d5760320 | 132 | if (!ns_caller) { |
kenjiArai | 0:5b88d5760320 | 133 | inptr = (psa_invec *)args[1]; |
kenjiArai | 0:5b88d5760320 | 134 | in_num = (size_t)args[2]; |
kenjiArai | 0:5b88d5760320 | 135 | outptr = (psa_outvec *)args[3]; |
kenjiArai | 0:5b88d5760320 | 136 | /* |
kenjiArai | 0:5b88d5760320 | 137 | * 5th parameter is pushed at stack top before SVC, then PE hardware |
kenjiArai | 0:5b88d5760320 | 138 | * stacks the execution context. The size of the context depends on |
kenjiArai | 0:5b88d5760320 | 139 | * various settings: |
kenjiArai | 0:5b88d5760320 | 140 | * - if FP is not used, 5th parameter is at 8th position counting |
kenjiArai | 0:5b88d5760320 | 141 | * from SP; |
kenjiArai | 0:5b88d5760320 | 142 | * - if FP is used and FPCCR_S.TS is 0, 5th parameter is at 26th |
kenjiArai | 0:5b88d5760320 | 143 | * position counting from SP; |
kenjiArai | 0:5b88d5760320 | 144 | * - if FP is used and FPCCR_S.TS is 1, 5th parameter is at 42th |
kenjiArai | 0:5b88d5760320 | 145 | * position counting from SP. |
kenjiArai | 0:5b88d5760320 | 146 | */ |
kenjiArai | 0:5b88d5760320 | 147 | if (lr & EXC_RETURN_FPU_FRAME_BASIC) { |
kenjiArai | 0:5b88d5760320 | 148 | out_num = (size_t)args[8]; |
kenjiArai | 0:5b88d5760320 | 149 | #if defined (__FPU_USED) && (__FPU_USED == 1U) |
kenjiArai | 0:5b88d5760320 | 150 | } else if (FPU->FPCCR & FPU_FPCCR_TS_Msk) { |
kenjiArai | 0:5b88d5760320 | 151 | out_num = (size_t)args[42]; |
kenjiArai | 0:5b88d5760320 | 152 | #endif |
kenjiArai | 0:5b88d5760320 | 153 | } else { |
kenjiArai | 0:5b88d5760320 | 154 | out_num = (size_t)args[26]; |
kenjiArai | 0:5b88d5760320 | 155 | } |
kenjiArai | 0:5b88d5760320 | 156 | } else { |
kenjiArai | 0:5b88d5760320 | 157 | /* |
kenjiArai | 0:5b88d5760320 | 158 | * FixMe: From non-secure caller, vec and len are composed into a new |
kenjiArai | 0:5b88d5760320 | 159 | * struct parameter. Need to extract them. |
kenjiArai | 0:5b88d5760320 | 160 | */ |
kenjiArai | 0:5b88d5760320 | 161 | /* |
kenjiArai | 0:5b88d5760320 | 162 | * Read parameters from the arguments. It is a fatal error if the |
kenjiArai | 0:5b88d5760320 | 163 | * memory reference for buffer is invalid or not readable. |
kenjiArai | 0:5b88d5760320 | 164 | */ |
kenjiArai | 0:5b88d5760320 | 165 | if (tfm_memory_check((void *)args[1], sizeof(uint32_t), |
kenjiArai | 0:5b88d5760320 | 166 | ns_caller, TFM_MEMORY_ACCESS_RO, privileged) != IPC_SUCCESS) { |
kenjiArai | 0:5b88d5760320 | 167 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 168 | } |
kenjiArai | 0:5b88d5760320 | 169 | if (tfm_memory_check((void *)args[2], sizeof(uint32_t), |
kenjiArai | 0:5b88d5760320 | 170 | ns_caller, TFM_MEMORY_ACCESS_RO, privileged) != IPC_SUCCESS) { |
kenjiArai | 0:5b88d5760320 | 171 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 172 | } |
kenjiArai | 0:5b88d5760320 | 173 | |
kenjiArai | 0:5b88d5760320 | 174 | inptr = (psa_invec *)((psa_invec *)args[1])->base; |
kenjiArai | 0:5b88d5760320 | 175 | in_num = ((psa_invec *)args[1])->len; |
kenjiArai | 0:5b88d5760320 | 176 | outptr = (psa_outvec *)((psa_invec *)args[2])->base; |
kenjiArai | 0:5b88d5760320 | 177 | out_num = ((psa_invec *)args[2])->len; |
kenjiArai | 0:5b88d5760320 | 178 | } |
kenjiArai | 0:5b88d5760320 | 179 | |
kenjiArai | 0:5b88d5760320 | 180 | /* It is a fatal error if in_len + out_len > PSA_MAX_IOVEC. */ |
kenjiArai | 0:5b88d5760320 | 181 | if (in_num + out_num > PSA_MAX_IOVEC) { |
kenjiArai | 0:5b88d5760320 | 182 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 183 | } |
kenjiArai | 0:5b88d5760320 | 184 | |
kenjiArai | 0:5b88d5760320 | 185 | /* It is a fatal error if an invalid handle was passed. */ |
kenjiArai | 0:5b88d5760320 | 186 | service = tfm_spm_get_service_by_handle(handle); |
kenjiArai | 0:5b88d5760320 | 187 | if (!service) { |
kenjiArai | 0:5b88d5760320 | 188 | /* FixMe: Need to implement one mechanism to resolve this failure. */ |
kenjiArai | 0:5b88d5760320 | 189 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 190 | } |
kenjiArai | 0:5b88d5760320 | 191 | |
kenjiArai | 0:5b88d5760320 | 192 | /* |
kenjiArai | 0:5b88d5760320 | 193 | * Read client invecs from the wrap input vector. It is a fatal error |
kenjiArai | 0:5b88d5760320 | 194 | * if the memory reference for the wrap input vector is invalid or not |
kenjiArai | 0:5b88d5760320 | 195 | * readable. |
kenjiArai | 0:5b88d5760320 | 196 | */ |
kenjiArai | 0:5b88d5760320 | 197 | if (tfm_memory_check((void *)inptr, in_num * sizeof(psa_invec), |
kenjiArai | 0:5b88d5760320 | 198 | ns_caller, TFM_MEMORY_ACCESS_RO, privileged) != IPC_SUCCESS) { |
kenjiArai | 0:5b88d5760320 | 199 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 200 | } |
kenjiArai | 0:5b88d5760320 | 201 | /* |
kenjiArai | 0:5b88d5760320 | 202 | * Read client outvecs from the wrap output vector and will update the |
kenjiArai | 0:5b88d5760320 | 203 | * actual length later. It is a fatal error if the memory reference for |
kenjiArai | 0:5b88d5760320 | 204 | * the wrap output vector is invalid or not read-write. |
kenjiArai | 0:5b88d5760320 | 205 | */ |
kenjiArai | 0:5b88d5760320 | 206 | if (tfm_memory_check((void *)outptr, out_num * sizeof(psa_outvec), |
kenjiArai | 0:5b88d5760320 | 207 | ns_caller, TFM_MEMORY_ACCESS_RW, privileged) != IPC_SUCCESS) { |
kenjiArai | 0:5b88d5760320 | 208 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 209 | } |
kenjiArai | 0:5b88d5760320 | 210 | |
kenjiArai | 0:5b88d5760320 | 211 | tfm_memset(invecs, 0, sizeof(invecs)); |
kenjiArai | 0:5b88d5760320 | 212 | tfm_memset(outvecs, 0, sizeof(outvecs)); |
kenjiArai | 0:5b88d5760320 | 213 | |
kenjiArai | 0:5b88d5760320 | 214 | /* Copy the address out to avoid TOCTOU attacks. */ |
kenjiArai | 0:5b88d5760320 | 215 | tfm_memcpy(invecs, inptr, in_num * sizeof(psa_invec)); |
kenjiArai | 0:5b88d5760320 | 216 | tfm_memcpy(outvecs, outptr, out_num * sizeof(psa_outvec)); |
kenjiArai | 0:5b88d5760320 | 217 | |
kenjiArai | 0:5b88d5760320 | 218 | /* |
kenjiArai | 0:5b88d5760320 | 219 | * For client input vector, it is a fatal error if the provided payload |
kenjiArai | 0:5b88d5760320 | 220 | * memory reference was invalid or not readable. |
kenjiArai | 0:5b88d5760320 | 221 | */ |
kenjiArai | 0:5b88d5760320 | 222 | for (i = 0; i < in_num; i++) { |
kenjiArai | 0:5b88d5760320 | 223 | if (tfm_memory_check((void *)invecs[i].base, invecs[i].len, |
kenjiArai | 0:5b88d5760320 | 224 | ns_caller, TFM_MEMORY_ACCESS_RO, privileged) != IPC_SUCCESS) { |
kenjiArai | 0:5b88d5760320 | 225 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 226 | } |
kenjiArai | 0:5b88d5760320 | 227 | } |
kenjiArai | 0:5b88d5760320 | 228 | /* |
kenjiArai | 0:5b88d5760320 | 229 | * For client output vector, it is a fatal error if the provided payload |
kenjiArai | 0:5b88d5760320 | 230 | * memory reference was invalid or not read-write. |
kenjiArai | 0:5b88d5760320 | 231 | */ |
kenjiArai | 0:5b88d5760320 | 232 | for (i = 0; i < out_num; i++) { |
kenjiArai | 0:5b88d5760320 | 233 | if (tfm_memory_check(outvecs[i].base, outvecs[i].len, |
kenjiArai | 0:5b88d5760320 | 234 | ns_caller, TFM_MEMORY_ACCESS_RW, privileged) != IPC_SUCCESS) { |
kenjiArai | 0:5b88d5760320 | 235 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 236 | } |
kenjiArai | 0:5b88d5760320 | 237 | } |
kenjiArai | 0:5b88d5760320 | 238 | |
kenjiArai | 0:5b88d5760320 | 239 | /* |
kenjiArai | 0:5b88d5760320 | 240 | * FixMe: Need to check if the message is unrecognized by the RoT |
kenjiArai | 0:5b88d5760320 | 241 | * Service or incorrectly formatted. |
kenjiArai | 0:5b88d5760320 | 242 | */ |
kenjiArai | 0:5b88d5760320 | 243 | msg = tfm_spm_create_msg(service, handle, PSA_IPC_CALL, ns_caller, invecs, |
kenjiArai | 0:5b88d5760320 | 244 | in_num, outvecs, out_num, outptr); |
kenjiArai | 0:5b88d5760320 | 245 | if (!msg) { |
kenjiArai | 0:5b88d5760320 | 246 | /* FixMe: Need to implement one mechanism to resolve this failure. */ |
kenjiArai | 0:5b88d5760320 | 247 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 248 | } |
kenjiArai | 0:5b88d5760320 | 249 | |
kenjiArai | 0:5b88d5760320 | 250 | /* |
kenjiArai | 0:5b88d5760320 | 251 | * Send message and wake up the SP who is waiting on message queue, |
kenjiArai | 0:5b88d5760320 | 252 | * and scheduler triggered |
kenjiArai | 0:5b88d5760320 | 253 | */ |
kenjiArai | 0:5b88d5760320 | 254 | if (tfm_spm_send_event(service, msg) != IPC_SUCCESS) { |
kenjiArai | 0:5b88d5760320 | 255 | /* FixMe: Need to refine failure process here. */ |
kenjiArai | 0:5b88d5760320 | 256 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 257 | } |
kenjiArai | 0:5b88d5760320 | 258 | return PSA_SUCCESS; |
kenjiArai | 0:5b88d5760320 | 259 | } |
kenjiArai | 0:5b88d5760320 | 260 | |
kenjiArai | 0:5b88d5760320 | 261 | void tfm_svcall_psa_close(uint32_t *args, int32_t ns_caller) |
kenjiArai | 0:5b88d5760320 | 262 | { |
kenjiArai | 0:5b88d5760320 | 263 | psa_handle_t handle; |
kenjiArai | 0:5b88d5760320 | 264 | struct tfm_spm_service_t *service; |
kenjiArai | 0:5b88d5760320 | 265 | struct tfm_msg_body_t *msg; |
kenjiArai | 0:5b88d5760320 | 266 | |
kenjiArai | 0:5b88d5760320 | 267 | TFM_ASSERT(args != NULL); |
kenjiArai | 0:5b88d5760320 | 268 | handle = args[0]; |
kenjiArai | 0:5b88d5760320 | 269 | /* It will have no effect if called with the NULL handle */ |
kenjiArai | 0:5b88d5760320 | 270 | if (handle == PSA_NULL_HANDLE) { |
kenjiArai | 0:5b88d5760320 | 271 | return; |
kenjiArai | 0:5b88d5760320 | 272 | } |
kenjiArai | 0:5b88d5760320 | 273 | |
kenjiArai | 0:5b88d5760320 | 274 | /* |
kenjiArai | 0:5b88d5760320 | 275 | * It is a fatal error if an invalid handle was provided that is not the |
kenjiArai | 0:5b88d5760320 | 276 | * null handle.. |
kenjiArai | 0:5b88d5760320 | 277 | */ |
kenjiArai | 0:5b88d5760320 | 278 | service = tfm_spm_get_service_by_handle(handle); |
kenjiArai | 0:5b88d5760320 | 279 | if (!service) { |
kenjiArai | 0:5b88d5760320 | 280 | /* FixMe: Need to implement one mechanism to resolve this failure. */ |
kenjiArai | 0:5b88d5760320 | 281 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 282 | } |
kenjiArai | 0:5b88d5760320 | 283 | |
kenjiArai | 0:5b88d5760320 | 284 | /* No input or output needed for close message */ |
kenjiArai | 0:5b88d5760320 | 285 | msg = tfm_spm_create_msg(service, handle, PSA_IPC_DISCONNECT, ns_caller, |
kenjiArai | 0:5b88d5760320 | 286 | NULL, 0, NULL, 0, NULL); |
kenjiArai | 0:5b88d5760320 | 287 | if (!msg) { |
kenjiArai | 0:5b88d5760320 | 288 | /* FixMe: Need to implement one mechanism to resolve this failure. */ |
kenjiArai | 0:5b88d5760320 | 289 | return; |
kenjiArai | 0:5b88d5760320 | 290 | } |
kenjiArai | 0:5b88d5760320 | 291 | |
kenjiArai | 0:5b88d5760320 | 292 | /* |
kenjiArai | 0:5b88d5760320 | 293 | * Send message and wake up the SP who is waiting on message queue, |
kenjiArai | 0:5b88d5760320 | 294 | * and scheduler triggered |
kenjiArai | 0:5b88d5760320 | 295 | */ |
kenjiArai | 0:5b88d5760320 | 296 | tfm_spm_send_event(service, msg); |
kenjiArai | 0:5b88d5760320 | 297 | } |
kenjiArai | 0:5b88d5760320 | 298 | |
kenjiArai | 0:5b88d5760320 | 299 | /*********************** SVC handler for PSA Service APIs ********************/ |
kenjiArai | 0:5b88d5760320 | 300 | |
kenjiArai | 0:5b88d5760320 | 301 | /** |
kenjiArai | 0:5b88d5760320 | 302 | * \brief SVC handler for \ref psa_wait. |
kenjiArai | 0:5b88d5760320 | 303 | * |
kenjiArai | 0:5b88d5760320 | 304 | * \param[in] args Include all input arguments: |
kenjiArai | 0:5b88d5760320 | 305 | * signal_mask, timeout. |
kenjiArai | 0:5b88d5760320 | 306 | * |
kenjiArai | 0:5b88d5760320 | 307 | * \retval >0 At least one signal is asserted. |
kenjiArai | 0:5b88d5760320 | 308 | * \retval 0 No signals are asserted. This is only seen when |
kenjiArai | 0:5b88d5760320 | 309 | * a polling timeout is used. |
kenjiArai | 0:5b88d5760320 | 310 | */ |
kenjiArai | 0:5b88d5760320 | 311 | static psa_signal_t tfm_svcall_psa_wait(uint32_t *args) |
kenjiArai | 0:5b88d5760320 | 312 | { |
kenjiArai | 0:5b88d5760320 | 313 | psa_signal_t signal_mask; |
kenjiArai | 0:5b88d5760320 | 314 | uint32_t timeout; |
kenjiArai | 0:5b88d5760320 | 315 | struct tfm_spm_ipc_partition_t *partition = NULL; |
kenjiArai | 0:5b88d5760320 | 316 | |
kenjiArai | 0:5b88d5760320 | 317 | TFM_ASSERT(args != NULL); |
kenjiArai | 0:5b88d5760320 | 318 | signal_mask = (psa_signal_t)args[0]; |
kenjiArai | 0:5b88d5760320 | 319 | timeout = args[1]; |
kenjiArai | 0:5b88d5760320 | 320 | |
kenjiArai | 0:5b88d5760320 | 321 | /* |
kenjiArai | 0:5b88d5760320 | 322 | * Timeout[30:0] are reserved for future use. |
kenjiArai | 0:5b88d5760320 | 323 | * SPM must ignore the value of RES. |
kenjiArai | 0:5b88d5760320 | 324 | */ |
kenjiArai | 0:5b88d5760320 | 325 | timeout &= PSA_TIMEOUT_MASK; |
kenjiArai | 0:5b88d5760320 | 326 | |
kenjiArai | 0:5b88d5760320 | 327 | partition = tfm_spm_get_running_partition(); |
kenjiArai | 0:5b88d5760320 | 328 | if (!partition) { |
kenjiArai | 0:5b88d5760320 | 329 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 330 | } |
kenjiArai | 0:5b88d5760320 | 331 | |
kenjiArai | 0:5b88d5760320 | 332 | /* |
kenjiArai | 0:5b88d5760320 | 333 | * Expected signals are included in signal wait mask, ignored signals |
kenjiArai | 0:5b88d5760320 | 334 | * should not be set and affect caller thread status. Save this mask for |
kenjiArai | 0:5b88d5760320 | 335 | * further checking while signals are ready to be set. |
kenjiArai | 0:5b88d5760320 | 336 | */ |
kenjiArai | 0:5b88d5760320 | 337 | partition->signal_mask = signal_mask; |
kenjiArai | 0:5b88d5760320 | 338 | |
kenjiArai | 0:5b88d5760320 | 339 | /* |
kenjiArai | 0:5b88d5760320 | 340 | * tfm_event_wait() blocks the caller thread if no signals are available. |
kenjiArai | 0:5b88d5760320 | 341 | * In this case, the return value of this function is temporary set into |
kenjiArai | 0:5b88d5760320 | 342 | * runtime context. After new signal(s) are available, the return value |
kenjiArai | 0:5b88d5760320 | 343 | * is updated with the available signal(s) and blocked thread gets to run. |
kenjiArai | 0:5b88d5760320 | 344 | */ |
kenjiArai | 0:5b88d5760320 | 345 | if (timeout == PSA_BLOCK && (partition->signals & signal_mask) == 0) { |
kenjiArai | 0:5b88d5760320 | 346 | tfm_event_wait(&partition->signal_evnt); |
kenjiArai | 0:5b88d5760320 | 347 | } |
kenjiArai | 0:5b88d5760320 | 348 | |
kenjiArai | 0:5b88d5760320 | 349 | return partition->signals & signal_mask; |
kenjiArai | 0:5b88d5760320 | 350 | } |
kenjiArai | 0:5b88d5760320 | 351 | |
kenjiArai | 0:5b88d5760320 | 352 | /** |
kenjiArai | 0:5b88d5760320 | 353 | * \brief SVC handler for \ref psa_get. |
kenjiArai | 0:5b88d5760320 | 354 | * |
kenjiArai | 0:5b88d5760320 | 355 | * \param[in] args Include all input arguments: signal, msg. |
kenjiArai | 0:5b88d5760320 | 356 | * |
kenjiArai | 0:5b88d5760320 | 357 | * \retval PSA_SUCCESS Success, *msg will contain the delivered |
kenjiArai | 0:5b88d5760320 | 358 | * message. |
kenjiArai | 0:5b88d5760320 | 359 | * \retval PSA_ERR_NOMSG Message could not be delivered. |
kenjiArai | 0:5b88d5760320 | 360 | * \retval "Does not return" The call is invalid because one or more of the |
kenjiArai | 0:5b88d5760320 | 361 | * following are true: |
kenjiArai | 0:5b88d5760320 | 362 | * \arg signal has more than a single bit set. |
kenjiArai | 0:5b88d5760320 | 363 | * \arg signal does not correspond to a RoT Service. |
kenjiArai | 0:5b88d5760320 | 364 | * \arg The RoT Service signal is not currently |
kenjiArai | 0:5b88d5760320 | 365 | * asserted. |
kenjiArai | 0:5b88d5760320 | 366 | * \arg The msg pointer provided is not a valid memory |
kenjiArai | 0:5b88d5760320 | 367 | * reference. |
kenjiArai | 0:5b88d5760320 | 368 | */ |
kenjiArai | 0:5b88d5760320 | 369 | static psa_status_t tfm_svcall_psa_get(uint32_t *args) |
kenjiArai | 0:5b88d5760320 | 370 | { |
kenjiArai | 0:5b88d5760320 | 371 | psa_signal_t signal; |
kenjiArai | 0:5b88d5760320 | 372 | psa_msg_t *msg = NULL; |
kenjiArai | 0:5b88d5760320 | 373 | struct tfm_spm_service_t *service = NULL; |
kenjiArai | 0:5b88d5760320 | 374 | struct tfm_msg_body_t *tmp_msg = NULL; |
kenjiArai | 0:5b88d5760320 | 375 | struct tfm_spm_ipc_partition_t *partition = NULL; |
kenjiArai | 0:5b88d5760320 | 376 | uint32_t privileged; |
kenjiArai | 0:5b88d5760320 | 377 | |
kenjiArai | 0:5b88d5760320 | 378 | TFM_ASSERT(args != NULL); |
kenjiArai | 0:5b88d5760320 | 379 | signal = (psa_signal_t)args[0]; |
kenjiArai | 0:5b88d5760320 | 380 | msg = (psa_msg_t *)args[1]; |
kenjiArai | 0:5b88d5760320 | 381 | |
kenjiArai | 0:5b88d5760320 | 382 | /* |
kenjiArai | 0:5b88d5760320 | 383 | * Only one message could be retrieved every time for psa_get(). It is a |
kenjiArai | 0:5b88d5760320 | 384 | * fatal error if the input signal has more than a signal bit set. |
kenjiArai | 0:5b88d5760320 | 385 | */ |
kenjiArai | 0:5b88d5760320 | 386 | if (tfm_bitcount(signal) != 1) { |
kenjiArai | 0:5b88d5760320 | 387 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 388 | } |
kenjiArai | 0:5b88d5760320 | 389 | |
kenjiArai | 0:5b88d5760320 | 390 | partition = tfm_spm_get_running_partition(); |
kenjiArai | 0:5b88d5760320 | 391 | if (!partition) { |
kenjiArai | 0:5b88d5760320 | 392 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 393 | } |
kenjiArai | 0:5b88d5760320 | 394 | privileged = tfm_spm_partition_get_privileged_mode(partition->index); |
kenjiArai | 0:5b88d5760320 | 395 | |
kenjiArai | 0:5b88d5760320 | 396 | /* |
kenjiArai | 0:5b88d5760320 | 397 | * Write the message to the service buffer. It is a fatal error if the |
kenjiArai | 0:5b88d5760320 | 398 | * input msg pointer is not a valid memory reference or not read-write. |
kenjiArai | 0:5b88d5760320 | 399 | */ |
kenjiArai | 0:5b88d5760320 | 400 | if (tfm_memory_check((void *)msg, sizeof(psa_msg_t), |
kenjiArai | 0:5b88d5760320 | 401 | false, TFM_MEMORY_ACCESS_RW, privileged) != IPC_SUCCESS) { |
kenjiArai | 0:5b88d5760320 | 402 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 403 | } |
kenjiArai | 0:5b88d5760320 | 404 | |
kenjiArai | 0:5b88d5760320 | 405 | /* |
kenjiArai | 0:5b88d5760320 | 406 | * It is a fatal error if the caller call psa_get() when no message has |
kenjiArai | 0:5b88d5760320 | 407 | * been set. The caller must call this function after a RoT Service signal |
kenjiArai | 0:5b88d5760320 | 408 | * is returned by psa_wait(). |
kenjiArai | 0:5b88d5760320 | 409 | */ |
kenjiArai | 0:5b88d5760320 | 410 | if (partition->signals == 0) { |
kenjiArai | 0:5b88d5760320 | 411 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 412 | } |
kenjiArai | 0:5b88d5760320 | 413 | |
kenjiArai | 0:5b88d5760320 | 414 | /* |
kenjiArai | 0:5b88d5760320 | 415 | * It is a fatal error if the RoT Service signal is not currently asserted. |
kenjiArai | 0:5b88d5760320 | 416 | */ |
kenjiArai | 0:5b88d5760320 | 417 | if ((partition->signals & signal) == 0) { |
kenjiArai | 0:5b88d5760320 | 418 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 419 | } |
kenjiArai | 0:5b88d5760320 | 420 | |
kenjiArai | 0:5b88d5760320 | 421 | /* |
kenjiArai | 0:5b88d5760320 | 422 | * Get Rot service by signal from partition. It is a fatal error if geting |
kenjiArai | 0:5b88d5760320 | 423 | * failed which mean the input signal is not correspond to a RoT service. |
kenjiArai | 0:5b88d5760320 | 424 | */ |
kenjiArai | 0:5b88d5760320 | 425 | service = tfm_spm_get_service_by_signal(partition, signal); |
kenjiArai | 0:5b88d5760320 | 426 | if (!service) { |
kenjiArai | 0:5b88d5760320 | 427 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 428 | } |
kenjiArai | 0:5b88d5760320 | 429 | |
kenjiArai | 0:5b88d5760320 | 430 | tmp_msg = tfm_msg_dequeue(&service->msg_queue); |
kenjiArai | 0:5b88d5760320 | 431 | if (!tmp_msg) { |
kenjiArai | 0:5b88d5760320 | 432 | return PSA_ERR_NOMSG; |
kenjiArai | 0:5b88d5760320 | 433 | } |
kenjiArai | 0:5b88d5760320 | 434 | |
kenjiArai | 0:5b88d5760320 | 435 | tfm_memcpy(msg, &tmp_msg->msg, sizeof(psa_msg_t)); |
kenjiArai | 0:5b88d5760320 | 436 | |
kenjiArai | 0:5b88d5760320 | 437 | /* |
kenjiArai | 0:5b88d5760320 | 438 | * There may be mutiple messages for this RoT Service signal, do not clear |
kenjiArai | 0:5b88d5760320 | 439 | * its mask until no remaining message. |
kenjiArai | 0:5b88d5760320 | 440 | */ |
kenjiArai | 0:5b88d5760320 | 441 | if (tfm_msg_queue_is_empty(&service->msg_queue)) { |
kenjiArai | 0:5b88d5760320 | 442 | partition->signals &= ~signal; |
kenjiArai | 0:5b88d5760320 | 443 | } |
kenjiArai | 0:5b88d5760320 | 444 | |
kenjiArai | 0:5b88d5760320 | 445 | return PSA_SUCCESS; |
kenjiArai | 0:5b88d5760320 | 446 | } |
kenjiArai | 0:5b88d5760320 | 447 | |
kenjiArai | 0:5b88d5760320 | 448 | /** |
kenjiArai | 0:5b88d5760320 | 449 | * \brief SVC handler for \ref psa_set_rhandle. |
kenjiArai | 0:5b88d5760320 | 450 | * |
kenjiArai | 0:5b88d5760320 | 451 | * \param[in] args Include all input arguments: |
kenjiArai | 0:5b88d5760320 | 452 | * msg_handle, rhandle. |
kenjiArai | 0:5b88d5760320 | 453 | * |
kenjiArai | 0:5b88d5760320 | 454 | * \retval void Success, rhandle will be provided with all |
kenjiArai | 0:5b88d5760320 | 455 | * subsequent messages delivered on this |
kenjiArai | 0:5b88d5760320 | 456 | * connection. |
kenjiArai | 0:5b88d5760320 | 457 | * \retval "Does not return" msg_handle is invalid. |
kenjiArai | 0:5b88d5760320 | 458 | */ |
kenjiArai | 0:5b88d5760320 | 459 | static void tfm_svcall_psa_set_rhandle(uint32_t *args) |
kenjiArai | 0:5b88d5760320 | 460 | { |
kenjiArai | 0:5b88d5760320 | 461 | psa_handle_t msg_handle; |
kenjiArai | 0:5b88d5760320 | 462 | void *rhandle = NULL; |
kenjiArai | 0:5b88d5760320 | 463 | struct tfm_msg_body_t *msg = NULL; |
kenjiArai | 0:5b88d5760320 | 464 | |
kenjiArai | 0:5b88d5760320 | 465 | TFM_ASSERT(args != NULL); |
kenjiArai | 0:5b88d5760320 | 466 | msg_handle = (psa_handle_t)args[0]; |
kenjiArai | 0:5b88d5760320 | 467 | rhandle = (void *)args[1]; |
kenjiArai | 0:5b88d5760320 | 468 | |
kenjiArai | 0:5b88d5760320 | 469 | /* It is a fatal error if message handle is invalid */ |
kenjiArai | 0:5b88d5760320 | 470 | msg = tfm_spm_get_msg_from_handle(msg_handle); |
kenjiArai | 0:5b88d5760320 | 471 | if (!msg) { |
kenjiArai | 0:5b88d5760320 | 472 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 473 | } |
kenjiArai | 0:5b88d5760320 | 474 | |
kenjiArai | 0:5b88d5760320 | 475 | /* |
kenjiArai | 0:5b88d5760320 | 476 | * Connection handle is not created while SP is processing PSA_IPC_CONNECT |
kenjiArai | 0:5b88d5760320 | 477 | * message. Store reverse handle temporarily and re-set it after the |
kenjiArai | 0:5b88d5760320 | 478 | * connection created. |
kenjiArai | 0:5b88d5760320 | 479 | */ |
kenjiArai | 0:5b88d5760320 | 480 | if (msg->handle != PSA_NULL_HANDLE) { |
kenjiArai | 0:5b88d5760320 | 481 | tfm_spm_set_rhandle(msg->service, msg->handle, rhandle); |
kenjiArai | 0:5b88d5760320 | 482 | } else { |
kenjiArai | 0:5b88d5760320 | 483 | msg->msg.rhandle = rhandle; |
kenjiArai | 0:5b88d5760320 | 484 | } |
kenjiArai | 0:5b88d5760320 | 485 | } |
kenjiArai | 0:5b88d5760320 | 486 | |
kenjiArai | 0:5b88d5760320 | 487 | /** |
kenjiArai | 0:5b88d5760320 | 488 | * \brief SVC handler for \ref psa_read. |
kenjiArai | 0:5b88d5760320 | 489 | * |
kenjiArai | 0:5b88d5760320 | 490 | * \param[in] args Include all input arguments: |
kenjiArai | 0:5b88d5760320 | 491 | * msg_handle, invec_idx, buffer, num_bytes. |
kenjiArai | 0:5b88d5760320 | 492 | * |
kenjiArai | 0:5b88d5760320 | 493 | * \retval >0 Number of bytes copied. |
kenjiArai | 0:5b88d5760320 | 494 | * \retval 0 There was no remaining data in this input |
kenjiArai | 0:5b88d5760320 | 495 | * vector. |
kenjiArai | 0:5b88d5760320 | 496 | * \retval "Does not return" The call is invalid, one or more of the |
kenjiArai | 0:5b88d5760320 | 497 | * following are true: |
kenjiArai | 0:5b88d5760320 | 498 | * \arg msg_handle is invalid. |
kenjiArai | 0:5b88d5760320 | 499 | * \arg msg_handle does not refer to a |
kenjiArai | 0:5b88d5760320 | 500 | * \ref PSA_IPC_CALL message. |
kenjiArai | 0:5b88d5760320 | 501 | * \arg invec_idx is equal to or greater than |
kenjiArai | 0:5b88d5760320 | 502 | * \ref PSA_MAX_IOVEC. |
kenjiArai | 0:5b88d5760320 | 503 | * \arg the memory reference for buffer is invalid or |
kenjiArai | 0:5b88d5760320 | 504 | * not writable. |
kenjiArai | 0:5b88d5760320 | 505 | */ |
kenjiArai | 0:5b88d5760320 | 506 | static size_t tfm_svcall_psa_read(uint32_t *args) |
kenjiArai | 0:5b88d5760320 | 507 | { |
kenjiArai | 0:5b88d5760320 | 508 | psa_handle_t msg_handle; |
kenjiArai | 0:5b88d5760320 | 509 | uint32_t invec_idx; |
kenjiArai | 0:5b88d5760320 | 510 | void *buffer = NULL; |
kenjiArai | 0:5b88d5760320 | 511 | size_t num_bytes; |
kenjiArai | 0:5b88d5760320 | 512 | size_t bytes; |
kenjiArai | 0:5b88d5760320 | 513 | struct tfm_msg_body_t *msg = NULL; |
kenjiArai | 0:5b88d5760320 | 514 | uint32_t privileged; |
kenjiArai | 0:5b88d5760320 | 515 | struct tfm_spm_ipc_partition_t *partition = NULL; |
kenjiArai | 0:5b88d5760320 | 516 | |
kenjiArai | 0:5b88d5760320 | 517 | TFM_ASSERT(args != NULL); |
kenjiArai | 0:5b88d5760320 | 518 | msg_handle = (psa_handle_t)args[0]; |
kenjiArai | 0:5b88d5760320 | 519 | invec_idx = args[1]; |
kenjiArai | 0:5b88d5760320 | 520 | buffer = (void *)args[2]; |
kenjiArai | 0:5b88d5760320 | 521 | num_bytes = (size_t)args[3]; |
kenjiArai | 0:5b88d5760320 | 522 | |
kenjiArai | 0:5b88d5760320 | 523 | /* It is a fatal error if message handle is invalid */ |
kenjiArai | 0:5b88d5760320 | 524 | msg = tfm_spm_get_msg_from_handle(msg_handle); |
kenjiArai | 0:5b88d5760320 | 525 | if (!msg) { |
kenjiArai | 0:5b88d5760320 | 526 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 527 | } |
kenjiArai | 0:5b88d5760320 | 528 | |
kenjiArai | 0:5b88d5760320 | 529 | partition = msg->service->partition; |
kenjiArai | 0:5b88d5760320 | 530 | privileged = tfm_spm_partition_get_privileged_mode(partition->index); |
kenjiArai | 0:5b88d5760320 | 531 | |
kenjiArai | 0:5b88d5760320 | 532 | /* |
kenjiArai | 0:5b88d5760320 | 533 | * It is a fatal error if message handle does not refer to a PSA_IPC_CALL |
kenjiArai | 0:5b88d5760320 | 534 | * message |
kenjiArai | 0:5b88d5760320 | 535 | */ |
kenjiArai | 0:5b88d5760320 | 536 | if (msg->msg.type != PSA_IPC_CALL) { |
kenjiArai | 0:5b88d5760320 | 537 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 538 | } |
kenjiArai | 0:5b88d5760320 | 539 | |
kenjiArai | 0:5b88d5760320 | 540 | /* |
kenjiArai | 0:5b88d5760320 | 541 | * It is a fatal error if invec_idx is equal to or greater than |
kenjiArai | 0:5b88d5760320 | 542 | * PSA_MAX_IOVEC |
kenjiArai | 0:5b88d5760320 | 543 | */ |
kenjiArai | 0:5b88d5760320 | 544 | if (invec_idx >= PSA_MAX_IOVEC) { |
kenjiArai | 0:5b88d5760320 | 545 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 546 | } |
kenjiArai | 0:5b88d5760320 | 547 | |
kenjiArai | 0:5b88d5760320 | 548 | /* There was no remaining data in this input vector */ |
kenjiArai | 0:5b88d5760320 | 549 | if (msg->msg.in_size[invec_idx] == 0) { |
kenjiArai | 0:5b88d5760320 | 550 | return 0; |
kenjiArai | 0:5b88d5760320 | 551 | } |
kenjiArai | 0:5b88d5760320 | 552 | |
kenjiArai | 0:5b88d5760320 | 553 | /* |
kenjiArai | 0:5b88d5760320 | 554 | * Copy the client data to the service buffer. It is a fatal error |
kenjiArai | 0:5b88d5760320 | 555 | * if the memory reference for buffer is invalid or not read-write. |
kenjiArai | 0:5b88d5760320 | 556 | */ |
kenjiArai | 0:5b88d5760320 | 557 | if (tfm_memory_check(buffer, num_bytes, false, |
kenjiArai | 0:5b88d5760320 | 558 | TFM_MEMORY_ACCESS_RW, privileged) != IPC_SUCCESS) { |
kenjiArai | 0:5b88d5760320 | 559 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 560 | } |
kenjiArai | 0:5b88d5760320 | 561 | |
kenjiArai | 0:5b88d5760320 | 562 | bytes = num_bytes > msg->msg.in_size[invec_idx] ? |
kenjiArai | 0:5b88d5760320 | 563 | msg->msg.in_size[invec_idx] : num_bytes; |
kenjiArai | 0:5b88d5760320 | 564 | |
kenjiArai | 0:5b88d5760320 | 565 | tfm_memcpy(buffer, msg->invec[invec_idx].base, bytes); |
kenjiArai | 0:5b88d5760320 | 566 | |
kenjiArai | 0:5b88d5760320 | 567 | /* There maybe some remaining data */ |
kenjiArai | 0:5b88d5760320 | 568 | msg->invec[invec_idx].base += bytes; |
kenjiArai | 0:5b88d5760320 | 569 | msg->msg.in_size[invec_idx] -= bytes; |
kenjiArai | 0:5b88d5760320 | 570 | |
kenjiArai | 0:5b88d5760320 | 571 | return bytes; |
kenjiArai | 0:5b88d5760320 | 572 | } |
kenjiArai | 0:5b88d5760320 | 573 | |
kenjiArai | 0:5b88d5760320 | 574 | /** |
kenjiArai | 0:5b88d5760320 | 575 | * \brief SVC handler for \ref psa_skip. |
kenjiArai | 0:5b88d5760320 | 576 | * |
kenjiArai | 0:5b88d5760320 | 577 | * \param[in] args Include all input arguments: |
kenjiArai | 0:5b88d5760320 | 578 | * msg_handle, invec_idx, num_bytes. |
kenjiArai | 0:5b88d5760320 | 579 | * |
kenjiArai | 0:5b88d5760320 | 580 | * \retval >0 Number of bytes skipped. |
kenjiArai | 0:5b88d5760320 | 581 | * \retval 0 There was no remaining data in this input |
kenjiArai | 0:5b88d5760320 | 582 | * vector. |
kenjiArai | 0:5b88d5760320 | 583 | * \retval "Does not return" The call is invalid, one or more of the |
kenjiArai | 0:5b88d5760320 | 584 | * following are true: |
kenjiArai | 0:5b88d5760320 | 585 | * \arg msg_handle is invalid. |
kenjiArai | 0:5b88d5760320 | 586 | * \arg msg_handle does not refer to a |
kenjiArai | 0:5b88d5760320 | 587 | * \ref PSA_IPC_CALL message. |
kenjiArai | 0:5b88d5760320 | 588 | * \arg invec_idx is equal to or greater than |
kenjiArai | 0:5b88d5760320 | 589 | * \ref PSA_MAX_IOVEC. |
kenjiArai | 0:5b88d5760320 | 590 | */ |
kenjiArai | 0:5b88d5760320 | 591 | static size_t tfm_svcall_psa_skip(uint32_t *args) |
kenjiArai | 0:5b88d5760320 | 592 | { |
kenjiArai | 0:5b88d5760320 | 593 | psa_handle_t msg_handle; |
kenjiArai | 0:5b88d5760320 | 594 | uint32_t invec_idx; |
kenjiArai | 0:5b88d5760320 | 595 | size_t num_bytes; |
kenjiArai | 0:5b88d5760320 | 596 | struct tfm_msg_body_t *msg = NULL; |
kenjiArai | 0:5b88d5760320 | 597 | |
kenjiArai | 0:5b88d5760320 | 598 | TFM_ASSERT(args != NULL); |
kenjiArai | 0:5b88d5760320 | 599 | msg_handle = (psa_handle_t)args[0]; |
kenjiArai | 0:5b88d5760320 | 600 | invec_idx = args[1]; |
kenjiArai | 0:5b88d5760320 | 601 | num_bytes = (size_t)args[2]; |
kenjiArai | 0:5b88d5760320 | 602 | |
kenjiArai | 0:5b88d5760320 | 603 | /* It is a fatal error if message handle is invalid */ |
kenjiArai | 0:5b88d5760320 | 604 | msg = tfm_spm_get_msg_from_handle(msg_handle); |
kenjiArai | 0:5b88d5760320 | 605 | if (!msg) { |
kenjiArai | 0:5b88d5760320 | 606 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 607 | } |
kenjiArai | 0:5b88d5760320 | 608 | |
kenjiArai | 0:5b88d5760320 | 609 | /* |
kenjiArai | 0:5b88d5760320 | 610 | * It is a fatal error if message handle does not refer to a PSA_IPC_CALL |
kenjiArai | 0:5b88d5760320 | 611 | * message |
kenjiArai | 0:5b88d5760320 | 612 | */ |
kenjiArai | 0:5b88d5760320 | 613 | if (msg->msg.type != PSA_IPC_CALL) { |
kenjiArai | 0:5b88d5760320 | 614 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 615 | } |
kenjiArai | 0:5b88d5760320 | 616 | |
kenjiArai | 0:5b88d5760320 | 617 | /* |
kenjiArai | 0:5b88d5760320 | 618 | * It is a fatal error if invec_idx is equal to or greater than |
kenjiArai | 0:5b88d5760320 | 619 | * PSA_MAX_IOVEC |
kenjiArai | 0:5b88d5760320 | 620 | */ |
kenjiArai | 0:5b88d5760320 | 621 | if (invec_idx >= PSA_MAX_IOVEC) { |
kenjiArai | 0:5b88d5760320 | 622 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 623 | } |
kenjiArai | 0:5b88d5760320 | 624 | |
kenjiArai | 0:5b88d5760320 | 625 | /* There was no remaining data in this input vector */ |
kenjiArai | 0:5b88d5760320 | 626 | if (msg->msg.in_size[invec_idx] == 0) { |
kenjiArai | 0:5b88d5760320 | 627 | return 0; |
kenjiArai | 0:5b88d5760320 | 628 | } |
kenjiArai | 0:5b88d5760320 | 629 | |
kenjiArai | 0:5b88d5760320 | 630 | /* |
kenjiArai | 0:5b88d5760320 | 631 | * If num_bytes is greater than the remaining size of the input vector then |
kenjiArai | 0:5b88d5760320 | 632 | * the remaining size of the input vector is used. |
kenjiArai | 0:5b88d5760320 | 633 | */ |
kenjiArai | 0:5b88d5760320 | 634 | if (num_bytes > msg->msg.in_size[invec_idx]) { |
kenjiArai | 0:5b88d5760320 | 635 | num_bytes = msg->msg.in_size[invec_idx]; |
kenjiArai | 0:5b88d5760320 | 636 | } |
kenjiArai | 0:5b88d5760320 | 637 | |
kenjiArai | 0:5b88d5760320 | 638 | /* There maybe some remaining data */ |
kenjiArai | 0:5b88d5760320 | 639 | msg->invec[invec_idx].base += num_bytes; |
kenjiArai | 0:5b88d5760320 | 640 | msg->msg.in_size[invec_idx] -= num_bytes; |
kenjiArai | 0:5b88d5760320 | 641 | |
kenjiArai | 0:5b88d5760320 | 642 | return num_bytes; |
kenjiArai | 0:5b88d5760320 | 643 | } |
kenjiArai | 0:5b88d5760320 | 644 | |
kenjiArai | 0:5b88d5760320 | 645 | /** |
kenjiArai | 0:5b88d5760320 | 646 | * \brief SVC handler for \ref psa_write. |
kenjiArai | 0:5b88d5760320 | 647 | * |
kenjiArai | 0:5b88d5760320 | 648 | * \param[in] args Include all input arguments: |
kenjiArai | 0:5b88d5760320 | 649 | * msg_handle, outvec_idx, buffer, num_bytes. |
kenjiArai | 0:5b88d5760320 | 650 | * |
kenjiArai | 0:5b88d5760320 | 651 | * \retval void Success |
kenjiArai | 0:5b88d5760320 | 652 | * \retval "Does not return" The call is invalid, one or more of the |
kenjiArai | 0:5b88d5760320 | 653 | * following are true: |
kenjiArai | 0:5b88d5760320 | 654 | * \arg msg_handle is invalid. |
kenjiArai | 0:5b88d5760320 | 655 | * \arg msg_handle does not refer to a |
kenjiArai | 0:5b88d5760320 | 656 | * \ref PSA_IPC_CALL message. |
kenjiArai | 0:5b88d5760320 | 657 | * \arg outvec_idx is equal to or greater than |
kenjiArai | 0:5b88d5760320 | 658 | * \ref PSA_MAX_IOVEC. |
kenjiArai | 0:5b88d5760320 | 659 | * \arg The memory reference for buffer is invalid. |
kenjiArai | 0:5b88d5760320 | 660 | * \arg The call attempts to write data past the end |
kenjiArai | 0:5b88d5760320 | 661 | * of the client output vector. |
kenjiArai | 0:5b88d5760320 | 662 | */ |
kenjiArai | 0:5b88d5760320 | 663 | static void tfm_svcall_psa_write(uint32_t *args) |
kenjiArai | 0:5b88d5760320 | 664 | { |
kenjiArai | 0:5b88d5760320 | 665 | psa_handle_t msg_handle; |
kenjiArai | 0:5b88d5760320 | 666 | uint32_t outvec_idx; |
kenjiArai | 0:5b88d5760320 | 667 | void *buffer = NULL; |
kenjiArai | 0:5b88d5760320 | 668 | size_t num_bytes; |
kenjiArai | 0:5b88d5760320 | 669 | struct tfm_msg_body_t *msg = NULL; |
kenjiArai | 0:5b88d5760320 | 670 | uint32_t privileged; |
kenjiArai | 0:5b88d5760320 | 671 | struct tfm_spm_ipc_partition_t *partition = NULL; |
kenjiArai | 0:5b88d5760320 | 672 | |
kenjiArai | 0:5b88d5760320 | 673 | TFM_ASSERT(args != NULL); |
kenjiArai | 0:5b88d5760320 | 674 | msg_handle = (psa_handle_t)args[0]; |
kenjiArai | 0:5b88d5760320 | 675 | outvec_idx = args[1]; |
kenjiArai | 0:5b88d5760320 | 676 | buffer = (void *)args[2]; |
kenjiArai | 0:5b88d5760320 | 677 | num_bytes = (size_t)args[3]; |
kenjiArai | 0:5b88d5760320 | 678 | |
kenjiArai | 0:5b88d5760320 | 679 | /* It is a fatal error if message handle is invalid */ |
kenjiArai | 0:5b88d5760320 | 680 | msg = tfm_spm_get_msg_from_handle(msg_handle); |
kenjiArai | 0:5b88d5760320 | 681 | if (!msg) { |
kenjiArai | 0:5b88d5760320 | 682 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 683 | } |
kenjiArai | 0:5b88d5760320 | 684 | |
kenjiArai | 0:5b88d5760320 | 685 | partition = msg->service->partition; |
kenjiArai | 0:5b88d5760320 | 686 | privileged = tfm_spm_partition_get_privileged_mode(partition->index); |
kenjiArai | 0:5b88d5760320 | 687 | |
kenjiArai | 0:5b88d5760320 | 688 | /* |
kenjiArai | 0:5b88d5760320 | 689 | * It is a fatal error if message handle does not refer to a PSA_IPC_CALL |
kenjiArai | 0:5b88d5760320 | 690 | * message |
kenjiArai | 0:5b88d5760320 | 691 | */ |
kenjiArai | 0:5b88d5760320 | 692 | if (msg->msg.type != PSA_IPC_CALL) { |
kenjiArai | 0:5b88d5760320 | 693 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 694 | } |
kenjiArai | 0:5b88d5760320 | 695 | |
kenjiArai | 0:5b88d5760320 | 696 | /* |
kenjiArai | 0:5b88d5760320 | 697 | * It is a fatal error if outvec_idx is equal to or greater than |
kenjiArai | 0:5b88d5760320 | 698 | * PSA_MAX_IOVEC |
kenjiArai | 0:5b88d5760320 | 699 | */ |
kenjiArai | 0:5b88d5760320 | 700 | if (outvec_idx >= PSA_MAX_IOVEC) { |
kenjiArai | 0:5b88d5760320 | 701 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 702 | } |
kenjiArai | 0:5b88d5760320 | 703 | |
kenjiArai | 0:5b88d5760320 | 704 | /* |
kenjiArai | 0:5b88d5760320 | 705 | * It is a fatal error if the call attempts to write data past the end of |
kenjiArai | 0:5b88d5760320 | 706 | * the client output vector |
kenjiArai | 0:5b88d5760320 | 707 | */ |
kenjiArai | 0:5b88d5760320 | 708 | if (num_bytes > msg->msg.out_size[outvec_idx] - |
kenjiArai | 0:5b88d5760320 | 709 | msg->outvec[outvec_idx].len) { |
kenjiArai | 0:5b88d5760320 | 710 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 711 | } |
kenjiArai | 0:5b88d5760320 | 712 | |
kenjiArai | 0:5b88d5760320 | 713 | /* |
kenjiArai | 0:5b88d5760320 | 714 | * Copy the service buffer to client outvecs. It is a fatal error |
kenjiArai | 0:5b88d5760320 | 715 | * if the memory reference for buffer is invalid or not readable. |
kenjiArai | 0:5b88d5760320 | 716 | */ |
kenjiArai | 0:5b88d5760320 | 717 | if (tfm_memory_check(buffer, num_bytes, false, |
kenjiArai | 0:5b88d5760320 | 718 | TFM_MEMORY_ACCESS_RO, privileged) != IPC_SUCCESS) { |
kenjiArai | 0:5b88d5760320 | 719 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 720 | } |
kenjiArai | 0:5b88d5760320 | 721 | |
kenjiArai | 0:5b88d5760320 | 722 | tfm_memcpy(msg->outvec[outvec_idx].base + msg->outvec[outvec_idx].len, |
kenjiArai | 0:5b88d5760320 | 723 | buffer, num_bytes); |
kenjiArai | 0:5b88d5760320 | 724 | |
kenjiArai | 0:5b88d5760320 | 725 | /* Update the write number */ |
kenjiArai | 0:5b88d5760320 | 726 | msg->outvec[outvec_idx].len += num_bytes; |
kenjiArai | 0:5b88d5760320 | 727 | } |
kenjiArai | 0:5b88d5760320 | 728 | |
kenjiArai | 0:5b88d5760320 | 729 | static void update_caller_outvec_len(struct tfm_msg_body_t *msg) |
kenjiArai | 0:5b88d5760320 | 730 | { |
kenjiArai | 0:5b88d5760320 | 731 | int32_t i = 0; |
kenjiArai | 0:5b88d5760320 | 732 | |
kenjiArai | 0:5b88d5760320 | 733 | /* |
kenjiArai | 0:5b88d5760320 | 734 | * FixeMe: abstract these part into dedicated functions to avoid |
kenjiArai | 0:5b88d5760320 | 735 | * accessing thread context in psa layer |
kenjiArai | 0:5b88d5760320 | 736 | */ |
kenjiArai | 0:5b88d5760320 | 737 | TFM_ASSERT(msg->ack_evnt.owner->status == THRD_STAT_BLOCK); |
kenjiArai | 0:5b88d5760320 | 738 | |
kenjiArai | 0:5b88d5760320 | 739 | while (msg->msg.out_size[i] != 0) { |
kenjiArai | 0:5b88d5760320 | 740 | TFM_ASSERT(msg->caller_outvec[i].base == msg->outvec[i].base); |
kenjiArai | 0:5b88d5760320 | 741 | msg->caller_outvec[i].len = msg->outvec[i].len; |
kenjiArai | 0:5b88d5760320 | 742 | i++; |
kenjiArai | 0:5b88d5760320 | 743 | } |
kenjiArai | 0:5b88d5760320 | 744 | } |
kenjiArai | 0:5b88d5760320 | 745 | /** |
kenjiArai | 0:5b88d5760320 | 746 | * \brief SVC handler for \ref psa_reply. |
kenjiArai | 0:5b88d5760320 | 747 | * |
kenjiArai | 0:5b88d5760320 | 748 | * \param[in] args Include all input arguments: |
kenjiArai | 0:5b88d5760320 | 749 | * msg_handle, status. |
kenjiArai | 0:5b88d5760320 | 750 | * |
kenjiArai | 0:5b88d5760320 | 751 | * \retval void Success. |
kenjiArai | 0:5b88d5760320 | 752 | * \retval "Does not return" The call is invalid, one or more of the |
kenjiArai | 0:5b88d5760320 | 753 | * following are true: |
kenjiArai | 0:5b88d5760320 | 754 | * \arg msg_handle is invalid. |
kenjiArai | 0:5b88d5760320 | 755 | * \arg An invalid status code is specified for the |
kenjiArai | 0:5b88d5760320 | 756 | * type of message. |
kenjiArai | 0:5b88d5760320 | 757 | */ |
kenjiArai | 0:5b88d5760320 | 758 | static void tfm_svcall_psa_reply(uint32_t *args) |
kenjiArai | 0:5b88d5760320 | 759 | { |
kenjiArai | 0:5b88d5760320 | 760 | psa_handle_t msg_handle; |
kenjiArai | 0:5b88d5760320 | 761 | psa_status_t status; |
kenjiArai | 0:5b88d5760320 | 762 | struct tfm_spm_service_t *service = NULL; |
kenjiArai | 0:5b88d5760320 | 763 | struct tfm_msg_body_t *msg = NULL; |
kenjiArai | 0:5b88d5760320 | 764 | psa_handle_t connect_handle; |
kenjiArai | 0:5b88d5760320 | 765 | int32_t ret = PSA_SUCCESS; |
kenjiArai | 0:5b88d5760320 | 766 | |
kenjiArai | 0:5b88d5760320 | 767 | TFM_ASSERT(args != NULL); |
kenjiArai | 0:5b88d5760320 | 768 | msg_handle = (psa_handle_t)args[0]; |
kenjiArai | 0:5b88d5760320 | 769 | status = (psa_status_t)args[1]; |
kenjiArai | 0:5b88d5760320 | 770 | |
kenjiArai | 0:5b88d5760320 | 771 | /* It is a fatal error if message handle is invalid */ |
kenjiArai | 0:5b88d5760320 | 772 | msg = tfm_spm_get_msg_from_handle(msg_handle); |
kenjiArai | 0:5b88d5760320 | 773 | if (!msg) { |
kenjiArai | 0:5b88d5760320 | 774 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 775 | } |
kenjiArai | 0:5b88d5760320 | 776 | |
kenjiArai | 0:5b88d5760320 | 777 | /* |
kenjiArai | 0:5b88d5760320 | 778 | * RoT Service information is needed in this function, stored it in message |
kenjiArai | 0:5b88d5760320 | 779 | * body structure. Only two parameters are passed in this function: handle |
kenjiArai | 0:5b88d5760320 | 780 | * and status, so it is useful and simply to do like this. |
kenjiArai | 0:5b88d5760320 | 781 | */ |
kenjiArai | 0:5b88d5760320 | 782 | service = msg->service; |
kenjiArai | 0:5b88d5760320 | 783 | if (!service) { |
kenjiArai | 0:5b88d5760320 | 784 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 785 | } |
kenjiArai | 0:5b88d5760320 | 786 | |
kenjiArai | 0:5b88d5760320 | 787 | /* |
kenjiArai | 0:5b88d5760320 | 788 | * Three type of message are passed in this function: CONNECT, CALL, |
kenjiArai | 0:5b88d5760320 | 789 | * DISCONNECT. It needs to process differently for each type. |
kenjiArai | 0:5b88d5760320 | 790 | */ |
kenjiArai | 0:5b88d5760320 | 791 | switch (msg->msg.type) { |
kenjiArai | 0:5b88d5760320 | 792 | case PSA_IPC_CONNECT: |
kenjiArai | 0:5b88d5760320 | 793 | /* |
kenjiArai | 0:5b88d5760320 | 794 | * Reply to PSA_IPC_CONNECT message. Connect handle is created if the |
kenjiArai | 0:5b88d5760320 | 795 | * input status is PSA_SUCCESS. Others return values are based on the |
kenjiArai | 0:5b88d5760320 | 796 | * input status. |
kenjiArai | 0:5b88d5760320 | 797 | */ |
kenjiArai | 0:5b88d5760320 | 798 | if (status == PSA_SUCCESS) { |
kenjiArai | 0:5b88d5760320 | 799 | connect_handle = tfm_spm_create_conn_handle(service); |
kenjiArai | 0:5b88d5760320 | 800 | if (connect_handle == PSA_NULL_HANDLE) { |
kenjiArai | 0:5b88d5760320 | 801 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 802 | } |
kenjiArai | 0:5b88d5760320 | 803 | ret = connect_handle; |
kenjiArai | 0:5b88d5760320 | 804 | |
kenjiArai | 0:5b88d5760320 | 805 | /* Set reverse handle after connection created if needed. */ |
kenjiArai | 0:5b88d5760320 | 806 | if (msg->msg.rhandle) { |
kenjiArai | 0:5b88d5760320 | 807 | tfm_spm_set_rhandle(service, connect_handle, msg->msg.rhandle); |
kenjiArai | 0:5b88d5760320 | 808 | } |
kenjiArai | 0:5b88d5760320 | 809 | } else if (status == PSA_CONNECTION_REFUSED) { |
kenjiArai | 0:5b88d5760320 | 810 | ret = PSA_CONNECTION_REFUSED; |
kenjiArai | 0:5b88d5760320 | 811 | } else if (status == PSA_CONNECTION_BUSY) { |
kenjiArai | 0:5b88d5760320 | 812 | ret = PSA_CONNECTION_BUSY; |
kenjiArai | 0:5b88d5760320 | 813 | } else { |
kenjiArai | 0:5b88d5760320 | 814 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 815 | } |
kenjiArai | 0:5b88d5760320 | 816 | break; |
kenjiArai | 0:5b88d5760320 | 817 | case PSA_IPC_CALL: |
kenjiArai | 0:5b88d5760320 | 818 | /* Reply to PSA_IPC_CALL message. Return values are based on status */ |
kenjiArai | 0:5b88d5760320 | 819 | if (status == PSA_SUCCESS) { |
kenjiArai | 0:5b88d5760320 | 820 | ret = PSA_SUCCESS; |
kenjiArai | 0:5b88d5760320 | 821 | } else if (status == PSA_DROP_CONNECTION) { |
kenjiArai | 0:5b88d5760320 | 822 | ret = PSA_DROP_CONNECTION; |
kenjiArai | 0:5b88d5760320 | 823 | } else if ((status >= (INT32_MIN + 1)) && |
kenjiArai | 0:5b88d5760320 | 824 | (status <= (INT32_MIN + 127))) { |
kenjiArai | 0:5b88d5760320 | 825 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 826 | } else if ((status >= (INT32_MIN + 128)) && (status <= -1)) { |
kenjiArai | 0:5b88d5760320 | 827 | ret = status; |
kenjiArai | 0:5b88d5760320 | 828 | } else if ((status >= 1) && (status <= INT32_MAX)) { |
kenjiArai | 0:5b88d5760320 | 829 | ret = status; |
kenjiArai | 0:5b88d5760320 | 830 | } else { |
kenjiArai | 0:5b88d5760320 | 831 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 832 | } |
kenjiArai | 0:5b88d5760320 | 833 | |
kenjiArai | 0:5b88d5760320 | 834 | /* |
kenjiArai | 0:5b88d5760320 | 835 | * The total number of bytes written to a single parameter must be |
kenjiArai | 0:5b88d5760320 | 836 | * reported to the client by updating the len member of the psa_outvec |
kenjiArai | 0:5b88d5760320 | 837 | * structure for the parameter before returning from psa_call(). |
kenjiArai | 0:5b88d5760320 | 838 | */ |
kenjiArai | 0:5b88d5760320 | 839 | update_caller_outvec_len(msg); |
kenjiArai | 0:5b88d5760320 | 840 | break; |
kenjiArai | 0:5b88d5760320 | 841 | case PSA_IPC_DISCONNECT: |
kenjiArai | 0:5b88d5760320 | 842 | /* Service handle is not used anymore */ |
kenjiArai | 0:5b88d5760320 | 843 | tfm_spm_free_conn_handle(service, msg->handle); |
kenjiArai | 0:5b88d5760320 | 844 | |
kenjiArai | 0:5b88d5760320 | 845 | /* |
kenjiArai | 0:5b88d5760320 | 846 | * If the message type is PSA_IPC_DISCONNECT, then the status code is |
kenjiArai | 0:5b88d5760320 | 847 | * ignored |
kenjiArai | 0:5b88d5760320 | 848 | */ |
kenjiArai | 0:5b88d5760320 | 849 | break; |
kenjiArai | 0:5b88d5760320 | 850 | default: |
kenjiArai | 0:5b88d5760320 | 851 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 852 | } |
kenjiArai | 0:5b88d5760320 | 853 | |
kenjiArai | 0:5b88d5760320 | 854 | tfm_event_wake(&msg->ack_evnt, ret); |
kenjiArai | 0:5b88d5760320 | 855 | |
kenjiArai | 0:5b88d5760320 | 856 | /* Message should not be unsed anymore */ |
kenjiArai | 0:5b88d5760320 | 857 | tfm_spm_free_msg(msg); |
kenjiArai | 0:5b88d5760320 | 858 | } |
kenjiArai | 0:5b88d5760320 | 859 | |
kenjiArai | 0:5b88d5760320 | 860 | /** |
kenjiArai | 0:5b88d5760320 | 861 | * \brief SVC handler for \ref psa_notify. |
kenjiArai | 0:5b88d5760320 | 862 | * |
kenjiArai | 0:5b88d5760320 | 863 | * \param[in] args Include all input arguments: partition_id. |
kenjiArai | 0:5b88d5760320 | 864 | * |
kenjiArai | 0:5b88d5760320 | 865 | * \retval void Success. |
kenjiArai | 0:5b88d5760320 | 866 | * \retval "Does not return" partition_id does not correspond to a Secure |
kenjiArai | 0:5b88d5760320 | 867 | * Partition. |
kenjiArai | 0:5b88d5760320 | 868 | */ |
kenjiArai | 0:5b88d5760320 | 869 | static void tfm_svcall_psa_notify(uint32_t *args) |
kenjiArai | 0:5b88d5760320 | 870 | { |
kenjiArai | 0:5b88d5760320 | 871 | int32_t partition_id; |
kenjiArai | 0:5b88d5760320 | 872 | struct tfm_spm_ipc_partition_t *partition = NULL; |
kenjiArai | 0:5b88d5760320 | 873 | |
kenjiArai | 0:5b88d5760320 | 874 | TFM_ASSERT(args != NULL); |
kenjiArai | 0:5b88d5760320 | 875 | partition_id = (int32_t)args[0]; |
kenjiArai | 0:5b88d5760320 | 876 | |
kenjiArai | 0:5b88d5760320 | 877 | /* |
kenjiArai | 0:5b88d5760320 | 878 | * The value of partition_id must be greater than zero as the target of |
kenjiArai | 0:5b88d5760320 | 879 | * notification must be a Secure Partition, providing a Non-secure |
kenjiArai | 0:5b88d5760320 | 880 | * Partition ID is a fatal error. |
kenjiArai | 0:5b88d5760320 | 881 | */ |
kenjiArai | 0:5b88d5760320 | 882 | if (!TFM_CLIENT_ID_IS_S(partition_id)) { |
kenjiArai | 0:5b88d5760320 | 883 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 884 | } |
kenjiArai | 0:5b88d5760320 | 885 | |
kenjiArai | 0:5b88d5760320 | 886 | /* |
kenjiArai | 0:5b88d5760320 | 887 | * It is a fatal error if partition_id does not correspond to a Secure |
kenjiArai | 0:5b88d5760320 | 888 | * Partition. |
kenjiArai | 0:5b88d5760320 | 889 | */ |
kenjiArai | 0:5b88d5760320 | 890 | partition = tfm_spm_get_partition_by_id(partition_id); |
kenjiArai | 0:5b88d5760320 | 891 | if (!partition) { |
kenjiArai | 0:5b88d5760320 | 892 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 893 | } |
kenjiArai | 0:5b88d5760320 | 894 | |
kenjiArai | 0:5b88d5760320 | 895 | partition->signals |= PSA_DOORBELL; |
kenjiArai | 0:5b88d5760320 | 896 | |
kenjiArai | 0:5b88d5760320 | 897 | /* |
kenjiArai | 0:5b88d5760320 | 898 | * The target partition may be blocked with waiting for signals after |
kenjiArai | 0:5b88d5760320 | 899 | * called psa_wait(). Set the return value with the available signals |
kenjiArai | 0:5b88d5760320 | 900 | * before wake it up with tfm_event_signal(). |
kenjiArai | 0:5b88d5760320 | 901 | */ |
kenjiArai | 0:5b88d5760320 | 902 | tfm_event_wake(&partition->signal_evnt, |
kenjiArai | 0:5b88d5760320 | 903 | partition->signals & partition->signal_mask); |
kenjiArai | 0:5b88d5760320 | 904 | } |
kenjiArai | 0:5b88d5760320 | 905 | |
kenjiArai | 0:5b88d5760320 | 906 | /** |
kenjiArai | 0:5b88d5760320 | 907 | * \brief SVC handler for \ref psa_clear. |
kenjiArai | 0:5b88d5760320 | 908 | * |
kenjiArai | 0:5b88d5760320 | 909 | * \retval void Success. |
kenjiArai | 0:5b88d5760320 | 910 | * \retval "Does not return" The Secure Partition's doorbell signal is not |
kenjiArai | 0:5b88d5760320 | 911 | * currently asserted. |
kenjiArai | 0:5b88d5760320 | 912 | */ |
kenjiArai | 0:5b88d5760320 | 913 | static void tfm_svcall_psa_clear(uint32_t *args) |
kenjiArai | 0:5b88d5760320 | 914 | { |
kenjiArai | 0:5b88d5760320 | 915 | struct tfm_spm_ipc_partition_t *partition = NULL; |
kenjiArai | 0:5b88d5760320 | 916 | |
kenjiArai | 0:5b88d5760320 | 917 | partition = tfm_spm_get_running_partition(); |
kenjiArai | 0:5b88d5760320 | 918 | if (!partition) { |
kenjiArai | 0:5b88d5760320 | 919 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 920 | } |
kenjiArai | 0:5b88d5760320 | 921 | |
kenjiArai | 0:5b88d5760320 | 922 | /* |
kenjiArai | 0:5b88d5760320 | 923 | * It is a fatal error if the Secure Partition's doorbell signal is not |
kenjiArai | 0:5b88d5760320 | 924 | * currently asserted. |
kenjiArai | 0:5b88d5760320 | 925 | */ |
kenjiArai | 0:5b88d5760320 | 926 | if ((partition->signals & PSA_DOORBELL) == 0) { |
kenjiArai | 0:5b88d5760320 | 927 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 928 | } |
kenjiArai | 0:5b88d5760320 | 929 | partition->signals &= ~PSA_DOORBELL; |
kenjiArai | 0:5b88d5760320 | 930 | } |
kenjiArai | 0:5b88d5760320 | 931 | |
kenjiArai | 0:5b88d5760320 | 932 | /** |
kenjiArai | 0:5b88d5760320 | 933 | * \brief SVC handler for \ref psa_eoi. |
kenjiArai | 0:5b88d5760320 | 934 | * |
kenjiArai | 0:5b88d5760320 | 935 | * \param[in] args Include all input arguments: irq_signal. |
kenjiArai | 0:5b88d5760320 | 936 | * |
kenjiArai | 0:5b88d5760320 | 937 | * \retval void Success. |
kenjiArai | 0:5b88d5760320 | 938 | * \retval "Does not return" The call is invalid, one or more of the |
kenjiArai | 0:5b88d5760320 | 939 | * following are true: |
kenjiArai | 0:5b88d5760320 | 940 | * \arg irq_signal is not an interrupt signal. |
kenjiArai | 0:5b88d5760320 | 941 | * \arg irq_signal indicates more than one signal. |
kenjiArai | 0:5b88d5760320 | 942 | * \arg irq_signal is not currently asserted. |
kenjiArai | 0:5b88d5760320 | 943 | */ |
kenjiArai | 0:5b88d5760320 | 944 | static void tfm_svcall_psa_eoi(uint32_t *args) |
kenjiArai | 0:5b88d5760320 | 945 | { |
kenjiArai | 0:5b88d5760320 | 946 | psa_signal_t irq_signal; |
kenjiArai | 0:5b88d5760320 | 947 | struct tfm_spm_ipc_partition_t *partition = NULL; |
kenjiArai | 0:5b88d5760320 | 948 | |
kenjiArai | 0:5b88d5760320 | 949 | TFM_ASSERT(args != NULL); |
kenjiArai | 0:5b88d5760320 | 950 | irq_signal = (psa_signal_t)args[0]; |
kenjiArai | 0:5b88d5760320 | 951 | |
kenjiArai | 0:5b88d5760320 | 952 | partition = tfm_spm_get_running_partition(); |
kenjiArai | 0:5b88d5760320 | 953 | if (!partition) { |
kenjiArai | 0:5b88d5760320 | 954 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 955 | } |
kenjiArai | 0:5b88d5760320 | 956 | |
kenjiArai | 0:5b88d5760320 | 957 | /* |
kenjiArai | 0:5b88d5760320 | 958 | * FixMe: It is a fatal error if passed signal is not an interrupt signal. |
kenjiArai | 0:5b88d5760320 | 959 | */ |
kenjiArai | 0:5b88d5760320 | 960 | |
kenjiArai | 0:5b88d5760320 | 961 | /* It is a fatal error if passed signal indicates more than one signals. */ |
kenjiArai | 0:5b88d5760320 | 962 | if (tfm_bitcount(partition->signals) != 1) { |
kenjiArai | 0:5b88d5760320 | 963 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 964 | } |
kenjiArai | 0:5b88d5760320 | 965 | |
kenjiArai | 0:5b88d5760320 | 966 | /* It is a fatal error if passed signal is not currently asserted */ |
kenjiArai | 0:5b88d5760320 | 967 | if ((partition->signals & irq_signal) == 0) { |
kenjiArai | 0:5b88d5760320 | 968 | tfm_panic(); |
kenjiArai | 0:5b88d5760320 | 969 | } |
kenjiArai | 0:5b88d5760320 | 970 | |
kenjiArai | 0:5b88d5760320 | 971 | partition->signals &= ~irq_signal; |
kenjiArai | 0:5b88d5760320 | 972 | |
kenjiArai | 0:5b88d5760320 | 973 | /* FixMe: re-enable interrupt */ |
kenjiArai | 0:5b88d5760320 | 974 | } |
kenjiArai | 0:5b88d5760320 | 975 | |
kenjiArai | 0:5b88d5760320 | 976 | int32_t SVC_Handler_IPC(tfm_svc_number_t svc_num, uint32_t *ctx, uint32_t lr) |
kenjiArai | 0:5b88d5760320 | 977 | { |
kenjiArai | 0:5b88d5760320 | 978 | switch (svc_num) { |
kenjiArai | 0:5b88d5760320 | 979 | case TFM_SVC_SCHEDULE: |
kenjiArai | 0:5b88d5760320 | 980 | tfm_thrd_activate_schedule(); |
kenjiArai | 0:5b88d5760320 | 981 | break; |
kenjiArai | 0:5b88d5760320 | 982 | case TFM_SVC_EXIT_THRD: |
kenjiArai | 0:5b88d5760320 | 983 | tfm_svcall_thrd_exit(); |
kenjiArai | 0:5b88d5760320 | 984 | break; |
kenjiArai | 0:5b88d5760320 | 985 | case TFM_SVC_PSA_FRAMEWORK_VERSION: |
kenjiArai | 0:5b88d5760320 | 986 | return tfm_svcall_psa_framework_version(); |
kenjiArai | 0:5b88d5760320 | 987 | case TFM_SVC_PSA_VERSION: |
kenjiArai | 0:5b88d5760320 | 988 | return tfm_svcall_psa_version(ctx, 0); |
kenjiArai | 0:5b88d5760320 | 989 | case TFM_SVC_PSA_CONNECT: |
kenjiArai | 0:5b88d5760320 | 990 | return tfm_svcall_psa_connect(ctx, 0); |
kenjiArai | 0:5b88d5760320 | 991 | case TFM_SVC_PSA_CALL: |
kenjiArai | 0:5b88d5760320 | 992 | return tfm_svcall_psa_call(ctx, 0, lr); |
kenjiArai | 0:5b88d5760320 | 993 | case TFM_SVC_PSA_CLOSE: |
kenjiArai | 0:5b88d5760320 | 994 | tfm_svcall_psa_close(ctx, 0); |
kenjiArai | 0:5b88d5760320 | 995 | break; |
kenjiArai | 0:5b88d5760320 | 996 | case TFM_SVC_PSA_WAIT: |
kenjiArai | 0:5b88d5760320 | 997 | return tfm_svcall_psa_wait(ctx); |
kenjiArai | 0:5b88d5760320 | 998 | case TFM_SVC_PSA_GET: |
kenjiArai | 0:5b88d5760320 | 999 | return tfm_svcall_psa_get(ctx); |
kenjiArai | 0:5b88d5760320 | 1000 | case TFM_SVC_PSA_SET_RHANDLE: |
kenjiArai | 0:5b88d5760320 | 1001 | tfm_svcall_psa_set_rhandle(ctx); |
kenjiArai | 0:5b88d5760320 | 1002 | break; |
kenjiArai | 0:5b88d5760320 | 1003 | case TFM_SVC_PSA_READ: |
kenjiArai | 0:5b88d5760320 | 1004 | return tfm_svcall_psa_read(ctx); |
kenjiArai | 0:5b88d5760320 | 1005 | case TFM_SVC_PSA_SKIP: |
kenjiArai | 0:5b88d5760320 | 1006 | return tfm_svcall_psa_skip(ctx); |
kenjiArai | 0:5b88d5760320 | 1007 | case TFM_SVC_PSA_WRITE: |
kenjiArai | 0:5b88d5760320 | 1008 | tfm_svcall_psa_write(ctx); |
kenjiArai | 0:5b88d5760320 | 1009 | break; |
kenjiArai | 0:5b88d5760320 | 1010 | case TFM_SVC_PSA_REPLY: |
kenjiArai | 0:5b88d5760320 | 1011 | tfm_svcall_psa_reply(ctx); |
kenjiArai | 0:5b88d5760320 | 1012 | break; |
kenjiArai | 0:5b88d5760320 | 1013 | case TFM_SVC_PSA_NOTIFY: |
kenjiArai | 0:5b88d5760320 | 1014 | tfm_svcall_psa_notify(ctx); |
kenjiArai | 0:5b88d5760320 | 1015 | break; |
kenjiArai | 0:5b88d5760320 | 1016 | case TFM_SVC_PSA_CLEAR: |
kenjiArai | 0:5b88d5760320 | 1017 | tfm_svcall_psa_clear(ctx); |
kenjiArai | 0:5b88d5760320 | 1018 | break; |
kenjiArai | 0:5b88d5760320 | 1019 | case TFM_SVC_PSA_EOI: |
kenjiArai | 0:5b88d5760320 | 1020 | tfm_svcall_psa_eoi(ctx); |
kenjiArai | 0:5b88d5760320 | 1021 | break; |
kenjiArai | 0:5b88d5760320 | 1022 | default: |
kenjiArai | 0:5b88d5760320 | 1023 | break; |
kenjiArai | 0:5b88d5760320 | 1024 | } |
kenjiArai | 0:5b88d5760320 | 1025 | return PSA_SUCCESS; |
kenjiArai | 0:5b88d5760320 | 1026 | } |