/* Copyright (c) 2017-2018 ARM Limited * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef SPM_INTERNAL_H #define SPM_INTERNAL_H #include <stdbool.h> #include "cmsis_os2.h" #include "cmsis.h" #include "psa_defs.h" #include "spm_messages.h" #include "spm_panic.h" #include "handles_manager.h" #include "cmsis_compiler.h" #ifdef __cplusplus extern "C" { #endif #define SPM_COMPLETION_SEM_MAX_COUNT (1UL) /* Maximum number of available tokens for a completion semaphore. */ #define SPM_COMPLETION_SEM_INITIAL_COUNT (0UL) /* Initial number of available tokens for a completion semaphore. */ #define PSA_MMIO_PERM_READ_ONLY (0x000000001) #define PSA_MMIO_PERM_READ_WRITE (0x000000003) #define PSA_RESERVED_ERROR_MIN (INT32_MIN + 1) #define PSA_RESERVED_ERROR_MAX (INT32_MIN + 127) #define SPM_CHANNEL_STATE_INVALID (0x01) #define SPM_CHANNEL_STATE_CONNECTING (0x02) #define SPM_CHANNEL_STATE_IDLE (0x03) #define SPM_CHANNEL_STATE_PENDING (0x04) #define SPM_CHANNEL_STATE_ACTIVE (0x05) #define MEM_PARTITIONS_ALL (0) /* A constant to use to retrieve the memory regions for all the partitions at once. */ #define SPM_CMSIS_RTOS_ERROR_BIT_MSK (0x80000000) #ifndef TRUE #define TRUE (1) #endif #ifndef FALSE #define FALSE (0) #endif struct spm_partition; struct spm_ipc_channel; /* * Structure to describe MMIO region along with owning partition. */ typedef struct mem_region { const uint32_t base; const uint32_t size; const uint32_t permission; const int32_t partition_id; } mem_region_t; typedef union spm_iovec { psa_invec in; psa_outvec out; } spm_iovec_t; /* * IRQ signal mapper definition. * The function will not return on invalid signal. */ typedef IRQn_Type(*spm_signal_to_irq_mapper_t)(uint32_t); /* * Structure to aggregate channels queue in a Root of Trust Service. */ typedef struct spm_channel_linked_list { struct spm_ipc_channel *head; /* List's first object*/ struct spm_ipc_channel *tail; /* List's last object*/ } spm_channel_linked_list_t; /* * Structure containing resources and attributes of a Root of Trust Service. */ typedef struct spm_rot_service { const uint32_t sid; /* The Root of Trust Service ID.*/ const uint32_t mask; /* The signal for this Root of Trust Service*/ struct spm_partition *partition; /* Pointer to the Partition which the Root of Trust Service belongs to.*/ const uint32_t min_version; /* Minor version of the Root of Trust Service interface.*/ const uint32_t min_version_policy; /* Minor version policy of the Root of Trust Service.*/ const bool allow_nspe; /* Whether to allow non-secure clients to connect to the Root of Trust Service.*/ spm_channel_linked_list_t queue; /* Queue of channels holding ROT_SRV operations waiting to be served. */ } spm_rot_service_t; /* * Structure containing Partition->RoT-Service channel information. */ typedef struct spm_ipc_channel { struct spm_partition *src_partition; /* Pointer to the Partition which connects to the Root of Trust Service.*/ spm_rot_service_t *dst_rot_service; /* Pointer to the connected Root of Trust Service.*/ void *rhandle; /* Reverse handle to be used for this channel.*/ void *msg_ptr; /* Message data sent from user. */ struct spm_ipc_channel *next; /* Next channel in the chain.*/ uint8_t msg_type; /* The message type.*/ uint8_t state; /* The current processing state of the channel.*/ uint8_t is_dropped; /* Indicates whether the channel has been dropped by the partition.*/ } spm_ipc_channel_t; /* * Structure containing the currently active message for a Root of Trust Service. */ typedef struct spm_active_msg { spm_ipc_channel_t *channel; /* Pointer to the channel delivering this message.*/ spm_iovec_t iovecs[PSA_MAX_IOVEC]; /* IOvecs sent for message and response.*/ uint8_t out_index; /* First index of outvecs in iovecs*/ } spm_active_msg_t; /* * Structure containing resources and attributes of a secure partition. */ typedef struct spm_partition { const int32_t partition_id; /* The Partition ID.*/ osThreadId_t thread_id; /* Thread ID of the Partition thread.*/ const uint32_t flags; /* Mask of all the signals the partition supports.*/ spm_rot_service_t *rot_services; /* Array of the Partition's Root of Trust Services.*/ const uint32_t rot_services_count; /* Number of the Partition's Root of Trust Services.*/ const uint32_t *extern_sids; /* Array of Root of Trust Service IDs that the partition can connect to.*/ const uint32_t extern_sids_count; /* Number of Root of Trust Services which the partition can connect to.*/ osMutexId_t mutex; /* Mutex for all rot_service's queues operations. */ spm_signal_to_irq_mapper_t irq_mapper; /* a function which maps signal to irq number*/ } spm_partition_t; /* * Structure containing the SPM internal data. */ typedef struct spm_db { spm_partition_t *partitions; /* Array of all the Secure Partitions in the system.*/ uint32_t partition_count; /* Number of Secure Partitions in the system.*/ psa_handle_manager_t channels_handle_mgr; psa_handle_manager_t messages_handle_mgr; osMemoryPoolId_t channel_mem_pool; /* Channel memory pool identifier.*/ osMemoryPoolId_t active_messages_mem_pool; /* Channel memory pool identifier.*/ } spm_db_t; /* * Returns a pointer to the currently active secure partition or NULL in case called from NSPE. */ spm_partition_t *get_active_partition(void); /* * Return an array of memory regions used by a given partition. * * @param[in] partition_id - a partition ID to find memory regions for, if MEM_PARTITIONS_ALL then * memory regions for all the partitions are returned * @param[out] region_count - will be set to the number of memory regions returned */ const mem_region_t *get_mem_regions(int32_t partition_id, uint32_t *region_count); // Platform dependent APIs /* * Validates that a memory block accessible from a specific partition * * @param[in] ptr - Pointer to the beggining of the memory block. * @param[in] size - Size of the memory block in bytes. * @param[in] accessing_partition - Which partition is trying to access the memory. * @return `true` if the entire memory block is accessable from given partition. */ bool is_buffer_accessible(const void *ptr, size_t size, spm_partition_t *accessing_partition); /** * Alerts NSPE that a proccess (connect or call) has ended. * * @param[in] completion_sem_id - semaphore id in NSPE. */ void nspe_done(osSemaphoreId_t completion_sem_id); /* * Validates parameters sent from caller and queues a connect message on the correct ROT_SRV. * * @param[in] sid - desired RoT service ID * @param[in] msg - pointer to connect message struct */ void psa_connect_async(uint32_t sid, spm_pending_connect_msg_t *msg); /* * Validates parameters sent from caller and queues a call message on the correct ROT_SRV. * * @param[in] handle - channel handle for the connection * @param[in] msg - pointer to call message struct */ void psa_call_async(psa_handle_t handle, spm_pending_call_msg_t *msg); /* * Validates parameters sent from caller and queues a disconnect message on the correct ROT_SRV. * * @param[in] handle - handle of channel to close * @param[in] msg - pointer to close message struct */ void psa_close_async(psa_handle_t handle, spm_pending_close_msg_t *msg); /* * Validates IOvecs. * * @param[in] in_vec - psa_invec array * @param[in] in_len - number of elements in in_vec * @param[in] out_vec - psa_outvec array * @param[in] out_len - number of elements in out_vec */ void validate_iovec( const void *in_vec, const uint32_t in_len, const void *out_vec, const uint32_t out_len ); /* * Assert and modify PSA IPC channel state machine state * * @param[in,out] current_state - current state * @param[in] expected_state - expected state * @param[in] new_state - new state */ void channel_state_switch(uint8_t *current_state, uint8_t expected_state, uint8_t new_state); /* * Assert PSA IPC channel state machine state * * @param[in] current_state - current state * @param[in] expected_state - expected state */ void channel_state_assert(const uint8_t *current_state, uint8_t expected_state); #ifdef __cplusplus } #endif #endif // SPM_INTERNAL_H