/external/mbed-os/features/FEATURE_UVISOR/includes/uvisor/api/inc/rpc_gateway.h

https://github.com/adamgreen/gcc4mbed · C Header · 272 lines · 170 code · 36 blank · 66 comment · 0 complexity · 327d5f903494fa4389117ad2e5b94045 MD5 · raw file

  1. /*
  2. * Copyright (c) 2016, ARM Limited, All Rights Reserved
  3. * SPDX-License-Identifier: Apache-2.0
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License"); you may
  6. * not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  13. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. #ifndef __UVISOR_API_RPC_GATEWAY_H__
  18. #define __UVISOR_API_RPC_GATEWAY_H__
  19. #include "api/inc/rpc_gateway_exports.h"
  20. #include "api/inc/rpc.h"
  21. #include "api/inc/uvisor_exports.h"
  22. #include <stdint.h>
  23. /** Synchronous RPC Gateway
  24. *
  25. * This macro declares a new function pointer (with no name mangling) named
  26. * `gw_name` to perform a remote procedure call (RPC) to the target function
  27. * given by `fn_name`. RPCs are assembled into a read-only flash structure that
  28. * is read and validated by uVisor before performing the operation.
  29. *
  30. * Create function with following signature:
  31. * UVISOR_EXTERN fn_ret gw_name(uint32_t a, uint32_t b);
  32. *
  33. * @param box_name[in] The name of the source box as declared in
  34. * `UVISOR_BOX_CONFIG`
  35. * @param gw_name[in] The new, callable function pointer for initiating an RPC from the caller's box
  36. * @param fn_name[in] The function that will run in the callee's box as an RPC target
  37. * @param fn_ret[in] The return type of the function being designated as an
  38. * RPC target
  39. * @param __VA_ARGS__ The type of each parameter passed to the target
  40. * function. There can be up to 4 parameters in a target
  41. * function. Each parameter must be no more than uint32_t
  42. * in size. If the RPC target function accepts no
  43. * arguments, pass `void` here.
  44. */
  45. #define UVISOR_BOX_RPC_GATEWAY_SYNC(box_name, gw_name, fn_name, fn_ret, ...) \
  46. UVISOR_STATIC_ASSERT(sizeof(fn_ret) <= sizeof(uint32_t), gw_name ## _return_type_too_big); \
  47. _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK(gw_name, __VA_ARGS__) \
  48. _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_DECL(fn_name, gw_name ## _rpc_gateway, __VA_ARGS__) \
  49. /* Instanstiate the gateway. This gets resolved at link-time. */ \
  50. UVISOR_EXTERN TRPCGateway const gw_name ## _rpc_gateway = { \
  51. .ldr_pc = LDR_PC_PC_IMM_OPCODE(__UVISOR_OFFSETOF(TRPCGateway, ldr_pc), \
  52. __UVISOR_OFFSETOF(TRPCGateway, caller)), \
  53. .magic = UVISOR_RPC_GATEWAY_MAGIC_SYNC, \
  54. .box_ptr = (uint32_t) &box_name ## _cfg_ptr, \
  55. .target = (uint32_t) fn_name, \
  56. .caller = (uint32_t) _sgw_sync_ ## fn_name, \
  57. }; \
  58. _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER(fn_name, gw_name ## _rpc_gateway, __VA_ARGS__) \
  59. \
  60. /* Pointer to the gateway we just created. The pointer is located in a
  61. * discoverable linker section. */ \
  62. __attribute__((section(".keep.uvisor.rpc_gateway_ptr"))) \
  63. uint32_t const gw_name ## _rpc_gateway_ptr = (uint32_t) &gw_name ## _rpc_gateway; \
  64. \
  65. /* Declare the actual gateway. */ \
  66. UVISOR_EXTERN_C_BEGIN \
  67. fn_ret (*gw_name)(__VA_ARGS__) __attribute__((section(".rodata"))) = (fn_ret (*)(__VA_ARGS__)) ((uint32_t) &gw_name ## _rpc_gateway + 1); \
  68. UVISOR_EXTERN_C_END
  69. /** Asynchronous RPC Gateway
  70. *
  71. * This macro declares a new function pointer (with no name mangling) named
  72. * `gw_name` to perform a remote procedure call (RPC) to the target function
  73. * given by `fn_name`. RPCs are assembled into a read-only flash structure that
  74. * is read and validated by uVisor before performing the operation.
  75. *
  76. * Create function with following signature:
  77. * UVISOR_EXTERN uvisor_rpc_result_t gw_name(uint32_t a, uint32_t b);
  78. *
  79. * @param box_name[in] The name of the source box as declared in
  80. * `UVISOR_BOX_CONFIG`
  81. * @param gw_name[in] The new, callable function pointer for initiating an RPC from the caller's box
  82. * @param fn_name[in] The function that will run in the callee's box as an RPC target
  83. * @param fn_ret[in] The return type of the function being designated as an
  84. * RPC target
  85. * @param __VA_ARGS__ The type of each parameter passed to the target
  86. * function. There can be up to 4 parameters in a target
  87. * function. Each parameter must be no more than uint32_t
  88. * in size. If the RPC target function accepts no
  89. * arguments, pass `void` here.
  90. */
  91. #define UVISOR_BOX_RPC_GATEWAY_ASYNC(box_name, gw_name, fn_name, fn_ret, ...) \
  92. UVISOR_STATIC_ASSERT(sizeof(fn_ret) <= sizeof(uint32_t), gw_name ## _return_type_too_big); \
  93. _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK(gw_name, __VA_ARGS__) \
  94. _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_DECL(fn_name, gw_name ## _rpc_gateway, __VA_ARGS__) \
  95. /* Instanstiate the gateway. This gets resolved at link-time. */ \
  96. UVISOR_EXTERN TRPCGateway const gw_name ## _rpc_gateway = { \
  97. .ldr_pc = LDR_PC_PC_IMM_OPCODE(__UVISOR_OFFSETOF(TRPCGateway, ldr_pc), \
  98. __UVISOR_OFFSETOF(TRPCGateway, caller)), \
  99. .magic = UVISOR_RPC_GATEWAY_MAGIC_ASYNC, \
  100. .box_ptr = (uint32_t) &box_name ## _cfg_ptr, \
  101. .target = (uint32_t) fn_name, \
  102. .caller = (uint32_t) _sgw_async_ ## fn_name, \
  103. }; \
  104. _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER(fn_name, gw_name ## _rpc_gateway, __VA_ARGS__) \
  105. \
  106. /* Pointer to the gateway we just created. The pointer is located in a
  107. * discoverable linker section. */ \
  108. __attribute__((section(".keep.uvisor.rpc_gateway_ptr"))) \
  109. uint32_t const gw_name ## _rpc_gateway_ptr = (uint32_t) &gw_name ## _rpc_gateway; \
  110. \
  111. /* Declare the actual gateway. */ \
  112. UVISOR_EXTERN_C_BEGIN \
  113. uvisor_rpc_result_t (*gw_name)(__VA_ARGS__) __attribute__((section(".rodata"))) = (uvisor_rpc_result_t (*)(__VA_ARGS__)) ((uint32_t) &gw_name ## _rpc_gateway + 1); \
  114. UVISOR_EXTERN_C_END
  115. #define _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK(gw_name, ...) \
  116. __UVISOR_BOX_MACRO(__VA_ARGS__, _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_4, \
  117. _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_3, \
  118. _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_2, \
  119. _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_1, \
  120. _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_0)(gw_name, __VA_ARGS__)
  121. #define _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_0(gw_name)
  122. #define _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_1(gw_name, p0_type) \
  123. UVISOR_STATIC_ASSERT(sizeof(p0_type) <= sizeof(uint32_t), gw_name ## _param_0_too_big);
  124. #define _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_2(gw_name, p0_type, p1_type) \
  125. UVISOR_STATIC_ASSERT(sizeof(p0_type) <= sizeof(uint32_t), gw_name ## _param_0_too_big); \
  126. UVISOR_STATIC_ASSERT(sizeof(p1_type) <= sizeof(uint32_t), gw_name ## _param_1_too_big);
  127. #define _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_3(gw_name, p0_type, p1_type, p2_type) \
  128. UVISOR_STATIC_ASSERT(sizeof(p0_type) <= sizeof(uint32_t), gw_name ## _param_0_too_big); \
  129. UVISOR_STATIC_ASSERT(sizeof(p1_type) <= sizeof(uint32_t), gw_name ## _param_1_too_big); \
  130. UVISOR_STATIC_ASSERT(sizeof(p2_type) <= sizeof(uint32_t), gw_name ## _param_2_too_big);
  131. #define _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_4(gw_name, p0_type, p1_type, p2_type, p3_type) \
  132. UVISOR_STATIC_ASSERT(sizeof(p0_type) <= sizeof(uint32_t), gw_name ## _param_0_too_big); \
  133. UVISOR_STATIC_ASSERT(sizeof(p1_type) <= sizeof(uint32_t), gw_name ## _param_1_too_big); \
  134. UVISOR_STATIC_ASSERT(sizeof(p2_type) <= sizeof(uint32_t), gw_name ## _param_2_too_big); \
  135. UVISOR_STATIC_ASSERT(sizeof(p3_type) <= sizeof(uint32_t), gw_name ## _param_3_too_big);
  136. #define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_DECL(fn_name, gateway, ...) \
  137. __UVISOR_BOX_MACRO(__VA_ARGS__, _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_4_DECL, \
  138. _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_3_DECL, \
  139. _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_2_DECL, \
  140. _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_1_DECL, \
  141. _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_0_DECL)(fn_name, gateway, __VA_ARGS__)
  142. #define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER(fn_name, gateway, ...) \
  143. __UVISOR_BOX_MACRO(__VA_ARGS__, _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_4, \
  144. _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_3, \
  145. _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_2, \
  146. _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_1, \
  147. _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_0)(fn_name, gateway, __VA_ARGS__)
  148. #define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_0_DECL(fn_name, gateway, ...) \
  149. static uint32_t _sgw_sync_ ## fn_name(void);
  150. #define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_0(fn_name, gateway, ...) \
  151. static uint32_t _sgw_sync_ ## fn_name(void) \
  152. { \
  153. return rpc_fncall_sync(0, 0, 0, 0, &gateway); \
  154. }
  155. #define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_1_DECL(fn_name, gateway, ...) \
  156. static uint32_t _sgw_sync_ ## fn_name(uint32_t p0);
  157. #define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_1(fn_name, gateway, ...) \
  158. static uint32_t _sgw_sync_ ## fn_name(uint32_t p0) \
  159. { \
  160. return rpc_fncall_sync(p0, 0, 0, 0, &gateway); \
  161. }
  162. #define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_2_DECL(fn_name, gateway, ...) \
  163. static uint32_t _sgw_sync_ ## fn_name(uint32_t p0, uint32_t p1);
  164. #define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_2(fn_name, gateway, ...) \
  165. static uint32_t _sgw_sync_ ## fn_name(uint32_t p0, uint32_t p1) \
  166. { \
  167. return rpc_fncall_sync(p0, p1, 0, 0, &gateway); \
  168. }
  169. #define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_3_DECL(fn_name, gateway, ...) \
  170. static uint32_t _sgw_sync_ ## fn_name(uint32_t p0, uint32_t p1, uint32_t p2);
  171. #define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_3(fn_name, gateway, ...) \
  172. static uint32_t _sgw_sync_ ## fn_name(uint32_t p0, uint32_t p1, uint32_t p2) \
  173. { \
  174. return rpc_fncall_sync(p0, p1, p2, 0, &gateway); \
  175. }
  176. #define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_4_DECL(fn_name, gateway, ...) \
  177. static uint32_t _sgw_sync_ ## fn_name(uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3);
  178. #define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_4(fn_name, gateway, ...) \
  179. static uint32_t _sgw_sync_ ## fn_name(uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3) \
  180. { \
  181. return rpc_fncall_sync(p0, p1, p2, p3, &gateway); \
  182. }
  183. #define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_DECL(fn_name, gateway, ...) \
  184. __UVISOR_BOX_MACRO(__VA_ARGS__, _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_4_DECL, \
  185. _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_3_DECL, \
  186. _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_2_DECL, \
  187. _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_1_DECL, \
  188. _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_0_DECL)(fn_name, gateway, __VA_ARGS__)
  189. #define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER(fn_name, gateway, ...) \
  190. __UVISOR_BOX_MACRO(__VA_ARGS__, _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_4, \
  191. _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_3, \
  192. _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_2, \
  193. _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_1, \
  194. _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_0)(fn_name, gateway, __VA_ARGS__)
  195. #define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_0_DECL(fn_name, gateway, ...) \
  196. static uvisor_rpc_result_t _sgw_async_ ## fn_name(void);
  197. #define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_0(fn_name, gateway, ...) \
  198. static uvisor_rpc_result_t _sgw_async_ ## fn_name(void) \
  199. { \
  200. return rpc_fncall_async(0, 0, 0, 0, &gateway); \
  201. }
  202. #define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_1_DECL(fn_name, gateway, ...) \
  203. static uvisor_rpc_result_t _sgw_async_ ## fn_name(uint32_t p0);
  204. #define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_1(fn_name, gateway, ...) \
  205. static uvisor_rpc_result_t _sgw_async_ ## fn_name(uint32_t p0) \
  206. { \
  207. return rpc_fncall_async(p0, 0, 0, 0, &gateway); \
  208. }
  209. #define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_2_DECL(fn_name, gateway, ...) \
  210. static uvisor_rpc_result_t _sgw_async_ ## fn_name(uint32_t p0, uint32_t p1);
  211. #define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_2(fn_name, gateway, ...) \
  212. static uvisor_rpc_result_t _sgw_async_ ## fn_name(uint32_t p0, uint32_t p1) \
  213. { \
  214. return rpc_fncall_async(p0, p1, 0, 0, &gateway); \
  215. }
  216. #define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_3_DECL(fn_name, gateway, ...) \
  217. static uvisor_rpc_result_t _sgw_async_ ## fn_name(uint32_t p0, uint32_t p1, uint32_t p2);
  218. #define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_3(fn_name, gateway, ...) \
  219. static uvisor_rpc_result_t _sgw_async_ ## fn_name(uint32_t p0, uint32_t p1, uint32_t p2) \
  220. { \
  221. return rpc_fncall_async(p0, p1, p2, 0, &gateway); \
  222. }
  223. #define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_4_DECL(fn_name, gateway, ...) \
  224. static uvisor_rpc_result_t _sgw_async_ ## fn_name(uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3);
  225. #define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_4(fn_name, gateway, ...) \
  226. static uvisor_rpc_result_t _sgw_async_ ## fn_name(uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3) \
  227. { \
  228. return rpc_fncall_async(p0, p1, p2, p3, &gateway); \
  229. }
  230. /* This function is private to uvisor-lib, but needs to be publicly visible for
  231. * the RPC gateway creation macros to work. */
  232. UVISOR_EXTERN uint32_t rpc_fncall_sync(uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3, const TRPCGateway * gateway);
  233. /* This function is private to uvisor-lib, but needs to be publicly visible for
  234. * the RPC gateway creation macros to work. */
  235. UVISOR_EXTERN uvisor_rpc_result_t rpc_fncall_async(uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3, const TRPCGateway * gateway);
  236. #endif /* __UVISOR_API_RPC_GATEWAY_H__ */