Rtos API example

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers rpc_gateway.h Source File

rpc_gateway.h

00001 /*
00002  * Copyright (c) 2016, ARM Limited, All Rights Reserved
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License"); you may
00006  * not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  * http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00013  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 #ifndef __UVISOR_API_RPC_GATEWAY_H__
00018 #define __UVISOR_API_RPC_GATEWAY_H__
00019 
00020 #include "api/inc/rpc_gateway_exports.h"
00021 #include "api/inc/rpc.h"
00022 #include "api/inc/uvisor_exports.h"
00023 #include <stdint.h>
00024 
00025 /** Synchronous RPC Gateway
00026  *
00027  * This macro declares a new function pointer (with no name mangling) named
00028  * `gw_name` to perform a remote procedure call (RPC) to the target function
00029  * given by `fn_name`. RPCs are assembled into a read-only flash structure that
00030  * is read and validated by uVisor before performing the operation.
00031  *
00032  * Create function with following signature:
00033  * UVISOR_EXTERN fn_ret gw_name(uint32_t a, uint32_t b);
00034  *
00035  * @param box_name[in] The name of the source box as declared in
00036  *                     `UVISOR_BOX_CONFIG`
00037  * @param gw_name[in]  The new, callable function pointer for initiating an RPC from the caller's box
00038  * @param fn_name[in]  The function that will run in the callee's box as an RPC target
00039  * @param fn_ret[in]   The return type of the function being designated as an
00040  *                     RPC target
00041  * @param __VA_ARGS__  The type of each parameter passed to the target
00042  *                     function. There can be up to 4 parameters in a target
00043  *                     function. Each parameter must be no more than uint32_t
00044  *                     in size. If the RPC target function accepts no
00045  *                     arguments, pass `void` here.
00046  */
00047 #define UVISOR_BOX_RPC_GATEWAY_SYNC(box_name, gw_name, fn_name, fn_ret, ...) \
00048     UVISOR_STATIC_ASSERT(sizeof(fn_ret) <= sizeof(uint32_t), gw_name ## _return_type_too_big); \
00049     _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK(gw_name, __VA_ARGS__) \
00050     _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_DECL(fn_name, gw_name ## _rpc_gateway, __VA_ARGS__) \
00051     /* Instanstiate the gateway. This gets resolved at link-time. */ \
00052     UVISOR_EXTERN TRPCGateway const gw_name ## _rpc_gateway = { \
00053         .ldr_pc   = LDR_PC_PC_IMM_OPCODE(__UVISOR_OFFSETOF(TRPCGateway, ldr_pc), \
00054                                          __UVISOR_OFFSETOF(TRPCGateway, caller)), \
00055         .magic    = UVISOR_RPC_GATEWAY_MAGIC_SYNC, \
00056         .box_ptr  = (uint32_t) &box_name ## _cfg_ptr, \
00057         .target = (uint32_t) fn_name, \
00058         .caller = (uint32_t) _sgw_sync_ ## fn_name, \
00059     }; \
00060     _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER(fn_name, gw_name ## _rpc_gateway, __VA_ARGS__) \
00061     \
00062     /* Pointer to the gateway we just created. The pointer is located in a
00063      * discoverable linker section. */ \
00064     __attribute__((section(".keep.uvisor.rpc_gateway_ptr"))) \
00065     uint32_t const gw_name ## _rpc_gateway_ptr = (uint32_t) &gw_name ## _rpc_gateway; \
00066     \
00067     /* Declare the actual gateway. */ \
00068     UVISOR_EXTERN_C_BEGIN \
00069         fn_ret (*gw_name)(__VA_ARGS__) __attribute__((section(".rodata"))) = (fn_ret (*)(__VA_ARGS__)) ((uint32_t) &gw_name ## _rpc_gateway + 1); \
00070     UVISOR_EXTERN_C_END
00071 
00072 /** Asynchronous RPC Gateway
00073  *
00074  * This macro declares a new function pointer (with no name mangling) named
00075  * `gw_name` to perform a remote procedure call (RPC) to the target function
00076  * given by `fn_name`. RPCs are assembled into a read-only flash structure that
00077  * is read and validated by uVisor before performing the operation.
00078  *
00079  * Create function with following signature:
00080  * UVISOR_EXTERN uvisor_rpc_result_t gw_name(uint32_t a, uint32_t b);
00081  *
00082  * @param box_name[in] The name of the source box as declared in
00083  *                     `UVISOR_BOX_CONFIG`
00084  * @param gw_name[in]  The new, callable function pointer for initiating an RPC from the caller's box
00085  * @param fn_name[in]  The function that will run in the callee's box as an RPC target
00086  * @param fn_ret[in]   The return type of the function being designated as an
00087  *                     RPC target
00088  * @param __VA_ARGS__  The type of each parameter passed to the target
00089  *                     function. There can be up to 4 parameters in a target
00090  *                     function. Each parameter must be no more than uint32_t
00091  *                     in size. If the RPC target function accepts no
00092  *                     arguments, pass `void` here.
00093  */
00094 #define UVISOR_BOX_RPC_GATEWAY_ASYNC(box_name, gw_name, fn_name, fn_ret, ...) \
00095     UVISOR_STATIC_ASSERT(sizeof(fn_ret) <= sizeof(uint32_t), gw_name ## _return_type_too_big); \
00096     _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK(gw_name, __VA_ARGS__) \
00097     _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_DECL(fn_name, gw_name ## _rpc_gateway, __VA_ARGS__) \
00098     /* Instanstiate the gateway. This gets resolved at link-time. */ \
00099     UVISOR_EXTERN TRPCGateway const gw_name ## _rpc_gateway = { \
00100         .ldr_pc   = LDR_PC_PC_IMM_OPCODE(__UVISOR_OFFSETOF(TRPCGateway, ldr_pc), \
00101                                          __UVISOR_OFFSETOF(TRPCGateway, caller)), \
00102         .magic    = UVISOR_RPC_GATEWAY_MAGIC_ASYNC, \
00103         .box_ptr  = (uint32_t) &box_name ## _cfg_ptr, \
00104         .target = (uint32_t) fn_name, \
00105         .caller = (uint32_t) _sgw_async_ ## fn_name, \
00106     }; \
00107     _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER(fn_name, gw_name ## _rpc_gateway, __VA_ARGS__) \
00108     \
00109     /* Pointer to the gateway we just created. The pointer is located in a
00110      * discoverable linker section. */ \
00111     __attribute__((section(".keep.uvisor.rpc_gateway_ptr"))) \
00112     uint32_t const gw_name ## _rpc_gateway_ptr = (uint32_t) &gw_name ## _rpc_gateway; \
00113     \
00114     /* Declare the actual gateway. */ \
00115     UVISOR_EXTERN_C_BEGIN \
00116         uvisor_rpc_result_t (*gw_name)(__VA_ARGS__) __attribute__((section(".rodata"))) = (uvisor_rpc_result_t (*)(__VA_ARGS__)) ((uint32_t) &gw_name ## _rpc_gateway + 1); \
00117     UVISOR_EXTERN_C_END
00118 
00119 #define _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK(gw_name, ...) \
00120     __UVISOR_BOX_MACRO(__VA_ARGS__, _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_4, \
00121                                     _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_3, \
00122                                     _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_2, \
00123                                     _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_1, \
00124                                     _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_0)(gw_name, __VA_ARGS__)
00125 
00126 #define _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_0(gw_name)
00127 
00128 #define _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_1(gw_name, p0_type) \
00129     UVISOR_STATIC_ASSERT(sizeof(p0_type) <= sizeof(uint32_t), gw_name ## _param_0_too_big);
00130 
00131 #define _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_2(gw_name, p0_type, p1_type) \
00132     UVISOR_STATIC_ASSERT(sizeof(p0_type) <= sizeof(uint32_t), gw_name ## _param_0_too_big); \
00133     UVISOR_STATIC_ASSERT(sizeof(p1_type) <= sizeof(uint32_t), gw_name ## _param_1_too_big);
00134 
00135 #define _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_3(gw_name, p0_type, p1_type, p2_type) \
00136     UVISOR_STATIC_ASSERT(sizeof(p0_type) <= sizeof(uint32_t), gw_name ## _param_0_too_big); \
00137     UVISOR_STATIC_ASSERT(sizeof(p1_type) <= sizeof(uint32_t), gw_name ## _param_1_too_big); \
00138     UVISOR_STATIC_ASSERT(sizeof(p2_type) <= sizeof(uint32_t), gw_name ## _param_2_too_big);
00139 
00140 #define _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_4(gw_name, p0_type, p1_type, p2_type, p3_type) \
00141     UVISOR_STATIC_ASSERT(sizeof(p0_type) <= sizeof(uint32_t), gw_name ## _param_0_too_big); \
00142     UVISOR_STATIC_ASSERT(sizeof(p1_type) <= sizeof(uint32_t), gw_name ## _param_1_too_big); \
00143     UVISOR_STATIC_ASSERT(sizeof(p2_type) <= sizeof(uint32_t), gw_name ## _param_2_too_big); \
00144     UVISOR_STATIC_ASSERT(sizeof(p3_type) <= sizeof(uint32_t), gw_name ## _param_3_too_big);
00145 
00146 #define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_DECL(fn_name, gateway, ...) \
00147     __UVISOR_BOX_MACRO(__VA_ARGS__, _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_4_DECL, \
00148                                     _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_3_DECL, \
00149                                     _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_2_DECL, \
00150                                     _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_1_DECL, \
00151                                     _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_0_DECL)(fn_name, gateway, __VA_ARGS__)
00152 
00153 #define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER(fn_name, gateway, ...) \
00154     __UVISOR_BOX_MACRO(__VA_ARGS__, _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_4, \
00155                                     _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_3, \
00156                                     _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_2, \
00157                                     _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_1, \
00158                                     _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_0)(fn_name, gateway, __VA_ARGS__)
00159 
00160 #define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_0_DECL(fn_name, gateway, ...) \
00161     static uint32_t _sgw_sync_ ## fn_name(void);
00162 
00163 #define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_0(fn_name, gateway, ...) \
00164     static uint32_t _sgw_sync_ ## fn_name(void) \
00165     { \
00166         return rpc_fncall_sync(0, 0, 0, 0, &gateway); \
00167     }
00168 
00169 #define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_1_DECL(fn_name, gateway, ...) \
00170     static uint32_t _sgw_sync_ ## fn_name(uint32_t p0);
00171 
00172 #define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_1(fn_name, gateway, ...) \
00173     static uint32_t _sgw_sync_ ## fn_name(uint32_t p0) \
00174     { \
00175         return rpc_fncall_sync(p0, 0, 0, 0, &gateway); \
00176     }
00177 
00178 #define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_2_DECL(fn_name, gateway, ...) \
00179     static uint32_t _sgw_sync_ ## fn_name(uint32_t p0, uint32_t p1);
00180 
00181 #define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_2(fn_name, gateway, ...) \
00182     static uint32_t _sgw_sync_ ## fn_name(uint32_t p0, uint32_t p1) \
00183     { \
00184         return rpc_fncall_sync(p0, p1, 0, 0, &gateway); \
00185     }
00186 
00187 #define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_3_DECL(fn_name, gateway, ...) \
00188     static uint32_t _sgw_sync_ ## fn_name(uint32_t p0, uint32_t p1, uint32_t p2);
00189 
00190 #define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_3(fn_name, gateway, ...) \
00191     static uint32_t _sgw_sync_ ## fn_name(uint32_t p0, uint32_t p1, uint32_t p2) \
00192     { \
00193         return rpc_fncall_sync(p0, p1, p2, 0, &gateway); \
00194     }
00195 
00196 #define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_4_DECL(fn_name, gateway, ...) \
00197     static uint32_t _sgw_sync_ ## fn_name(uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3);
00198 
00199 #define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_4(fn_name, gateway, ...) \
00200     static uint32_t _sgw_sync_ ## fn_name(uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3) \
00201     { \
00202         return rpc_fncall_sync(p0, p1, p2, p3, &gateway); \
00203     }
00204 
00205 #define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_DECL(fn_name, gateway, ...) \
00206     __UVISOR_BOX_MACRO(__VA_ARGS__, _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_4_DECL, \
00207                                     _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_3_DECL, \
00208                                     _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_2_DECL, \
00209                                     _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_1_DECL, \
00210                                     _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_0_DECL)(fn_name, gateway, __VA_ARGS__)
00211 
00212 #define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER(fn_name, gateway, ...) \
00213     __UVISOR_BOX_MACRO(__VA_ARGS__, _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_4, \
00214                                     _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_3, \
00215                                     _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_2, \
00216                                     _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_1, \
00217                                     _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_0)(fn_name, gateway, __VA_ARGS__)
00218 
00219 #define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_0_DECL(fn_name, gateway, ...) \
00220     static uvisor_rpc_result_t _sgw_async_ ## fn_name(void);
00221 
00222 #define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_0(fn_name, gateway, ...) \
00223     static uvisor_rpc_result_t _sgw_async_ ## fn_name(void) \
00224     { \
00225         return rpc_fncall_async(0, 0, 0, 0, &gateway); \
00226     }
00227 
00228 #define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_1_DECL(fn_name, gateway, ...) \
00229     static uvisor_rpc_result_t _sgw_async_ ## fn_name(uint32_t p0);
00230 
00231 #define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_1(fn_name, gateway, ...) \
00232     static uvisor_rpc_result_t _sgw_async_ ## fn_name(uint32_t p0) \
00233     { \
00234         return rpc_fncall_async(p0, 0, 0, 0, &gateway); \
00235     }
00236 
00237 #define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_2_DECL(fn_name, gateway, ...) \
00238     static uvisor_rpc_result_t _sgw_async_ ## fn_name(uint32_t p0, uint32_t p1);
00239 
00240 #define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_2(fn_name, gateway, ...) \
00241     static uvisor_rpc_result_t _sgw_async_ ## fn_name(uint32_t p0, uint32_t p1) \
00242     { \
00243         return rpc_fncall_async(p0, p1, 0, 0, &gateway); \
00244     }
00245 
00246 #define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_3_DECL(fn_name, gateway, ...) \
00247     static uvisor_rpc_result_t _sgw_async_ ## fn_name(uint32_t p0, uint32_t p1, uint32_t p2);
00248 
00249 #define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_3(fn_name, gateway, ...) \
00250     static uvisor_rpc_result_t _sgw_async_ ## fn_name(uint32_t p0, uint32_t p1, uint32_t p2) \
00251     { \
00252         return rpc_fncall_async(p0, p1, p2, 0, &gateway); \
00253     }
00254 
00255 #define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_4_DECL(fn_name, gateway, ...) \
00256     static uvisor_rpc_result_t _sgw_async_ ## fn_name(uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3);
00257 
00258 #define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_4(fn_name, gateway, ...) \
00259     static uvisor_rpc_result_t _sgw_async_ ## fn_name(uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3) \
00260     { \
00261         return rpc_fncall_async(p0, p1, p2, p3, &gateway); \
00262     }
00263 
00264 /* This function is private to uvisor-lib, but needs to be publicly visible for
00265  * the RPC gateway creation macros to work. */
00266 UVISOR_EXTERN uint32_t rpc_fncall_sync(uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3, const TRPCGateway * gateway);
00267 
00268 /* This function is private to uvisor-lib, but needs to be publicly visible for
00269  * the RPC gateway creation macros to work. */
00270 UVISOR_EXTERN uvisor_rpc_result_t rpc_fncall_async(uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3, const TRPCGateway * gateway);
00271 
00272 #endif /* __UVISOR_API_RPC_GATEWAY_H__ */