1/* 2 * Copyright 2016, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(D61_BSD) 11 */ 12 13/** 14 * @file rpc.h 15 * @date Fri 09 Aug 2013 13:00:56 EST 16 * 17 * @brief seL4 CIDL RPC Backend Interface 18 * 19 * This library provides the backend which the code generated from CIDL - Simple C IDL compiler 20 * uses in order to work. This library must deal with basic serialisation / deserialisation, 21 * manage basic client state on server side, and manage the communication channel in between. 22 * The CIDL generated code expects this library to be there. 23 * 24 * NOTE: All of the implementations here may _NOT_ themselves send RPCs, with few exception. 25 * Remember that if your printf involves an IPC to a server, this means no printf unless you 26 * use another IPC buffer. Likewise with malloc. 27 */ 28 29#ifndef _REFOS_RPC_H_ 30#define _REFOS_RPC_H_ 31 32#include <stdio.h> 33#include <stdint.h> 34#include <stdlib.h> 35#include <stdbool.h> 36#include <string.h> 37#include <assert.h> 38 39/** 40 * Maximum number of tracked objects for a single RPC call. Shouldn't need to be too long unless 41 * you have functions which take a lot of arguments. 42 */ 43#define RPC_MAX_TRACKED_OBJS 32 44 45// ------------------------------------------------------------------------------------------------- 46// ------------------------------------------ IDL Declarations ------------------------------------- 47// ------------------------------------------------------------------------------------------------- 48 49#define _SEL4_ 50#ifdef _SEL4_ 51 #include <sel4/sel4.h> 52 #define ENDPT seL4_CPtr 53 typedef char byte; 54 typedef seL4_CPtr cptr; 55 typedef seL4_CPtr cslot; 56 typedef seL4_CPtr seL4_CSlot; 57 typedef seL4_MessageInfo_t msginfo_t; 58#else 59 #error "Unimplemented backend." 60#endif 61 62// ------------------------------------------------------------------------------------------------- 63// ------------------------------------------- RPC Helper ------------------------------------------ 64// ------------------------------------------------------------------------------------------------- 65 66/** 67 * A helper function to allocate & manage the allocated memory for an RPC. Works like cstdlib 68 * malloc(). 69 * @param[in] sz Size of memory to allocate in bytes. 70 * @return Pointer to allocated memory. 71 */ 72void* rpc_malloc(size_t sz); 73 74/** 75 * Free the given object at memory address. Works like cstdlib free(). 76 * @param[in] addr The address ti free. 77 */ 78void rpc_free(void *addr); 79 80/** 81 * Use the given cslot as the destination slot for cap transfer. If this isn't called explicitly, 82 * the provided client/server interface below should automatically call this with a default cslot. 83 * @param[in] recv_cslot CSpace slot to use to recieve caps. 84 */ 85void rpc_setup_recv(cslot recv_cslot); 86 87/** 88 * Use the given cslot as the destination slot for cap transfer. This version does not assume 89 * default cspace. 90 * @param[in] cspace Root of the thread's CSpace. 91 * @param[in] recv_cslot Address of CSpace slot to use to recieve caps. 92 * @param[in] depth Number of bits of the capability address to be translated. 93 */ 94void rpc_setup_recv_cspace(seL4_CPtr cspace, seL4_CPtr recv_cslot, seL4_Word depth); 95 96/** 97 * Resets the data pointers (e.g. current IPC MR number and cap number) in the client's send buffer. 98 * @param[in] cl Generic reference to caller client state structure (optional). 99 */ 100void rpc_reset_contents(void *cl); 101 102// ------------------------------------------------------------------------------------------------- 103// ---------------------------------------------- Client RPC --------------------------------------- 104// ------------------------------------------------------------------------------------------------- 105 106/** 107 * Initialise client state, ready for a new RPC call. 108 * @param[in] name_str Name of call being initiated (for easier debugging, may ignore this). 109 * @param[in] label The call enum label which server will use to identify which call. 110 */ 111void rpc_init(const char* name_str, int32_t label); 112 113/** 114 * Set a custom destination endpoint. By default the destination endpoint used is the one specified 115 * in the interface XML file. To support interfaces which make sense to be served by multiple 116 * servers, the IDL param mode='connect_ep' is used. CIDL will see this flag and call this function 117 * with the marked parameter. 118 * @param[in] dest Destination server endpoint that the next rpc_call_server will invoke. 119 */ 120void rpc_set_dest(ENDPT dest); 121 122/** 123 * Add a new integer type variable to the end of the current global RPC packet. 124 * @param[in] v Value of integer to add. 125 */ 126void rpc_push_uint(uint32_t v); 127 128/** 129 * Add a new C string type variable to the end of the current global RPC packet. 130 * @param[in] v String to add. 131 */ 132void rpc_push_str(const char* v); 133 134/** 135 * Add a new generic buffer object to the end of the current global RPC packet. 136 * @param[in] v Pointer to buffer obj to add. 137 * @param[in] sz Size of the buffer obj in bytes. 138 */ 139void rpc_push_buf(void* v, size_t sz); 140 141/** 142 * Add a new array of generic buffer objects to the end of the current global RPC packet. 143 * @param[in] v Pointer to array of buffer objects to add. 144 * @param[in] sz Size of a single buffer obj in bytes. 145 * @param[in] count Number of objects in v. 146 */ 147void rpc_push_buf_array(void* v, size_t sz, uint32_t count); 148 149/** 150 * Add a new capablity to the end of the current global RPC packet. 151 * @param[in] v Capability to add. 152 */ 153void rpc_push_cptr(ENDPT v); 154 155/** 156 * Read the next integer type variable from current global RPC packet. 157 * @return Value of next integer. 158 */ 159uint32_t rpc_pop_uint(); 160 161/** 162 * Read the next C string from current global RPC packet. 163 * NOTE: Using a string as output is not safe in standard C function calls, and likewise it is also 164 * not a good idea at all for RPC calls, and is prone to buffer overflow. 165 * @param[out] v Pointer to allocated string to read into. 166 */ 167void rpc_pop_str(char* v); 168 169/** 170 * Read the next generic buffer object from current global RPC packet. 171 * @param[out] v Pointer to allocated buffer object to read into. 172 * @param[in] sz Size of generic object to read in bytes. 173 */ 174void rpc_pop_buf(void* v, size_t sz); 175 176/** 177 * Read the next capability from current global RPC packet. Note that this function may choose to 178 * copy out the recieved cap from the recieve slot in this function and leave an empty stub in 179 * rpc_copyout_cptr, or alternatively it may just simply return the recieve slot here and then 180 * implement copyout in rpc_copyout_cptr. See @ref rpc_copyout_cptr. 181 * @return CSpace pointer to recieved capability. 182 */ 183ENDPT rpc_pop_cptr(); 184 185/** 186 * Read the next buffer object array from current global RPC packet. 187 * @param[out] v Pointer to allocated buffer object to read into. 188 * @param[in] sz Size of generic object to read in bytes. 189 * @param[in] count Max. number of objects in array (only used for checking). 190 */ 191void rpc_pop_buf_array(void* v, size_t sz, uint32_t count); 192 193/** 194 * Invoke the server. The destination endpoint may be automatically determined from the label for 195 * simplicity, unless overridden by a call to @ref rpc_set_dest. 196 * @return 0 on success, non-zero otherwise. 197 */ 198int rpc_call_server(); 199 200/** 201 * Finish up the current client RPC call and release all allocated objects. 202 */ 203void rpc_release(); 204 205/** 206 * Allocate a new cslot, and then copy out the given recieved capabiliy from the recieve cslot to a 207 * new cslot. This function exists to optionally separate @ref rpc_pop_cptr from allocating a new 208 * cslot. This function useful in the case where allocating a cslot itself requires an RPC call, 209 * as RPC calling from @ref rpc_pop_cptr may result in munging the IPC buffer. This function may need 210 * to temporarily copy the given cap to an empty slot, in order to IPC to allocate a new cslot. 211 * @param[in] v CSpace pointer to capability to copy out. 212 * @return CSpace pointer to copied out capability. 213 */ 214ENDPT rpc_copyout_cptr(ENDPT v); 215 216// ------------------------------------------------------------------------------------------------- 217// ------------------------------------------- Server RPC ------------------------------------------ 218// ------------------------------------------------------------------------------------------------- 219 220/** 221 * Helper structure which stores the basic state needed for an RPC server to manage a single RPC 222 * client. Note that the rpc_sv server interface here passes generic void* as client struct and 223 * does not assume you use this struct, so this struct is provided for convenience and using this 224 * struct is optional. The default implementation assumes the void *cl parameters to be 225 * a valid rpc_client_state_t* object; 226 * 227 * A good way to use this structure is to 'inherit' it by putting it as the first element of your 228 * own client structure. Then you may pointer case freely between your own client structure and a 229 * rpc_client_state_t. 230 */ 231typedef struct rpc_client_state_s { 232 msginfo_t minfo; 233 void* obj[RPC_MAX_TRACKED_OBJS]; 234 uint32_t num_obj; 235 236 bool skip_reply; 237 ENDPT reply; 238 239 void *userptr; 240} rpc_client_state_t; 241 242/** 243 * A simple buffer structure. Buffer array (pointer / length combinations in C) are converted to 244 * this on server side. 245 */ 246typedef struct rpc_buffer_s { 247 void *data; 248 uint32_t count; 249} rpc_buffer_t; 250 251/** 252 * Initialise server's client state, ready for a new RPC call. 253 * @param[in] cl Generic reference to caller client state structure. 254 */ 255void rpc_sv_init(void *cl); 256 257/** 258 * Read next integer from recieved RPC packet. 259 * @param[in] cl Generic reference to caller client state structure. 260 * @return The next integer in packet. 261 */ 262uint32_t rpc_sv_pop_uint(void *cl); 263 264/** 265 * Read next string from recieved RPC packet. 266 * @param[in] cl Generic reference to caller client state structure. 267 * @return The allocated and read string. 268 */ 269char* rpc_sv_pop_str(void *cl); 270 271/** 272 * Read next buffer object from recieved RPC packet. 273 * @param[in] cl Generic reference to caller client state structure. 274 * @param[out] v Allocated buffer obj to read into. 275 * @param[in] sz Size of buffer object in bytes. 276 */ 277void rpc_sv_pop_buf(void *cl, void *v, size_t sz); 278 279/** 280 * Read next array of buffer objects from recieved RPC packet. 281 * @param[in] cl Generic reference to caller client state structure. 282 * @param[in] sz Size of a single buffer object in bytes. 283 * @return The allocated and read buffer obj array. 284 */ 285rpc_buffer_t rpc_sv_pop_buf_array(void *cl, size_t sz); 286 287/** 288 * Read next capability from recieved RPC packet. For an unwrapped capability, the unwrapped badge 289 * value is returned from this function. In the case of a transferred cap, it is _NOT_ copied out 290 * here (i.e. the value of recv_cslot in given @ref rpc_setup_recv is simply returned. It is up to 291 * the server handler to copy out given transferred caps. It is also up to the server handler to 292 * know (and check) which caps are unwrapped and which are transferred. 293 * @param[in] cl Generic reference to caller client state structure. 294 * @return The next capability. 295 */ 296ENDPT rpc_sv_pop_cptr(void *cl); 297 298/** 299 * Add a new integer variable to the end of the current global RPC packet. 300 * @param[in] cl Generic reference to caller client state structure. 301 * @param[in] v String to add. 302 */ 303void rpc_sv_push_uint(void *cl, uint32_t v); 304 305/** 306 * Add a new buffer object to the end of the current global RPC packet. 307 * @param[in] cl Generic reference to caller client state structure. 308 * @param[in] v Pointer to buffer object to add. 309 * @param[in] sz size of the given buffer object in bytes. 310 */ 311void rpc_sv_push_buf(void *cl, void* v, size_t sz); 312 313/** 314 * Add a capability to the end of the current global RPC packet. 315 * @param[in] cl Generic reference to caller client state structure. 316 * @param[in] v CPtr to capability to add and transfer. 317 */ 318void rpc_sv_push_cptr(void *cl, ENDPT v); 319 320/** 321 * Add an array of objects to the end of the current global RPC packet. 322 * @param[in] cl Generic reference to caller client state structure. 323 * @param[in] v A value rpc_buffer_t containing pointer to buffer and count info. 324 * @param[in] sz size of the a single object in bytes. 325 */ 326void rpc_sv_push_buf_array(void *cl, rpc_buffer_t v, size_t sz); 327 328/** 329 * Reply to the client RPC. Depending on whether the reply is immediate or saved-first then replied 330 * later, this function should send to the correct corresponding reply endpoint in either case. 331 * @param[in] cl Generic reference to caller client state structure. 332 */ 333void rpc_sv_reply(void* cl); 334 335/** 336 * End the current RPC for the given client caller and release all tis allocated objects. 337 * @param[in] cl Generic reference to caller client state structure. 338 */ 339void rpc_sv_release(void *cl); 340 341/** 342 * Optionally save the current client RPC reply cap to reply later. A default weak definition is 343 * provided, and servers may want to override this. If this function returns True, the generated 344 * reply_*() functions are not called and must be invoked manually by the server. Useful 345 * for implementing server-side asynchronous syscalls which providing a synchronous syscall 346 * interface to clients. You may RPC from this function. 347 * @param[in] cl Generic reference to caller client state structure. 348 * @return False to reply immediately, True if the reply endpoint was saved. 349 */ 350bool rpc_sv_save_reply(void *cl); 351 352/** 353 * Retrieve the saved reply endpoint if it has been saved, or 0 otherwise. 354 * @param[in] cl Generic reference to caller client state structure. 355 * @return saved reply endpoint if it was saved, 0 otherwise to reply immediately. 356 */ 357ENDPT rpc_sv_get_reply_endpoint(void *cl); 358 359void rpc_sv_track_obj(void* cl, void* addr); 360 361void rpc_sv_free_tracked_objs(void* cl); 362 363bool rpc_sv_skip_reply(void *cl); 364 365#endif /* _REFOS_RPC_H_ */ 366 367