joey shelton / LED_Demo

Dependencies:   MAX44000 PWM_Tone_Library nexpaq_mdk

Fork of LED_Demo by Maxim nexpaq

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 /* ldr pc, [pc, #<label - instr + 4>]
00026  * LDR (immediate) - ARMv7M ARM section A7.7.42
00027  * 1111;1 00 0; 0 10 1; <Rn - 1111>; <Rt - 1111>; <imm12> (Encoding T3) */
00028 #define LDR_PC_PC_IMM_OPCODE(instr, label) \
00029     ((uint32_t) (0xF000F8DFUL | ((((uint32_t) (label) - ((uint32_t) (instr) + 4)) & 0xFFFUL) << 16)))
00030 
00031 /** Synchronous RPC Gateway
00032  *
00033  * This macro declares a new function pointer (with no name mangling) named
00034  * `gw_name` to perform a remote procedure call (RPC) to the target function
00035  * given by `fn_name`. RPCs are assembled into a read-only flash structure that
00036  * is read and validated by uVisor before performing the operation.
00037  *
00038  * Create function with following signature:
00039  * UVISOR_EXTERN fn_ret gw_name(uint32_t a, uint32_t b);
00040  *
00041  * @param box_name[in] The name of the source box as declared in
00042  *                     `UVISOR_BOX_CONFIG`
00043  * @param gw_name[in]  The new, callable function pointer for performing RPC
00044  * @param fn_name[in]  The function being designated as an RPC target
00045  * @param fn_ret[in]   The return type of the function being designated as an
00046  *                     RPC target
00047  * @param __VA_ARGS__  The type of each parameter passed to the target
00048  *                     function. There can be up to 4 parameters in a target
00049  *                     function. Each parameter must be no more than uint32_t
00050  *                     in size. If the RPC target function accepts no
00051  *                     arguments, pass `void` here.
00052  */
00053 #define UVISOR_BOX_RPC_GATEWAY_SYNC(box_name, gw_name, fn_name, fn_ret, ...) \
00054     UVISOR_STATIC_ASSERT(sizeof(fn_ret) <= sizeof(uint32_t), gw_name ## _return_type_too_big); \
00055     _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK(gw_name, __VA_ARGS__) \
00056     _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER(fn_name, __VA_ARGS__) \
00057     /* Instanstiate the gateway. This gets resolved at link-time. */ \
00058     UVISOR_EXTERN TRPCGateway const gw_name ## _rpc_gateway = { \
00059         .ldr_pc   = LDR_PC_PC_IMM_OPCODE(__UVISOR_OFFSETOF(TRPCGateway, ldr_pc), \
00060                                          __UVISOR_OFFSETOF(TRPCGateway, function)), \
00061         .magic    = UVISOR_RPC_GATEWAY_MAGIC_SYNC, \
00062         .box_ptr  = (uint32_t) &box_name ## _cfg_ptr, \
00063         .function = (uint32_t) _sgw_sync_ ## fn_name, \
00064     }; \
00065     \
00066     /* Pointer to the gateway we just created. The pointer is located in a
00067      * discoverable linker section. */ \
00068     __attribute__((section(".keep.uvisor.rpc_gateway_ptr"))) \
00069     uint32_t const gw_name ## _rpc_gateway_ptr = (uint32_t) &gw_name ## _rpc_gateway; \
00070     \
00071     /* Declare the actual gateway. */ \
00072     UVISOR_EXTERN_C_BEGIN \
00073         fn_ret (*gw_name)(__VA_ARGS__) __attribute__((section(".rodata"))) = (fn_ret (*)(__VA_ARGS__)) ((uint32_t) &gw_name ## _rpc_gateway + 1); \
00074     UVISOR_EXTERN_C_END
00075 
00076 /** Asynchronous RPC Gateway
00077  *
00078  * This macro declares a new function pointer (with no name mangling) named
00079  * `gw_name` to perform a remote procedure call (RPC) to the target function
00080  * given by `fn_name`. RPCs are assembled into a read-only flash structure that
00081  * is read and validated by uVisor before performing the operation.
00082  *
00083  * Create function with following signature:
00084  * UVISOR_EXTERN uvisor_rpc_result_t gw_name(uint32_t a, uint32_t b);
00085  *
00086  * @param box_name[in] The name of the source box as declared in
00087  *                     `UVISOR_BOX_CONFIG`
00088  * @param gw_name[in]  The new, callable function pointer for performing RPC
00089  * @param fn_name[in]  The function being designated as an RPC target
00090  * @param fn_ret[in]   The return type of the function being designated as an
00091  *                     RPC target
00092  * @param __VA_ARGS__  The type of each parameter passed to the target
00093  *                     function. There can be up to 4 parameters in a target
00094  *                     function. Each parameter must be no more than uint32_t
00095  *                     in size. If the RPC target function accepts no
00096  *                     arguments, pass `void` here.
00097  */
00098 #define UVISOR_BOX_RPC_GATEWAY_ASYNC(box_name, gw_name, fn_name, fn_ret, ...) \
00099     UVISOR_STATIC_ASSERT(sizeof(fn_ret) <= sizeof(uint32_t), gw_name ## _return_type_too_big); \
00100     _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK(gw_name, __VA_ARGS__) \
00101     _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER(fn_name, __VA_ARGS__) \
00102     /* Instanstiate the gateway. This gets resolved at link-time. */ \
00103     UVISOR_EXTERN TRPCGateway const gw_name ## _rpc_gateway = { \
00104         .ldr_pc   = LDR_PC_PC_IMM_OPCODE(__UVISOR_OFFSETOF(TRPCGateway, ldr_pc), \
00105                                          __UVISOR_OFFSETOF(TRPCGateway, function)), \
00106         .magic    = UVISOR_RPC_GATEWAY_MAGIC_ASYNC, \
00107         .box_ptr  = (uint32_t) &box_name ## _cfg_ptr, \
00108         .function = (uint32_t) _sgw_async_ ## fn_name, \
00109     }; \
00110     \
00111     /* Pointer to the gateway we just created. The pointer is located in a
00112      * discoverable linker section. */ \
00113     __attribute__((section(".keep.uvisor.rpc_gateway_ptr"))) \
00114     uint32_t const gw_name ## _rpc_gateway_ptr = (uint32_t) &gw_name ## _rpc_gateway; \
00115     \
00116     /* Declare the actual gateway. */ \
00117     UVISOR_EXTERN_C_BEGIN \
00118         uvisor_rpc_result_t (*gw_name)(__VA_ARGS__) __attribute__((section(".rodata"))) = (uvisor_rpc_result_t (*)(__VA_ARGS__)) ((uint32_t) &gw_name ## _rpc_gateway + 1); \
00119     UVISOR_EXTERN_C_END
00120 
00121 #define _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK(gw_name, ...) \
00122     __UVISOR_BOX_MACRO(__VA_ARGS__, _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_4, \
00123                                     _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_3, \
00124                                     _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_2, \
00125                                     _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_1, \
00126                                     _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_0)(gw_name, __VA_ARGS__)
00127 
00128 #define _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_0(gw_name)
00129 
00130 #define _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_1(gw_name, p0_type) \
00131     UVISOR_STATIC_ASSERT(sizeof(p0_type) <= sizeof(uint32_t), gw_name ## _param_0_too_big);
00132 
00133 #define _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_2(gw_name, p0_type, p1_type) \
00134     UVISOR_STATIC_ASSERT(sizeof(p0_type) <= sizeof(uint32_t), gw_name ## _param_0_too_big); \
00135     UVISOR_STATIC_ASSERT(sizeof(p1_type) <= sizeof(uint32_t), gw_name ## _param_1_too_big);
00136 
00137 #define _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_3(gw_name, p0_type, p1_type, p2_type) \
00138     UVISOR_STATIC_ASSERT(sizeof(p0_type) <= sizeof(uint32_t), gw_name ## _param_0_too_big); \
00139     UVISOR_STATIC_ASSERT(sizeof(p1_type) <= sizeof(uint32_t), gw_name ## _param_1_too_big); \
00140     UVISOR_STATIC_ASSERT(sizeof(p2_type) <= sizeof(uint32_t), gw_name ## _param_2_too_big);
00141 
00142 #define _UVISOR_BOX_RPC_GATEWAY_ARG_CHECK_4(gw_name, p0_type, p1_type, p2_type, p3_type) \
00143     UVISOR_STATIC_ASSERT(sizeof(p0_type) <= sizeof(uint32_t), gw_name ## _param_0_too_big); \
00144     UVISOR_STATIC_ASSERT(sizeof(p1_type) <= sizeof(uint32_t), gw_name ## _param_1_too_big); \
00145     UVISOR_STATIC_ASSERT(sizeof(p2_type) <= sizeof(uint32_t), gw_name ## _param_2_too_big); \
00146     UVISOR_STATIC_ASSERT(sizeof(p3_type) <= sizeof(uint32_t), gw_name ## _param_3_too_big);
00147 
00148 #define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER(fn_name, ...) \
00149     __UVISOR_BOX_MACRO(__VA_ARGS__, _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_4, \
00150                                     _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_3, \
00151                                     _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_2, \
00152                                     _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_1, \
00153                                     _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_0)(fn_name, __VA_ARGS__)
00154 
00155 #define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_0(fn_name, ...) \
00156     static uint32_t _sgw_sync_ ## fn_name(void) \
00157     { \
00158         TFN_Ptr fp = (TFN_Ptr) fn_name; \
00159         return rpc_fncall_sync(0, 0, 0, 0, fp); \
00160     }
00161 
00162 #define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_1(fn_name, ...) \
00163     static uint32_t _sgw_sync_ ## fn_name(uint32_t p0) \
00164     { \
00165         TFN_Ptr fp = (TFN_Ptr) fn_name; \
00166         return rpc_fncall_sync(p0, 0, 0, 0, fp); \
00167     }
00168 
00169 #define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_2(fn_name, ...) \
00170     static uint32_t _sgw_sync_ ## fn_name(uint32_t p0, uint32_t p1) \
00171     { \
00172         TFN_Ptr fp = (TFN_Ptr) fn_name; \
00173         return rpc_fncall_sync(p0, p1, 0, 0, fp); \
00174     }
00175 
00176 #define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_3(fn_name, ...) \
00177     static uint32_t _sgw_sync_ ## fn_name(uint32_t p0, uint32_t p1, uint32_t p2) \
00178     { \
00179         TFN_Ptr fp = (TFN_Ptr) fn_name; \
00180         return rpc_fncall_sync(p0, p1, p2, 0, fp); \
00181     }
00182 
00183 #define _UVISOR_BOX_RPC_GATEWAY_SYNC_CALLER_4(fn_name, ...) \
00184     static uint32_t _sgw_sync_ ## fn_name(uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3) \
00185     { \
00186         TFN_Ptr fp = (TFN_Ptr) fn_name; \
00187         return rpc_fncall_sync(p0, p1, p2, p3, fp); \
00188     }
00189 
00190 #define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER(fn_name, ...) \
00191     __UVISOR_BOX_MACRO(__VA_ARGS__, _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_4, \
00192                                     _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_3, \
00193                                     _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_2, \
00194                                     _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_1, \
00195                                     _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_0)(fn_name, __VA_ARGS__)
00196 
00197 #define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_0(fn_name, ...) \
00198     static uvisor_rpc_result_t _sgw_async_ ## fn_name(void) \
00199     { \
00200         TFN_Ptr fp = (TFN_Ptr) fn_name; \
00201         return rpc_fncall_async(0, 0, 0, 0, fp); \
00202     }
00203 
00204 #define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_1(fn_name, ...) \
00205     static uvisor_rpc_result_t _sgw_async_ ## fn_name(uint32_t p0) \
00206     { \
00207         TFN_Ptr fp = (TFN_Ptr) fn_name; \
00208         return rpc_fncall_async(p0, 0, 0, 0, fp); \
00209     }
00210 
00211 #define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_2(fn_name, ...) \
00212     static uvisor_rpc_result_t _sgw_async_ ## fn_name(uint32_t p0, uint32_t p1) \
00213     { \
00214         TFN_Ptr fp = (TFN_Ptr) fn_name; \
00215         return rpc_fncall_async(p0, p1, 0, 0, fp); \
00216     }
00217 
00218 #define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_3(fn_name, ...) \
00219     static uvisor_rpc_result_t _sgw_async_ ## fn_name(uint32_t p0, uint32_t p1, uint32_t p2) \
00220     { \
00221         TFN_Ptr fp = (TFN_Ptr) fn_name; \
00222         return rpc_fncall_async(p0, p1, p2, 0, fp); \
00223     }
00224 
00225 #define _UVISOR_BOX_RPC_GATEWAY_ASYNC_CALLER_4(fn_name, ...) \
00226     static uvisor_rpc_result_t _sgw_async_ ## fn_name(uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3) \
00227     { \
00228         TFN_Ptr fp = (TFN_Ptr) fn_name; \
00229         return rpc_fncall_async(p0, p1, p2, p3, fp); \
00230     }
00231 
00232 /* This function is private to uvisor-lib, but needs to be publicly visible for
00233  * the RPC gateway creation macros to work. */
00234 UVISOR_EXTERN uint32_t rpc_fncall_sync(uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3, const TFN_Ptr fn);
00235 
00236 /* This function is private to uvisor-lib, but needs to be publicly visible for
00237  * the RPC gateway creation macros to work. */
00238 UVISOR_EXTERN uvisor_rpc_result_t rpc_fncall_async(uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3, const TFN_Ptr fn);
00239 
00240 #endif /* __UVISOR_API_RPC_GATEWAY_H__ */