aboutsummaryrefslogtreecommitdiffstats
path: root/os/common
diff options
context:
space:
mode:
authorisiora <none@example.com>2018-03-07 11:50:05 +0000
committerisiora <none@example.com>2018-03-07 11:50:05 +0000
commitdc60f9bbe50b4211a264363ee575eb3acc5ad8f5 (patch)
tree4a31367de11d87aa148b050adef6fa23aa9f10f7 /os/common
parentf5bb1e75164a0e9a33dfdfd533fa3eda7f075ee4 (diff)
downloadChibiOS-dc60f9bbe50b4211a264363ee575eb3acc5ad8f5.tar.gz
ChibiOS-dc60f9bbe50b4211a264363ee575eb3acc5ad8f5.tar.bz2
ChibiOS-dc60f9bbe50b4211a264363ee575eb3acc5ad8f5.zip
New TSSI interface.
git-svn-id: https://svn.code.sf.net/p/chibios/svn2/trunk@11612 110e8d01-0319-4d1e-a829-52ad28d1bb01
Diffstat (limited to 'os/common')
-rw-r--r--os/common/ports/ARMCAx-TZ/chtssi.c321
-rw-r--r--os/common/ports/ARMCAx-TZ/chtssi.h209
2 files changed, 530 insertions, 0 deletions
diff --git a/os/common/ports/ARMCAx-TZ/chtssi.c b/os/common/ports/ARMCAx-TZ/chtssi.c
new file mode 100644
index 000000000..1d0c2db79
--- /dev/null
+++ b/os/common/ports/ARMCAx-TZ/chtssi.c
@@ -0,0 +1,321 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ 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.
+*/
+
+/**
+ * @file chtssi.c
+ * @brief Trusted services related API and definition.
+ *
+ * @addtogroup TSSI
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+#include "chtssi.h"
+#include <string.h>
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+#define LOWORD(in64) ((int64_t)in64 & 0x0FFFFFFFF)
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/* The reference to the suspended nsec main thread.*/
+thread_reference_t _ns_thread = NULL;
+
+/* The services may broadcast and listen event flags via this object.*/
+EVENTSOURCE_DECL(tsEventSource);
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/* The ts module listen to the tsEventSource via this object.*/
+static event_listener_t tsEventListener;
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+static bool isAddrSpaceValid(uint8_t *addr, size_t size)
+{
+ //chEvtBroadcastFlags();
+ return (bool)((addr - NSEC_MEMORY_START_ADDR) <
+ (NSEC_MEMORY_END_ADDR - NSEC_MEMORY_START_ADDR)) &&
+ (bool)((addr + size - NSEC_MEMORY_START_ADDR) <
+ (NSEC_MEMORY_END_ADDR - NSEC_MEMORY_START_ADDR));
+}
+
+static bool isHndlValid(ts_state_t *handle)
+{
+ if ((handle < TS_STATE(0)) || (handle >= TS_STATE(TS_MAX_SVCS)))
+ return FALSE;
+ if (((char *)handle - (char *)TS_STATE(0)) % sizeof *TS_STATE(0))
+ return FALSE;
+ return TRUE;
+}
+
+static ts_state_t *findSvcsEntry(const char *name)
+{
+ int i;
+ for (i = 0; i < TS_MAX_SVCS; ++i) {
+ if (TS_CONF_TABLE(i)->name == NULL)
+ continue;
+ if (!strcmp(TS_CONF_TABLE(i)->name, name))
+ return TS_CONF_TABLE(i)->arg;
+ }
+ return NULL;
+}
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief The trusted service call entry point.
+ * @pre The foreign interrupts are disabled.
+ * @post A request is passed to the thread registered for the service.
+ * @post The service thread is resumed.
+ *
+ * @param[in] svc_handle the handle of the service to be invoked.
+ * @param[inout] svc_data service request data, often a reference to a more
+ * complex structure.
+ * @param[in] svc_datalen size of the svc_data memory area.
+ * @param[in] svc_timeout after this time interval, the service execution
+ * will be interrupted. Time is in microseconds.
+ * This interval represents the time slice granted
+ * to the services to continue their work.
+ *
+ * @return A 64bit value. It is the OR of the 32bit service
+ * status combined with a 32bit event mask (in the
+ * hi-word).
+ * The retval values are returned in the lower word
+ * as 32bit int.
+ * @retval SMC_SVC_OK generic success value.
+ * @retval SMC_SVC_INTR call interrupted.
+ * @retval SMC_SVC_BUSY the service has a pending request.
+ * @retval SMC_SVC_INVALID bad parameters.
+ * @retval SMC_SVC_NOENT no such service.
+ * @retval SMC_SVC_BADH bad handle.
+ *
+ * @notapi
+ */
+int64_t smcEntry(ts_state_t *svc_handle, ts_params_area_t svc_data,
+ size_t svc_datalen, sysinterval_t svc_timeout) {
+ ts_state_t *tssp = NULL;
+ msg_t r;
+
+ /* Internal query service.*/
+ if (svc_handle == TS_HND_STQRY) {
+ ts_state_t *tsqryd;
+
+ /* svc_data is the handle of the service to whom 'query' the state.*/
+ tsqryd = (ts_state_t *)svc_data;
+
+ /* handle argument validation.*/
+ if (!isHndlValid(tsqryd))
+ return LOWORD(SMC_SVC_BADH);
+
+ /* if the service has done, return its last status.*/
+ if (tsqryd->ts_thdp != NULL) {
+ r = tsqryd->ts_status;
+ return LOWORD(r);
+ }
+ }
+ else if (svc_handle != TS_HND_IDLE) {
+ if (!isAddrSpaceValid(svc_data, svc_datalen))
+ return LOWORD(SMC_SVC_INVALID);
+
+ /* Internal discovery service.*/
+ if (svc_handle == TS_HND_DISCOVERY) {
+ if (svc_datalen) {
+ *((char *)svc_data + svc_datalen - 1) = '\0';
+ tssp = findSvcsEntry((char *)svc_data);
+ }
+ if (tssp == NULL)
+ return LOWORD(SMC_SVC_NOENT);
+ return LOWORD((int32_t)tssp);
+ } else {
+ if (!isHndlValid(svc_handle))
+ return LOWORD(SMC_SVC_BADH);
+ tssp = svc_handle;
+ }
+ if (tssp->ts_thdp == NULL)
+ return LOWORD(SMC_SVC_BUSY);
+ tssp->ts_datap = svc_data;
+ tssp->ts_datalen = svc_datalen;
+ }
+
+#if (CH_DBG_SYSTEM_STATE_CHECK == TRUE)
+ _dbg_check_lock();
+#endif
+
+ /* limit the max timeout interval.*/
+ if (svc_timeout > TS_MAX_TMO)
+ svc_timeout = TS_MAX_TMO;
+
+ if (tssp)
+ chThdResumeS(&tssp->ts_thdp, MSG_OK);
+ r = chThdSuspendTimeoutS(&_ns_thread, TIME_US2I(svc_timeout));
+
+ /* Get and clear any pending event flags.*/
+ eventflags_t f = chEvtGetAndClearFlagsI(&tsEventListener);
+
+#if (CH_DBG_SYSTEM_STATE_CHECK == TRUE)
+ _dbg_check_unlock();
+#endif
+ return LOWORD(r) | ((int64_t)f << 32);
+}
+
+/**
+ * @brief The calling thread is a service and wait the arrival of
+ * a request.
+ * @post The service object state is filled with the parameters of
+ * the requester.
+ *
+ * @param[in] svcp the service object reference.
+ *
+ * @return The wakeup message.
+ * @retval MSG_OK a new request has to be processed.
+ *
+ * @api
+ */
+msg_t tssiWaitRequest(ts_state_t *svcp)
+{
+ msg_t r;
+
+ chDbgCheck(svcp != NULL);
+
+ chSysLock();
+ if (_ns_thread) {
+ /* Ack a previous service invocation. Not schedule.*/
+ chThdResumeI(&_ns_thread, svcp->ts_status);
+ }
+ r = chThdSuspendS(&svcp->ts_thdp);
+ chSysUnlock();
+ return r;
+}
+
+/**
+ * @brief Initializes the trusted services and jumps in the NSEC world.
+ *
+ * @init
+ */
+CC_NO_RETURN void tssiInit(void)
+{
+ int32_t i;
+ uint32_t d;
+ uint32_t *tt;
+
+
+ /*
+ * The DDR memory is divided in 4 region, each 32MB large.
+ * The last region is split in two areas, each 16MB large.
+ * The first 3 region and the lower area of this last region is non secure.
+ * All the rest of the regions space is secured.
+ *
+ * Those settings depend on the designed memory mapping.
+ */
+ mtxSetSlaveRegionSize(MATRIX0, H64MX_SLAVE_DDR_PORT0, MATRIX_AREA_SIZE_32M, REGION_0_MSK);
+ mtxSetSlaveRegionSize(MATRIX0, H64MX_SLAVE_DDR_PORT1, MATRIX_AREA_SIZE_32M, REGION_0_MSK);
+
+ mtxSetSlaveSplitAddr(MATRIX0, H64MX_SLAVE_DDR_PORT0, MATRIX_AREA_SIZE_32M,
+ REGION_0_MSK | REGION_1_MSK | REGION_2_MSK);
+ mtxSetSlaveSplitAddr(MATRIX0, H64MX_SLAVE_DDR_PORT1, MATRIX_AREA_SIZE_32M,
+ REGION_0_MSK | REGION_1_MSK | REGION_2_MSK);
+
+ mtxSetSlaveSplitAddr(MATRIX0, H64MX_SLAVE_DDR_PORT0, MATRIX_AREA_SIZE_16M, REGION_3_MSK);
+ mtxSetSlaveSplitAddr(MATRIX0, H64MX_SLAVE_DDR_PORT1, MATRIX_AREA_SIZE_16M, REGION_3_MSK);
+
+ mtxConfigSlaveSec(MATRIX0, H64MX_SLAVE_DDR_PORT0,
+ mtxRegionLansech(REGION_0, UPPER_AREA_SECURABLE) |
+ mtxRegionLansech(REGION_1, UPPER_AREA_SECURABLE) |
+ mtxRegionLansech(REGION_2, UPPER_AREA_SECURABLE) |
+ mtxRegionLansech(REGION_3, UPPER_AREA_SECURABLE),
+ mtxRegionRdnsech(REGION_0, NOT_SECURE_READ) |
+ mtxRegionRdnsech(REGION_1, NOT_SECURE_READ) |
+ mtxRegionRdnsech(REGION_2, NOT_SECURE_READ),
+ mtxRegionWrnsech(REGION_0, NOT_SECURE_WRITE) |
+ mtxRegionWrnsech(REGION_1, NOT_SECURE_WRITE) |
+ mtxRegionWrnsech(REGION_2, NOT_SECURE_WRITE));
+
+ mtxConfigSlaveSec(MATRIX0, H64MX_SLAVE_DDR_PORT1,
+ mtxRegionLansech(REGION_0, UPPER_AREA_SECURABLE) |
+ mtxRegionLansech(REGION_1, UPPER_AREA_SECURABLE) |
+ mtxRegionLansech(REGION_2, UPPER_AREA_SECURABLE) |
+ mtxRegionLansech(REGION_3, UPPER_AREA_SECURABLE),
+ mtxRegionRdnsech(REGION_0, NOT_SECURE_READ) |
+ mtxRegionRdnsech(REGION_1, NOT_SECURE_READ) |
+ mtxRegionRdnsech(REGION_2, NOT_SECURE_READ),
+ mtxRegionWrnsech(REGION_0, NOT_SECURE_WRITE) |
+ mtxRegionWrnsech(REGION_1, NOT_SECURE_WRITE) |
+ mtxRegionWrnsech(REGION_2, NOT_SECURE_WRITE));
+
+ /* Mark the whole non secure memory region as non executable
+ by the secure code.*/
+ tt = (uint32_t *)(__get_TTBR0() & 0xFFFFC000);
+ for (d = ((uint32_t)NSEC_MEMORY_START_ADDR >> 20);
+ d < ((uint32_t)NSEC_MEMORY_END_ADDR >> 20); d += 1) {
+ MMU_XNSection(tt + d, NON_EXECUTE);
+ }
+
+ /* Make sure that prio is NORMALPRIO.*/
+ chThdSetPriority(NORMALPRIO);
+
+ /* Initialize the services.*/
+ for (i = 0; i < TS_MAX_SVCS; ++i) {
+ if (TS_CONF_TABLE(i)->arg == NULL)
+ continue;
+
+ /* Check that the initialization of the TS_TABLE against TS_STATE_TABLE
+ was set right.*/
+ if (TS_CONF_TABLE(i)->arg != TS_STATE(i)) {
+ chSysHalt("Bad TS_STATE setting in the services configuration table.");
+ }
+
+ /* Check that the service priority was set right.*/
+ if ((TS_CONF_TABLE(i)->prio <= NORMALPRIO) ||
+ (TS_CONF_TABLE(i)->prio >= HIGHPRIO)) {
+ chSysHalt("Bad prio setting in the services configuration table.");
+ }
+
+ /* Create the service thread.*/
+ chThdCreate(TS_CONF_TABLE(i));
+ }
+
+ /* Register to the daemon services events. All flags.*/
+ chEvtRegister(&tsEventSource, &tsEventListener, EVT_DAEMON_REQ_ATN);
+
+ /* Now set the priority to the max.*/
+ chThdSetPriority(HIGHPRIO);
+
+ /* Jump in the NON SECURE world.
+ * This thread becomes the non secure environment as view by
+ * the secure world.*/
+ _ns_trampoline(NSEC_MEMORY_START_ADDR);
+
+ /* It never goes here.*/
+}
+
+/** @} */
diff --git a/os/common/ports/ARMCAx-TZ/chtssi.h b/os/common/ports/ARMCAx-TZ/chtssi.h
new file mode 100644
index 000000000..3fbb1497b
--- /dev/null
+++ b/os/common/ports/ARMCAx-TZ/chtssi.h
@@ -0,0 +1,209 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file chtssi.h
+ * @brief tssi module macros and structures.
+ *
+ * @addtogroup TSSI
+ * @{
+ */
+
+#ifndef CHTSSI_H
+#define CHTSSI_H
+
+#include "ch.h"
+#include "ccportab.h"
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/* Service registry errors as returned by smc.*/
+#define SMC_SVC_OK MSG_OK /* No error.*/
+#define SMC_SVC_INTR (msg_t)-1 /* Service interrupted ( == MSG_TIMEOUT).*/
+#define SMC_SVC_NOENT (msg_t)-2 /* No existent service.*/
+#define SMC_SVC_INVALID (msg_t)-3 /* Invalid service parameter(s).*/
+#define SMC_SVC_BADH (msg_t)-4 /* Invalid service handle.*/
+#define SMC_SVC_EXIST (msg_t)-5 /* Service already exists.*/
+#define SMC_SVC_NHND (msg_t)-6 /* No more services.*/
+#define SMC_SVC_BUSY (msg_t)-7 /* Service busy.*/
+
+/* Special trusted service handles.*/
+#define TS_HND_TRAMP ((ts_state_t *)0) /* Trampoline service handle.*/
+#define TS_HND_DISCOVERY ((ts_state_t *)1) /* Discovery service handle.*/
+#define TS_HND_STQRY ((ts_state_t *)2) /* Query status service handle.*/
+#define TS_HND_IDLE ((ts_state_t *)3) /* Idle service handle.*/
+
+/* Service states.*/
+#define TS_STATE_READY 0
+#define TS_STATE_PROCESSING 1
+#define TS_STATE_DONE 2
+
+/* Services events event mask.*/
+#define EVT_DAEMON_REQ_ATN EVENT_MASK(0)
+
+/* Service events flags.*/
+#define EVT_DRA_SOCK_PROXY 1
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name TSSI module settings.
+ * @{
+ */
+
+/*
+ * @brief Max number of services.
+ */
+#define TS_MAX_SVCS 64
+
+/*
+ * @brief Max smc call timeout, in microseconds.
+ */
+#define TS_MAX_TMO 10000
+
+/*
+ * @brief Secure and non secure memory address spaces.
+ */
+#define NSEC_MEMORY_START_ADDR ((uint8_t *)0x20000000)
+#define NSEC_MEMORY_END_ADDR ((uint8_t *)0x27000000)
+#define SEC_MEMORY_START_ADDR ((uint8_t *)0x27000000)
+#define SEC_MEMORY_END_ADDR ((size_t)0x1000000)
+
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+typedef uint8_t * ts_params_area_t;
+
+typedef struct tssi_service_state {
+ uint32_t ts_status;
+ thread_reference_t ts_thdp;
+ ts_params_area_t ts_datap;
+ uint32_t ts_datalen;
+} ts_state_t;
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @name Services tables definition macros.
+ * @{
+ */
+
+/**
+ * @brief Table of the runtime state of the services.
+ */
+#define TS_STATE_TABLE \
+ ts_state_t ts_state[TS_MAX_SVCS] = {0};
+
+/**
+ * @brief Accessor to the runtime state of service i.
+ */
+#define TS_STATE(i) (&ts_state[i])
+
+/**
+ * @brief Start of user service table.
+ */
+#define TS_CONF_TABLE_BEGIN \
+ const thread_descriptor_t ts_configs[TS_MAX_SVCS] = {
+
+/**
+ * @brief Entry of user services table.
+ */
+#define TS_CONF_TABLE_ENTRY(name, wap, prio, funcp, tsstatep) \
+ {name, wap, ((stkalign_t *)(wap)) + (sizeof (wap) / sizeof(stkalign_t)), \
+ prio, funcp, tsstatep},
+
+/**
+ * @brief End of user services table.
+ */
+#define TS_CONF_TABLE_END \
+};
+
+/*
+ * @brief Accessor to the service table entry i.
+ */
+#define TS_CONF_TABLE(i) (&ts_configs[i])
+
+/*
+ * @brief Trusted services base prio.
+ */
+#define TS_BASE_PRIO (NORMALPRIO+1)
+
+/*
+ * @brief Check if service is busy.
+ */
+#define TS_IS_BUSY(state) (state != TS_STATE_READY)
+
+/*
+ * @brief Set the service status.
+ * @note The service sets the status at a value representing the status
+ * of the completion of the request. This value is
+ * service dependent.
+ */
+#define TS_SET_STATUS(svcp, newst) (((ts_state_t *)svcp)->ts_status = newst)
+
+/*
+ * @brief Get the client shared memory start address.
+ * @note The client sets the data field at the start address
+ * of a shared memory allocated from the non secure memory space.
+ */
+#define TS_GET_DATA(svcp) ((char *)((ts_state_t *)svcp)->ts_datap)
+
+/*
+ * @brief Get the client shared memory size.
+ * @note The client sets the datalen field to the size
+ * of a shared memory allocated from the non secure memory space.
+ */
+#define TS_GET_DATALEN(svcp) (((ts_state_t *)svcp)->ts_datalen)
+
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ extern event_source_t tsEventSource;
+ extern ts_state_t ts_state[];
+ extern const thread_descriptor_t ts_configs[];
+ extern thread_reference_t _ns_thread;
+ CC_NO_RETURN void _ns_trampoline(uint8_t *addr);
+ CC_NO_RETURN void tssiInit(void);
+ msg_t tssiWaitRequest(ts_state_t *svcp);
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+#endif /* CHTSSI_H */