blob: 5ec66388661b6e35584aa317069e81bf94fde6e9 [file] [log] [blame]
Ashutosh Singhf4d88672017-11-29 13:35:43 +00001/*
Antonio de Angelisd9cd66e2018-03-27 11:19:59 +01002 * Copyright (c) 2017-2018, Arm Limited. All rights reserved.
Ashutosh Singhf4d88672017-11-29 13:35:43 +00003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7#include <stdint.h>
8#include <stdbool.h>
9
10#include "cmsis.h"
11#include "cmsis_os2.h"
12
13#include "tfm_api.h"
14#include "tfm_ns_svc.h"
15
16/**
17 * \brief struct ns_lock_state type
18 */
19struct ns_lock_state
20{
21 bool init;
22 osMutexId_t id;
23};
24
25/**
26 * \brief ns_lock status
27 */
28static struct ns_lock_state ns_lock = {.init=false, .id=NULL};
29
30/**
31 * \brief Mutex properties, NS lock
32 */
33static const osMutexAttr_t ns_lock_attrib = {
34 .name = "ns_lock",
35 .attr_bits = osMutexPrioInherit
36};
37
38/**
Antonio de Angelisd9cd66e2018-03-27 11:19:59 +010039 * \def TFM_SVC_DISPATCH_NAME
Ashutosh Singhf4d88672017-11-29 13:35:43 +000040 *
Antonio de Angelisd9cd66e2018-03-27 11:19:59 +010041 * \brief Macro to declare a SVC dispatch function name
Ashutosh Singhf4d88672017-11-29 13:35:43 +000042 */
Antonio de Angelisd9cd66e2018-03-27 11:19:59 +010043#define TFM_SVC_DISPATCH_NAME(SVC_ENUM) tfm_svc_dispatch_##SVC_ENUM
44
45/**
46 * \def TFM_SVC_DISPATCH_FUNCTION
47 *
48 * \brief Macro to declare a SVC dispatch naked function body (4 bytes each)
49 */
50#define TFM_SVC_DISPATCH_FUNCTION(SVC_ENUM) \
51 __attribute__((naked)) \
52 static uint32_t TFM_SVC_DISPATCH_NAME(SVC_ENUM)(uint32_t arg0, \
53 uint32_t arg1, \
54 uint32_t arg2, \
55 uint32_t arg3) \
56 { \
57 SVC(SVC_ENUM); \
58 __ASM("BX LR"); \
59 }
Ashutosh Singhf4d88672017-11-29 13:35:43 +000060
61/**
62 * \brief Naked functions associated to each
Antonio de Angelisd9cd66e2018-03-27 11:19:59 +010063 * SVC in the list of X macros
64 * \ref LIST_SVC_DISPATCHERS
Ashutosh Singhf4d88672017-11-29 13:35:43 +000065 */
Antonio de Angelisd9cd66e2018-03-27 11:19:59 +010066#define X(SVC_ENUM, SVC_HANDLER) TFM_SVC_DISPATCH_FUNCTION(SVC_ENUM);
67LIST_SVC_DISPATCHERS
68#undef X
Ashutosh Singhf4d88672017-11-29 13:35:43 +000069
70/**
71 * \brief Array with function pointers to the
72 * naked functions. Entry 0 is treated
Antonio de Angelisd9cd66e2018-03-27 11:19:59 +010073 * as invalid. The other entries are
74 * taken automatically from the list of
75 * X macros \ref LIST_SVC_DISPATCHERS
Ashutosh Singhf4d88672017-11-29 13:35:43 +000076 */
Antonio de Angelisd9cd66e2018-03-27 11:19:59 +010077static void *tfm_svc_dispatch_functions[] = {
Ashutosh Singhf4d88672017-11-29 13:35:43 +000078 (void *) NULL, /* SVC_INVALID */
Antonio de Angelisd9cd66e2018-03-27 11:19:59 +010079#define X(SVC_ENUM, SVC_HANDLER) (void *)TFM_SVC_DISPATCH_NAME(SVC_ENUM),
80 LIST_SVC_DISPATCHERS
81#undef X
Ashutosh Singhf4d88672017-11-29 13:35:43 +000082};
83
84/**
85 * \brief NS world, NS lock based dispatcher
86 */
87uint32_t tfm_ns_lock_svc_dispatch(enum tfm_svc_num svc_num,
88 uint32_t arg0,
89 uint32_t arg1,
90 uint32_t arg2,
91 uint32_t arg3)
92{
93 uint32_t result;
94 uint32_t (*tfm_svc_dispatch_function_p)(uint32_t, uint32_t,
Antonio de Angelisd9cd66e2018-03-27 11:19:59 +010095 uint32_t, uint32_t);
96
97 const uint32_t num_svc_dispatchers =
98 sizeof(tfm_svc_dispatch_functions)/sizeof(tfm_svc_dispatch_functions[0]);
Ashutosh Singhf4d88672017-11-29 13:35:43 +000099
100 /* Check the NS lock has been initialized */
101 if (ns_lock.init == false) {
102 return TFM_ERROR_GENERIC;
103 }
104
105 /* Validate the SVC number requested */
Antonio de Angelisd9cd66e2018-03-27 11:19:59 +0100106 if ((svc_num > SVC_INVALID) && (svc_num < num_svc_dispatchers)) {
Ashutosh Singhf4d88672017-11-29 13:35:43 +0000107 tfm_svc_dispatch_function_p = tfm_svc_dispatch_functions[svc_num];
108
109 /* TFM request protected by NS lock */
110 osMutexAcquire(ns_lock.id,osWaitForever);
111 result = (*tfm_svc_dispatch_function_p)(arg0, arg1, arg2, arg3);
112 osMutexRelease(ns_lock.id);
113
114 return result;
115 }
116 else {
117 return TFM_ERROR_GENERIC;
118 }
119}
120
121/**
122 * \brief NS world, Init NS lock
123 */
124uint32_t tfm_ns_lock_init()
125{
126 if (ns_lock.init == false) {
127 ns_lock.id = osMutexNew(&ns_lock_attrib);
128 ns_lock.init = true;
129 return TFM_SUCCESS;
130 }
131 else {
132 return TFM_ERROR_GENERIC;
133 }
134}